Decompiled source of Mimics v1.2.0

TFS_Mimics.dll

Decompiled a week ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Cryptography;
using System.Security.Permissions;
using System.Text;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using BepInEx.Logging;
using ExitGames.Client.Photon;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using Photon.Pun;
using Photon.Realtime;
using Photon.Voice;
using RepoSteamNetworking.API;
using RepoSteamNetworking.Networking;
using RepoSteamNetworking.Networking.Serialization;
using RepoSteamNetworking.Networking.Unity;
using Steamworks;
using Steamworks.Data;
using TFS_Mimics.patches;
using UnityEngine;
using UnityEngine.Audio;
using UnityEngine.Networking;
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: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("0.0.0.0")]
[module: UnverifiableCode]
[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 TFS_Mimics
{
	public static class MimicsAPI
	{
		private sealed class PendingEntry
		{
			public string ModGuid;

			public string ModDisplayName;

			public AudioClip Clip;
		}

		private static readonly List<PendingEntry> _pending = new List<PendingEntry>();

		private static readonly object _lock = new object();

		public static void RegisterClip(string modGuid, string modDisplayName, AudioClip clip)
		{
			if (string.IsNullOrWhiteSpace(modGuid))
			{
				throw new ArgumentException("modGuid must not be empty.", "modGuid");
			}
			if ((Object)(object)clip == (Object)null)
			{
				throw new ArgumentNullException("clip");
			}
			string modDisplayName2 = (string.IsNullOrWhiteSpace(modDisplayName) ? modGuid : modDisplayName);
			lock (_lock)
			{
				_pending.Add(new PendingEntry
				{
					ModGuid = modGuid,
					ModDisplayName = modDisplayName2,
					Clip = clip
				});
			}
			TFS_Mimics.Instance?.ConsumeApiClips();
		}

		public static void RegisterClips(string modGuid, string modDisplayName, IEnumerable<AudioClip> clips)
		{
			if (clips == null)
			{
				throw new ArgumentNullException("clips");
			}
			foreach (AudioClip clip in clips)
			{
				if ((Object)(object)clip != (Object)null)
				{
					RegisterClip(modGuid, modDisplayName, clip);
				}
			}
		}

		internal static List<(string modGuid, string modDisplayName, AudioClip clip)> TakePending()
		{
			lock (_lock)
			{
				if (_pending.Count == 0)
				{
					return null;
				}
				List<(string, string, AudioClip)> list = new List<(string, string, AudioClip)>(_pending.Count);
				foreach (PendingEntry item in _pending)
				{
					list.Add((item.ModGuid, item.ModDisplayName, item.Clip));
				}
				_pending.Clear();
				return list;
			}
		}
	}
	[BepInPlugin("TFS_Mimics", "TFS_Mimics", "1.2.0")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	public class Plugin : BaseUnityPlugin
	{
		internal static ManualLogSource PluginLogger;

		private static Harmony harmony;

		public static ConfigEntry<bool> configDebugVerbose;

		public static ConfigEntry<string> configDebugMenuKey;

		public static ConfigEntry<int> configVoiceVolume;

		public static ConfigEntry<int> configPlaybackNearRadius;

		public static ConfigEntry<int> configMinDelay;

		public static ConfigEntry<int> configMaxDelay;

		public static ConfigEntry<bool> configHearYourself;

		public static ConfigEntry<bool> configFilterEnabled;

		public static ConfigEntry<bool> configPlaybackVoiceFilterEnabled;

		public static ConfigEntry<bool> configSmartDirector;

		public static ConfigEntry<bool> configEventDeath;

		public static ConfigEntry<bool> configEventHurt;

		public static ConfigEntry<bool> configEventSpotted;

		public static ConfigEntry<bool> configEventBreak;

		public static ConfigEntry<bool> configEventHeadTalk;

		public static ConfigEntry<bool> configEventPickup;

		public static ConfigEntry<int> configSamplingRate;

		public static ConfigEntry<bool> configPersistAudioCache;

		public static ConfigEntry<int> configPersistMaxFilesPerPlayer;

		public static ConfigEntry<int> configNormalizeTarget;

		public static ConfigEntry<int> configVadSensitivity;

		public static ConfigEntry<bool> configShowSetupWizard;

		public static ConfigEntry<int> configMaxClipsInMemory;

		public static readonly Dictionary<string, ConfigEntry<bool>> enemyConfigEntries = new Dictionary<string, ConfigEntry<bool>>();

		public static KeyCode GetDebugMenuKey()
		{
			//IL_0052: Unknown result type (might be due to invalid IL or missing references)
			//IL_0046: Unknown result type (might be due to invalid IL or missing references)
			string value = configDebugMenuKey.Value;
			if (value == "Enter")
			{
				return (KeyCode)13;
			}
			if (value.Length == 1 && char.IsDigit(value[0]) && Enum.TryParse<KeyCode>("Alpha" + value, out KeyCode result))
			{
				return result;
			}
			if (Enum.TryParse<KeyCode>(value, out KeyCode result2))
			{
				return result2;
			}
			return (KeyCode)289;
		}

		private void Awake()
		{
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0048: Expected O, but got Unknown
			//IL_00b4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00be: Expected O, but got Unknown
			//IL_00ea: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f4: Expected O, but got Unknown
			//IL_011d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0127: Expected O, but got Unknown
			//IL_0150: Unknown result type (might be due to invalid IL or missing references)
			//IL_015a: Expected O, but got Unknown
			//IL_01a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ad: Expected O, but got Unknown
			//IL_01d9: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e3: Expected O, but got Unknown
			//IL_020f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0219: Expected O, but got Unknown
			//IL_035e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0368: Expected O, but got Unknown
			//IL_039b: Unknown result type (might be due to invalid IL or missing references)
			//IL_03a5: Expected O, but got Unknown
			//IL_03cf: Unknown result type (might be due to invalid IL or missing references)
			//IL_03d9: Expected O, but got Unknown
			PluginLogger = ((BaseUnityPlugin)this).Logger;
			PluginLogger.LogInfo((object)"Plugin TFS_Mimics loaded.");
			configVoiceVolume = ((BaseUnityPlugin)this).Config.Bind<int>("General", "Volume", 30, new ConfigDescription("Volume of mimic voices (percent).", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 100), Array.Empty<object>()));
			configHearYourself = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "Hear Yourself?", true, "If false, only other clients hear mimic playback.");
			configPersistAudioCache = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "Persist Audio Cache", false, "If true, received mimic audio clips are saved to disk and loaded on world entry.");
			configMaxClipsInMemory = ((BaseUnityPlugin)this).Config.Bind<int>("General", "Max Clips In Memory Per Player", 40, new ConfigDescription("How many recordings per player are kept loaded during a session (oldest unpinned are dropped from memory, not from disk). Keeps long sessions light.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(5, 500), Array.Empty<object>()));
			configPersistMaxFilesPerPlayer = ((BaseUnityPlugin)this).Config.Bind<int>("General", "Persist Max Files Per Player", 100, new ConfigDescription("Maximum number of persisted recordings to keep per player folder.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 5000), Array.Empty<object>()));
			configNormalizeTarget = ((BaseUnityPlugin)this).Config.Bind<int>("General", "Normalize Target", 85, new ConfigDescription("Peak normalization target for voice and custom audio (0 = off, 100 = 0 dBFS).", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 100), Array.Empty<object>()));
			configVadSensitivity = ((BaseUnityPlugin)this).Config.Bind<int>("General", "Voice Detection Sensitivity", 85, new ConfigDescription("How easily your voice starts a recording (higher = quieter speech is captured, but more background noise too).", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 100), Array.Empty<object>()));
			configShowSetupWizard = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "Show Setup Wizard", false, "Open the microphone setup wizard on the main menu. Turns itself off once the setup is saved or skipped.");
			configPlaybackNearRadius = ((BaseUnityPlugin)this).Config.Bind<int>("Host Only", "Playback Near Radius", 15, new ConfigDescription("Preferred radius around local player for selecting a mimic playback enemy.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(5, 100), Array.Empty<object>()));
			configMinDelay = ((BaseUnityPlugin)this).Config.Bind<int>("Host Only", "MinDelay", 10, new ConfigDescription("Minimum delay before record/play.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 300), Array.Empty<object>()));
			configMaxDelay = ((BaseUnityPlugin)this).Config.Bind<int>("Host Only", "MaxDelay", 20, new ConfigDescription("Maximum delay before record/play.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(5, 600), Array.Empty<object>()));
			configPlaybackVoiceFilterEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("Host Only", "Playback Voice Filters Enabled", true, "If false, playback never applies pitch/alien voice filters.");
			configSmartDirector = ((BaseUnityPlugin)this).Config.Bind<bool>("Host Only", "Smart Director", true, "Pick voices, enemies and listeners by context (who can see whom, who is far or dead, what was played recently) instead of at random.");
			configEventDeath = ((BaseUnityPlugin)this).Config.Bind<bool>("Host Only", "Event: Player Death", true, "Some time after a player dies, an enemy near the body calls out with their voice.");
			configEventHurt = ((BaseUnityPlugin)this).Config.Bind<bool>("Host Only", "Event: Player Hurt", true, "Shortly after a player gets hurt, nearby teammates hear their voice from an enemy.");
			configEventSpotted = ((BaseUnityPlugin)this).Config.Bind<bool>("Host Only", "Event: Enemy Spotted Player", true, "An enemy that spotted a player tries to lure them with another teammate's voice.");
			configEventBreak = ((BaseUnityPlugin)this).Config.Bind<bool>("Host Only", "Event: Valuable Broken", true, "After a valuable is damaged, an enemy nearby reacts with the voice of whoever held it.");
			configEventHeadTalk = ((BaseUnityPlugin)this).Config.Bind<bool>("Host Only", "Event: Head Grabber Talks", true, "While a Head Grabber carries a dead player's head, the head calls out with its owner's voice (and screams when the grabber attacks).");
			configEventPickup = ((BaseUnityPlugin)this).Config.Bind<bool>("Host Only", "Event: Valuable Picked Up", true, "Sometimes, after a player grabs a valuable worth $200+, a hidden enemy nearby talks to them with a teammate's voice.");
			configDebugVerbose = ((BaseUnityPlugin)this).Config.Bind<bool>("Debug", "Verbose Logging", false, "Enable very detailed debug logs for the whole mimic pipeline.");
			configDebugMenuKey = ((BaseUnityPlugin)this).Config.Bind<string>("Debug", "Menu Keybind", "F8", new ConfigDescription("Keybind to open the Mimics debug menu in-game (UnityEngine.KeyCode name, e.g. F8, Insert, Keypad5). Can be rebound by key press in the debug menu Settings tab.", (AcceptableValueBase)null, Array.Empty<object>()));
			configSamplingRate = ((BaseUnityPlugin)this).Config.Bind<int>("Experimental", "Sampling Rate", 48000, new ConfigDescription("Microphone/sample rate.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(16000, 48000), Array.Empty<object>()));
			configFilterEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("Filter", "Filter Enabled?", false, "Enable per-enemy mimic filter.");
			harmony = new Harmony("TFS_Mimics");
			SteamNetworkingCompat.Apply(harmony);
			RepoSteamNetwork.RegisterPacket<MimicsAudioPacket>();
			RepoSteamNetwork.AddCallback<MimicsAudioPacket>((Action<MimicsAudioPacket>)TFS_Mimics.OnMimicsAudioPacketReceived);
			RepoSteamNetwork.RegisterPacket<SoundReadyPacket>();
			RepoSteamNetwork.AddCallback<SoundReadyPacket>((Action<SoundReadyPacket>)TFS_Mimics.OnSoundReadyPacketReceived);
			RepoSteamNetwork.RegisterPacket<SoundForgetPacket>();
			RepoSteamNetwork.AddCallback<SoundForgetPacket>((Action<SoundForgetPacket>)TFS_Mimics.OnSoundForgetPacketReceived);
			RepoSteamNetwork.RegisterPacket<CustomSoundManifestPacket>();
			RepoSteamNetwork.AddCallback<CustomSoundManifestPacket>((Action<CustomSoundManifestPacket>)TFS_Mimics.OnCustomSoundManifestReceived);
			RepoSteamNetwork.RegisterPacket<SyncPlayCommandPacket>();
			RepoSteamNetwork.AddCallback<SyncPlayCommandPacket>((Action<SyncPlayCommandPacket>)TFS_Mimics.OnSyncPlayCommandReceived);
			harmony.PatchAll();
			EnemyDirectorStartPatch.Initialize(((BaseUnityPlugin)this).Config);
			EnsureDataFolders();
			MimicsSetupWizard.Create();
		}

		private void EnsureDataFolders()
		{
			string text = Path.Combine(Paths.BepInExRootPath, "plugins", "ToxesFoxes-Mimics");
			Directory.CreateDirectory(Path.Combine(text, "audio-cache"));
			string text2 = Path.Combine(text, "custom-audio");
			Directory.CreateDirectory(text2);
			string path = Path.Combine(text2, "HOW TO USE.txt");
			if (!File.Exists(path))
			{
				File.WriteAllText(path, "=== Mimics — Custom Audio ===\r\n\r\nDrop .mp3 or .wav files into this folder.\r\nThey will be loaded automatically when you join a level.\r\n\r\nCustom clips are played through nearby enemies just like recorded\r\nplayer voices, but without any online-player restriction.\r\n\r\nTips:\r\n  - Mono or stereo files both work.\r\n  - Volume is normalized automatically (configurable in Settings tab).\r\n  - Use the 'Reload Custom' button in the Debug HUD (Cache tab) to\r\n    reload files without restarting the game.\r\n  - This file (HOW TO USE.txt) is ignored by the mod.\r\n");
			}
			PluginLogger.LogInfo((object)("[Mimics] Data folders ready: " + text));
		}
	}
	internal static class AudioFilters
	{
		internal static readonly (string Key, Func<float[], int, float[]> Apply)[] Registry = new(string, Func<float[], int, float[]>)[6]
		{
			("pitch_down", (float[] s, int sr) => ApplyPitchShift(s, 0.5f)),
			("pitch_up", (float[] s, int sr) => ApplyPitchShift(s, 1.2f)),
			("alien", ApplyAlienFilter),
			("teeth_bot", ApplyTeethBotFilter),
			("slow_mouth", ApplySlowMouthFilter),
			("tranq", ApplyTranqFilter)
		};

		internal static int Count => Registry.Length;

		internal static float[] ApplyAlienFilter(float[] samples, int sampleRate)
		{
			float[] array = new float[samples.Length];
			int num = (int)((float)sampleRate * 8f / 1000f) + 2;
			float[] array2 = new float[num];
			int num2 = 0;
			for (int i = 0; i < samples.Length; i++)
			{
				float num3 = (float)i / (float)sampleRate;
				int num4 = (int)((float)sampleRate * 8f / 1000f);
				float num5 = (Mathf.Sin(8.16814f * num3) + 1f) * 0.5f;
				int num6 = (int)((float)num4 * num5) + 1;
				int num7 = (num2 - num6 + num) % num;
				float num8 = (array2[num2] = samples[i]);
				num2 = (num2 + 1) % num;
				float num9 = Mathf.Round(array2[num7] * 1024f) / 1024f;
				array[i] = Mathf.Clamp(num8 * 0.55f + num9 * 0.45f, -1f, 1f);
			}
			return array;
		}

		internal static float[] Apply(float[] samples, int filterIndex, int sampleRate)
		{
			if (filterIndex < 0 || filterIndex >= Registry.Length)
			{
				return samples;
			}
			return Registry[filterIndex].Apply(samples, sampleRate);
		}

		internal static float[] ApplyLowPassFilter(float[] samples, float cutoffFreq, int sampleRate)
		{
			float[] array = new float[samples.Length];
			if (samples.Length == 0)
			{
				return array;
			}
			float num = ((sampleRate > 0) ? ((float)sampleRate) : 48000f);
			float num2 = Mathf.Tan(MathF.PI * cutoffFreq / num);
			float num3 = num2 * num2;
			float num4 = MathF.Sqrt(2f) * num2;
			float num5 = 1f / (num3 + num4 + 1f);
			float num6 = num3 * num5;
			float num7 = 2f * num3 * num5;
			float num8 = num3 * num5;
			float num9 = 2f * (num3 - 1f) * num5;
			float num10 = (num3 - num4 + 1f) * num5;
			float num11 = 0f;
			float num12 = 0f;
			float num13 = 0f;
			float num14 = 0f;
			for (int i = 0; i < samples.Length; i++)
			{
				float num15 = samples[i];
				float num16 = num6 * num15 + num7 * num11 + num8 * num12 - num9 * num13 - num10 * num14;
				num12 = num11;
				num11 = num15;
				num14 = num13;
				num13 = num16;
				array[i] = Mathf.Clamp(num16, -1f, 1f);
			}
			return array;
		}

		internal static void NormalizeSamples(float[] samples)
		{
			if (samples == null || samples.Length == 0)
			{
				return;
			}
			int num = ((Plugin.configNormalizeTarget != null) ? Plugin.configNormalizeTarget.Value : 85);
			if (num <= 0)
			{
				return;
			}
			float num2 = Mathf.Clamp((float)num / 100f, 0.001f, 1f);
			float num3 = 0f;
			for (int i = 0; i < samples.Length; i++)
			{
				float num4 = Mathf.Abs(samples[i]);
				if (num4 > num3)
				{
					num3 = num4;
				}
			}
			if (num3 < 0.0001f)
			{
				return;
			}
			float num5 = num2 / num3;
			if (!(num5 >= 1f) || !(num3 >= num2))
			{
				for (int j = 0; j < samples.Length; j++)
				{
					samples[j] *= num5;
				}
			}
		}

		internal static float[] ApplyPitchShift(float[] samples, float pitchFactor)
		{
			int num = (int)((float)samples.Length / pitchFactor);
			float[] array = new float[num];
			for (int i = 0; i < num; i++)
			{
				float num2 = (float)i * pitchFactor;
				int num3 = (int)num2;
				float num4 = num2 - (float)num3;
				float num5 = ((num3 > 0) ? samples[num3 - 1] : samples[0]);
				float num6 = ((num3 < samples.Length) ? samples[num3] : 0f);
				float num7 = ((num3 + 1 < samples.Length) ? samples[num3 + 1] : 0f);
				float num8 = ((num3 + 2 < samples.Length) ? samples[num3 + 2] : 0f);
				float num9 = -0.5f * num5 + 1.5f * num6 - 1.5f * num7 + 0.5f * num8;
				float num10 = num5 - 2.5f * num6 + 2f * num7 - 0.5f * num8;
				float num11 = -0.5f * num5 + 0.5f * num7;
				float num12 = num6;
				array[i] = Mathf.Clamp(((num9 * num4 + num10) * num4 + num11) * num4 + num12, -1f, 1f);
			}
			return array;
		}

		internal static float[] ApplySlowMouthFilter(float[] samples, int sampleRate)
		{
			samples = ApplyLowPassFilter(samples, 3000f, sampleRate);
			return ApplyPitchShift(samples, 0.75f);
		}

		internal static float[] ApplyTeethBotFilter(float[] samples, int sampleRate)
		{
			samples = ApplyPitchShift(samples, 1.25f);
			float[] array = new float[samples.Length];
			for (int i = 0; i < samples.Length; i++)
			{
				float num = (float)i / (float)sampleRate;
				float num2 = (Mathf.Sin(MathF.PI * 20f * num) + 1f) * 0.5f;
				float num3 = 1f - 0.25f * num2;
				array[i] = Mathf.Clamp(samples[i] * num3, -1f, 1f);
			}
			return array;
		}

		internal static float[] ApplyTranqFilter(float[] samples, int sampleRate)
		{
			samples = ApplyLowPassFilter(samples, 1800f, sampleRate);
			return ApplyPitchShift(samples, 0.65f);
		}
	}
	internal sealed class MimicsAudioMarker : MonoBehaviour
	{
		private static Sprite s_sprite;

		private static Font s_font;

		private static readonly Color CAccent = new Color(0.35f, 0.65f, 1f);

		private static readonly Color CBg = new Color(0.05f, 0.07f, 0.11f, 0.82f);

		private static readonly Color CGreen = new Color(0.3f, 0.85f, 0.4f);

		private static readonly Color CDim = new Color(0.5f, 0.55f, 0.6f, 0.75f);

		private static readonly Color CText = new Color(0.88f, 0.91f, 0.95f);

		private static readonly Color CYellow = new Color(1f, 0.8f, 0.2f);

		private const float PanelW = 100f;

		private const float PanelH = 38f;

		private const float WorldScale = 0.01f;

		private const float YOffset = 0.6f;

		private AudioSource _source;

		private Canvas _canvas;

		private RectTransform _canvasRect;

		private Image _bg;

		private Image _border;

		private Text _iconText;

		private Text _stateText;

		private float _pulse;

		private static Sprite GetSprite()
		{
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			//IL_0052: Unknown result type (might be due to invalid IL or missing references)
			//IL_005c: Expected O, but got Unknown
			if ((Object)(object)s_sprite != (Object)null)
			{
				return s_sprite;
			}
			Texture2D val = new Texture2D(1, 1, (TextureFormat)4, false);
			val.SetPixel(0, 0, Color.white);
			val.Apply();
			s_sprite = Sprite.Create(val, new Rect(0f, 0f, 1f, 1f), Vector2.one * 0.5f);
			return s_sprite;
		}

		private static Font GetFont()
		{
			if ((Object)(object)s_font == (Object)null)
			{
				s_font = Resources.GetBuiltinResource<Font>("Arial.ttf");
			}
			return s_font;
		}

		public void Init(AudioSource src)
		{
			_source = src;
			BuildUI();
			SetAlwaysOnTop();
		}

		public void SetVisible(bool v)
		{
			if ((Object)(object)_canvas != (Object)null)
			{
				((Component)_canvas).gameObject.SetActive(v);
			}
		}

		private void OnDestroy()
		{
			if ((Object)(object)_canvas != (Object)null)
			{
				Object.Destroy((Object)(object)((Component)_canvas).gameObject);
			}
		}

		private void Update()
		{
			//IL_006d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0066: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c2: 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_0072: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ce: Unknown result type (might be due to invalid IL or missing references)
			//IL_01be: Unknown result type (might be due to invalid IL or missing references)
			//IL_013f: 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)
			//IL_0106: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ff: Unknown result type (might be due to invalid IL or missing references)
			//IL_010b: Unknown result type (might be due to invalid IL or missing references)
			//IL_011f: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)_source == (Object)null || (Object)(object)_canvas == (Object)null)
			{
				return;
			}
			bool isPlaying = _source.isPlaying;
			_pulse = (isPlaying ? (0.55f + 0.45f * Mathf.Sin(Time.time * 7f)) : 1f);
			if ((Object)(object)_border != (Object)null)
			{
				Color color = (isPlaying ? CAccent : CDim);
				color.a = (isPlaying ? _pulse : 0.4f);
				((Graphic)_border).color = color;
			}
			if ((Object)(object)_bg != (Object)null)
			{
				Color color2 = (Color)(isPlaying ? new Color(0.03f, 0.08f, 0.16f, 0.88f) : CBg);
				((Graphic)_bg).color = color2;
			}
			if ((Object)(object)_iconText != (Object)null)
			{
				_iconText.text = (isPlaying ? "♫" : "♪");
				Color color3 = (isPlaying ? CGreen : CDim);
				color3.a = _pulse;
				((Graphic)_iconText).color = color3;
			}
			if ((Object)(object)_stateText != (Object)null)
			{
				if (isPlaying)
				{
					((Graphic)_stateText).color = CText;
					float num = Mathf.Max(0f, ((Object)(object)_source.clip != (Object)null) ? (_source.clip.length - _source.time) : 0f);
					_stateText.text = ((num > 0.05f) ? $"PLAYING\n{num:F1}s left" : "PLAYING");
				}
				else
				{
					((Graphic)_stateText).color = CDim;
					_stateText.text = "AUDIO\nSOURCE";
				}
			}
		}

		private void LateUpdate()
		{
			//IL_002b: 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_003a: Unknown result type (might be due to invalid IL or missing references)
			//IL_003f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0055: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)_canvas == (Object)null))
			{
				Camera main = Camera.main;
				if (!((Object)(object)main == (Object)null))
				{
					((Transform)_canvasRect).position = ((Component)this).transform.position + Vector3.up * 0.6f;
					((Transform)_canvasRect).rotation = ((Component)main).transform.rotation;
				}
			}
		}

		private void BuildUI()
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Expected O, but got Unknown
			//IL_005e: Unknown result type (might be due to invalid IL or missing references)
			//IL_006e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0078: Unknown result type (might be due to invalid IL or missing references)
			//IL_009f: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cf: Unknown result type (might be due to invalid IL or missing references)
			//IL_0102: Unknown result type (might be due to invalid IL or missing references)
			//IL_0160: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = new GameObject("_MimicsAudioMarkerCanvas");
			val.transform.SetParent(((Component)this).transform, false);
			_canvas = val.AddComponent<Canvas>();
			_canvas.renderMode = (RenderMode)2;
			_canvas.sortingOrder = 101;
			_canvasRect = val.GetComponent<RectTransform>();
			_canvasRect.sizeDelta = new Vector2(100f, 38f);
			((Transform)_canvasRect).localScale = Vector3.one * 0.01f;
			val.AddComponent<CanvasScaler>().dynamicPixelsPerUnit = 10f;
			_bg = MkImg(val.transform, "bg", CBg, 0f, 1f, 0f, 1f);
			_border = MkImg(val.transform, "border", CAccent, 0f, 1f, 0.9f, 1f);
			_iconText = MkText(val.transform, "icon", 18, (FontStyle)1, CGreen);
			SetAnch(((Graphic)_iconText).rectTransform, 0.02f, 0.28f, 0f, 1f);
			_iconText.alignment = (TextAnchor)4;
			_iconText.text = "♪";
			_stateText = MkText(val.transform, "state", 8, (FontStyle)1, CDim);
			SetAnch(((Graphic)_stateText).rectTransform, 0.3f, 0.98f, 0f, 1f);
			_stateText.alignment = (TextAnchor)3;
			_stateText.text = "AUDIO\nSOURCE";
			_stateText.lineSpacing = 1.1f;
		}

		private Image MkImg(Transform parent, string name, Color color, float xMin, float xMax, float yMin, float yMax)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Expected O, but got Unknown
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = new GameObject(name);
			val.transform.SetParent(parent, false);
			Image obj = val.AddComponent<Image>();
			obj.sprite = GetSprite();
			((Graphic)obj).color = color;
			SetAnch(val.GetComponent<RectTransform>(), xMin, xMax, yMin, yMax);
			return obj;
		}

		private Text MkText(Transform parent, string name, int fontSize, FontStyle style, Color color)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = new GameObject(name);
			val.transform.SetParent(parent, false);
			Text obj = val.AddComponent<Text>();
			obj.font = GetFont();
			obj.fontSize = fontSize;
			obj.fontStyle = style;
			((Graphic)obj).color = color;
			((Graphic)obj).raycastTarget = false;
			obj.supportRichText = false;
			return obj;
		}

		private static void SetAnch(RectTransform r, float xMin, float xMax, float yMin, float yMax)
		{
			//IL_0003: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			r.anchorMin = new Vector2(xMin, yMin);
			r.anchorMax = new Vector2(xMax, yMax);
			Vector2 offsetMin = (r.offsetMax = Vector2.zero);
			r.offsetMin = offsetMin;
		}

		private void SetAlwaysOnTop()
		{
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Expected O, but got Unknown
			Graphic[] componentsInChildren = ((Component)_canvas).GetComponentsInChildren<Graphic>(true);
			foreach (Graphic obj in componentsInChildren)
			{
				Material val = new Material(obj.defaultMaterial);
				val.SetInt("unity_GUIZTestMode", 8);
				obj.material = val;
			}
		}
	}
	public class TFS_Mimics : MonoBehaviour, IInRoomCallbacks
	{
		private sealed class FpmPlayerEntry
		{
			public string PlayerId;

			public string DisplayName;

			public bool IsLocalPlayer;

			public bool IsOnline;

			public readonly List<int> CacheIndices = new List<int>();
		}

		private sealed class FpmEnemyEntry
		{
			public GameObject Enemy;

			public GameObject Target;

			public string Name;

			public float Distance;

			public bool IsPlaying;
		}

		private sealed class VoiceLogEntry
		{
			public bool IsIncoming;

			public string TransmissionId;

			public string PlayerId;

			public string PlayerName;

			public int Bytes;

			public bool IsComplete;

			public bool IsFailed;

			public float ReceivedAt;

			public float UpdatedAt;

			public int ChunksDone;

			public int ChunksTotal;
		}

		private sealed class RecordingRow
		{
			public CachedAudioEntry Voice;

			public CustomAudioEntry Custom;

			public string Owner;

			public bool IsMine;

			public float Duration;

			public float ReceivedAt;

			public object Key => ((object)Voice) ?? ((object)Custom);

			public bool Pinned
			{
				get
				{
					if (Voice != null)
					{
						return Voice.Pinned;
					}
					return false;
				}
			}

			public int PlayCount => Voice?.PlayCount ?? Custom?.PlayCount ?? 0;

			public float[] Waveform
			{
				get
				{
					object obj = Voice?.Waveform;
					if (obj == null)
					{
						CustomAudioEntry custom = Custom;
						if (custom == null)
						{
							return null;
						}
						obj = custom.Waveform;
					}
					return (float[])obj;
				}
			}
		}

		private sealed class CachedAudioEntry
		{
			public byte[] AudioData;

			public bool ApplyVoiceFilter;

			public int SampleRate;

			public int SourceActor;

			public string SourcePlayerId;

			public string SourceName;

			public float ReceivedAt;

			public string SoundGuid;

			public string FilePath;

			public bool Pinned;

			public int PlayCount;

			public float[] Waveform;
		}

		private sealed class ActivePlayback
		{
			public string EnemyName;

			public string Source;

			public float StartedAt;

			public float Length;
		}

		private sealed class HudPlaybackCandidate
		{
			public GameObject Enemy;

			public GameObject Target;

			public Vector3 Position;

			public float Distance;

			public string EnemyName;

			public bool IsPlaying;

			public float PlaybackEndsAt;
		}

		private sealed class PlayersIndexData
		{
			public List<PlayerIndexEntry> players { get; set; } = new List<PlayerIndexEntry>();
		}

		private sealed class PlayerIndexEntry
		{
			public string id { get; set; }

			public string name { get; set; }
		}

		private sealed class IncomingAudioTransmission
		{
			public int ExpectedChunkCount;

			public bool ApplyFilter;

			public int SampleRate;

			public int SenderActor;

			public string SenderPlayerId;

			public string SenderName;

			public float LastUpdatedAt;

			public readonly List<byte[]> Chunks = new List<byte[]>();
		}

		private sealed class CustomAudioEntry
		{
			public AudioClip Clip;

			public string FileName;

			public string FilePath;

			public string SourceMod;

			public bool IsNormalized;

			public string SoundGuid;

			public string ContentHash;

			public int PlayCount;

			public float[] Waveform;
		}

		private sealed class DirectorPlayer
		{
			public Player Player;

			public PlayerAvatar Avatar;

			public int Actor;

			public string Name;

			public Vector3 Pos;

			public Vector3 Eye;

			public Vector3 Forward;

			public bool Alive;

			public bool HearsSelf;
		}

		private sealed class DirectorEnemy
		{
			public GameObject Go;

			public int ViewId;

			public string Name;

			public Vector3 Pos;
		}

		private sealed class DirectorSound
		{
			public string Guid;

			public int SpeakerActor;

			public string Label;

			public float Duration;

			public HashSet<int> HaveActors;
		}

		private sealed class DirectorPickResult
		{
			public string SoundGuid;

			public int[] EnemyViewIds;

			public int ListenerCount;
		}

		private sealed class DirectorRequest
		{
			public string Reason;

			public Func<DirectorSound, bool> SoundFilter;

			public Func<DirectorPlayer, bool> ListenerFilter;

			public int ForcedEnemyViewId = -1;

			public Vector3? Anchor;

			public float AnchorRadius = 20f;

			public bool IgnoreEnemyVisibility;

			public int SpectatorActor = -1;

			public float Radius = -1f;

			public static DirectorRequest Timer()
			{
				return new DirectorRequest
				{
					Reason = "timer"
				};
			}
		}

		private sealed class DirectorDecision
		{
			public float Time;

			public string Reason;

			public string Sound;

			public string Enemies;

			public int Listeners;

			public float Score;

			public readonly List<string> Details = new List<string>();
		}

		private sealed class DirectorFeedEntry
		{
			public float Time;

			public string Kind;

			public string Text;

			public Color Color;
		}

		private enum DirectorEventKind
		{
			Death,
			Hurt,
			Spotted,
			Break,
			HeadTalk,
			Pickup
		}

		private sealed class DirectorCarriedHead
		{
			public int OwnerActor;

			public string OwnerName;

			public float NextTalkAt;

			public float NextShoutAt;
		}

		private sealed class DirectorPendingEvent
		{
			public DirectorEventKind Kind;

			public float FireAt;

			public int Actor;

			public Vector3 Position;

			public int EnemyViewId = -1;

			public string Label;

			public int Retries;

			public int EnemyRetries;
		}

		private sealed class PlayerJsonEntry
		{
			public string id;

			public string name;

			public int volumeOverride = -1;
		}

		private bool _debugWindowOpen;

		private bool _debugWindowCollapsed;

		private bool _showGizmos;

		private Rect _debugWindowRect = new Rect(20f, 20f, 640f, 520f);

		private float _debugWindowExpandedHeight = 520f;

		private int _debugTab;

		private Vector2 _scrollMobs;

		private Vector2 _scrollPlayers;

		private Vector2 _scrollRecordings;

		private Vector2 _scrollVoiceLog;

		private Vector2 _scrollVoiceLogOut;

		private Vector2 _scrollOverlays;

		private const int VoiceLogMaxEntries = 200;

		private readonly List<VoiceLogEntry> _voiceLog = new List<VoiceLogEntry>();

		private bool _isResizing;

		private Vector2 _resizeMouseStart;

		private Rect _resizeRectStart;

		private const float MinWindowWidth = 560f;

		private const float MinWindowHeight = 360f;

		private const float SidebarWidth = 112f;

		private readonly Dictionary<int, MimicsEnemyOverlay> _enemyOverlays = new Dictionary<int, MimicsEnemyOverlay>();

		private readonly Dictionary<int, MimicsAudioMarker> _audioMarkers = new Dictionary<int, MimicsAudioMarker>();

		private float _overlayNextRefresh;

		private const int TabRecordings = 0;

		private const int TabMobs = 1;

		private const int TabPlayers = 2;

		private const int TabNetwork = 3;

		private const int TabOverlays = 4;

		private const int TabSettings = 5;

		private const int TabDirector = 6;

		private static readonly string[] TabNames = new string[7] { "Recordings", "Mobs", "Players", "Network", "Overlays", "Settings", "Director" };

		private static readonly int[] TabOrder = new int[7] { 0, 6, 1, 2, 3, 4, 5 };

		private string _settingVolumeBuf;

		private string _settingRadiusBuf;

		private string _settingMinDelayBuf;

		private string _settingMaxDelayBuf;

		private string _settingMaxFilesBuf;

		private string _settingSamplingRateBuf;

		private string _settingNormalizeBuf;

		private string _settingVadSensitivityBuf;

		private bool _settingsDirty;

		private Vector2 _scrollSettings;

		private Vector2 _scrollReadiness;

		private readonly Dictionary<string, string> _playerVolBuf = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);

		private float _tabCacheNextRebuild;

		private const float TabCacheInterval = 0.25f;

		private readonly List<(string pid, string name, int count)> _cachedPlayersSorted = new List<(string, string, int)>();

		private readonly HashSet<string> _cachedPlayersOnlineIds = new HashSet<string>(StringComparer.OrdinalIgnoreCase);

		private string _cachedPlayersLocalId = string.Empty;

		private int _cachedPlayersWithClips;

		private int _playersPage;

		private readonly List<VoiceLogEntry> _cachedVoiceLogIn = new List<VoiceLogEntry>();

		private readonly List<VoiceLogEntry> _cachedVoiceLogOut = new List<VoiceLogEntry>();

		private int _cachedVoiceLogInProgress;

		private int _cachedReadinessEligibleCount;

		private readonly Dictionary<string, bool> _cachedReadinessEligible = new Dictionary<string, bool>();

		private bool _fpmOpen;

		private int _fpmPage;

		private int _fpmPlayerIdx;

		private int _fpmClipIdx;

		private int _fpmEnemyIdx;

		private int _fpmFilterIdx = -1;

		private bool _fpmHearYourself;

		private Vector2 _fpmScrollPlayer;

		private Vector2 _fpmScrollClip;

		private Vector2 _fpmScrollEnemy;

		private Vector2 _fpmScrollFilter;

		private int _fpmPagePlayer;

		private int _fpmPageClip;

		private int _fpmPageEnemy;

		private int _fpmPageFilter;

		private List<FpmPlayerEntry> _fpmPlayers;

		private List<FpmEnemyEntry> _fpmEnemies;

		private bool _guiStylesInit;

		private GUIStyle _gsWindow;

		private GUIStyle _gsH1;

		private GUIStyle _gsLabel;

		private GUIStyle _gsLabelDim;

		private GUIStyle _gsSmall;

		private GUIStyle _gsTitle;

		private GUIStyle _gsBtn;

		private GUIStyle _gsBtnPrimary;

		private GUIStyle _gsBtnDanger;

		private GUIStyle _gsBtnYellow;

		private GUIStyle _gsIconBtn;

		private GUIStyle _gsTabBtn;

		private GUIStyle _gsTabBtnActive;

		private GUIStyle _gsNavItem;

		private GUIStyle _gsNavItemActive;

		private GUIStyle _gsChip;

		private GUIStyle _gsListItem;

		private GUIStyle _gsListItemSel;

		private GUIStyle _gsPanelBox;

		private GUIStyle _gsModalTitle;

		private GUIStyle _gsRow;

		private GUIStyle _gsRowAlt;

		private Texture2D _txWhite;

		private Texture2D _txBgDark;

		private Texture2D _txBgPanel;

		private Texture2D _txBgHover;

		private Texture2D _txAccent;

		private Texture2D _txAccentDim;

		private Texture2D _txGreen;

		private Texture2D _txRed;

		private Texture2D _txYellow;

		private static readonly Color CAccent = new Color(0.29f, 0.67f, 1f);

		private static readonly Color CAccentDim = new Color(0.16f, 0.38f, 0.62f);

		private static readonly Color CGreen = new Color(0.27f, 0.87f, 0.42f);

		private static readonly Color CRed = new Color(1f, 0.33f, 0.33f);

		private static readonly Color CYellow = new Color(1f, 0.84f, 0.2f);

		private static readonly Color CCustom = new Color(0.55f, 0.85f, 0.4f);

		private static readonly Color CText = new Color(0.9f, 0.92f, 0.94f);

		private static readonly Color CTextDim = new Color(0.5f, 0.54f, 0.58f);

		private static readonly Color CBgDark = new Color(0.07f, 0.09f, 0.11f, 0.97f);

		private static readonly Color CBgPanel = new Color(0.11f, 0.14f, 0.17f, 1f);

		private static readonly Color CBgHover = new Color(0.18f, 0.22f, 0.27f, 1f);

		private static readonly Color CBgTrack = new Color(0.15f, 0.19f, 0.24f);

		private static readonly Color CLine = new Color(0.17f, 0.21f, 0.26f);

		private CursorLockMode _savedCursorLockMode;

		private bool _savedCursorVisible;

		private bool _cursorOverrideActive;

		private bool _debugWindowFocused = true;

		private ConfigEntry<string> _keybindListeningEntry;

		private bool _windowStateLoaded;

		private string _windowStateSaved;

		private float _windowStateNextSaveAt;

		private Vector2 _scrollDirector;

		private int _directorExpandedDecision = -1;

		private GUIStyle _gsGizmoLabel;

		private static readonly string[] RecordingFilterNames = new string[5] { "All", "Mine", "Others", "Custom", "Pinned" };

		private static readonly string[] RecordingSortNames = new string[3] { "newest", "most played", "longest" };

		private const int RecordingsPerPage = 25;

		private const int WaveformBuckets = 48;

		private const int WaveformsPerRebuild = 6;

		private const float ConfirmWindowSeconds = 3f;

		private int _recFilter;

		private int _recSort;

		private int _recPage;

		private readonly List<RecordingRow> _recRows = new List<RecordingRow>();

		private readonly int[] _recFilterCounts = new int[5];

		private object _pendingDeleteKey;

		private float _pendingDeleteUntil;

		private float _pendingClearUntil;

		private AudioSource _previewSource;

		private AudioClip _previewOwnedClip;

		private object _previewKey;

		private int _recBuiltVersion = -1;

		private string _recBuiltKey;

		private float _recBuiltAt;

		private bool _recWaveformsPending;

		private const int MaxExtraPlaybackRows = 2;

		private const float MeterMinDb = -60f;

		private readonly List<ActivePlayback> _activePlaybackScratch = new List<ActivePlayback>();

		private Dictionary<string, PlayerAvatar> _avatarMapCache = new Dictionary<string, PlayerAvatar>(StringComparer.OrdinalIgnoreCase);

		private float _avatarMapNextRebuild;

		private const float AvatarMapRebuildInterval = 1f;

		private static readonly ManualLogSource Log = Logger.CreateLogSource("TFS_Mimics");

		public PhotonView photonView;

		private PlayerVoiceChat playerVoiceChat;

		private int sampleRate;

		private float[] audioBuffer;

		private int bufferPosition;

		private float[] preSpeechBuffer;

		private int preSpeechWritePos;

		private int preSpeechCount;

		private int postSpeechSamplesRemaining;

		private int pendingSilenceSamples;

		private const int RecordingBufferSeconds = 30;

		private const int MaxSendBytes = 262144;

		private const int MaxSendQueueDepth = 3;

		private bool isRecording;

		private bool capturingSpeech;

		private bool fileSaved;

		private bool _isSendingAudio;

		private readonly Queue<byte[]> _sendQueue = new Queue<byte[]>();

		private float vadHoldUntil;

		private Dictionary<string, bool> filter;

		private readonly Dictionary<string, IncomingAudioTransmission> incomingAudioTransmissions = new Dictionary<string, IncomingAudioTransmission>();

		private readonly Dictionary<int, AudioSource> reusableEnemyAudioSources = new Dictionary<int, AudioSource>();

		private readonly Dictionary<int, float> playbackBusyUntilByTargetKey = new Dictionary<int, float>();

		private readonly Dictionary<int, float> playbackStartedAtByTargetKey = new Dictionary<int, float>();

		private readonly Dictionary<int, float> playbackClipLengthByTargetKey = new Dictionary<int, float>();

		private readonly Dictionary<int, ActivePlayback> activePlaybacks = new Dictionary<int, ActivePlayback>();

		private static readonly List<CachedAudioEntry> cachedAudio = new List<CachedAudioEntry>();

		private static readonly Dictionary<string, CachedAudioEntry> cachedAudioByGuid = new Dictionary<string, CachedAudioEntry>();

		private static int cachedAudioVersion;

		private string currentPlaybackEnemyName = "None";

		private string currentPlaybackSourcePlayerId = "None";

		private float currentPlaybackEndsAt;

		private readonly List<string> nearestPlaybackTargetsHud = new List<string>();

		private readonly List<HudPlaybackCandidate> nearestPlaybackCandidatesHud = new List<HudPlaybackCandidate>();

		private Vector3 hudLastSelectedEnemyPos;

		private bool hudHasSelectedEnemyPos;

		private GameObject hudTrackedEnemy;

		private GameObject hudTrackedTarget;

		private float hudNextRefreshAt;

		private bool wasInLevel;

		private bool persistenceInitialized;

		private static readonly HashSet<string> loadedPersistedFiles = new HashSet<string>(StringComparer.OrdinalIgnoreCase);

		private readonly Dictionary<string, string> playerNameById = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);

		private readonly Dictionary<string, int> playerVolumeOverrides = new Dictionary<string, int>(StringComparer.OrdinalIgnoreCase);

		private const float IncomingTransmissionTimeoutSeconds = 30f;

		private static readonly Dictionary<string, HashSet<int>> soundReadinessMap = new Dictionary<string, HashSet<int>>();

		private bool _hostAuthorityLoopRunning;

		private float _nextTickAt = -1f;

		private readonly List<CustomAudioEntry> _customAudioClips = new List<CustomAudioEntry>();

		private bool _customAudioLoaded;

		private const int DirectorFeedMax = 40;

		private const int DirectorDecisionsMax = 12;

		private const float DirectorEventGap = 10f;

		private const float DirectorRecentWindow = 90f;

		private static readonly Dictionary<string, float> _directorLastPlayed = new Dictionary<string, float>();

		private static readonly Dictionary<string, int> _directorPlayCount = new Dictionary<string, int>();

		private readonly List<DirectorFeedEntry> _directorFeed = new List<DirectorFeedEntry>();

		private readonly List<DirectorDecision> _directorDecisions = new List<DirectorDecision>();

		private readonly List<DirectorPendingEvent> _directorPending = new List<DirectorPendingEvent>();

		private readonly Dictionary<int, int> _directorLastHealth = new Dictionary<int, int>();

		private readonly Dictionary<int, float> _directorHurtCooldown = new Dictionary<int, float>();

		private readonly Dictionary<int, float> _directorSpotCooldown = new Dictionary<int, float>();

		private float _directorBreakCooldownUntil;

		private float _directorPickupCooldownUntil;

		private readonly Dictionary<string, float> _directorNoteThrottle = new Dictionary<string, float>();

		private float _directorLastEventPlaybackAt = -999f;

		private float _directorTimerSuppressedUntil;

		private float _directorNextHealthPollAt;

		private float _directorNextHeadPollAt;

		private readonly Dictionary<int, DirectorCarriedHead> _directorCarriedHeads = new Dictionary<int, DirectorCarriedHead>();

		private static readonly Dictionary<(int, int), bool> _speakerVisCache = new Dictionary<(int, int), bool>();

		private static readonly Dictionary<int, bool> _aloneCache = new Dictionary<int, bool>();

		private bool _directorLastPickWantsEnemy;

		private const int DirectorEventEnemyRetries = 4;

		private const float DirectorEventRadius = 20f;

		private const string HearSelfPropertyKey = "tfsm.hs";

		private static bool _hearSelfHooked;

		private static HashSet<string> _pinnedFileNames;

		private static FieldInfo _steamIdField;

		private FieldInfo _recorderField;

		private PropertyInfo _recorderTransmitProp;

		private bool _recorderReflectionDone;

		private const float VadThresholdAtMinSensitivity = 0.012f;

		private const float VadThresholdAtMaxSensitivity = 0.001f;

		private const float VadNoiseFloorMultiplier = 3f;

		private const float VadHoldSeconds = 0.5f;

		private float vadNoiseFloor;

		private float _micLevel;

		private float _micPeakHold;

		private float _micLevelAt;

		private const int SteamChunkSize = 204800;

		internal static TFS_Mimics Instance { get; private set; }

		private static bool IsDirectorHost => SemiFunc.IsMasterClientOrSingleplayer();

		private static bool DirectorEnabled
		{
			get
			{
				if (Plugin.configSmartDirector != null)
				{
					return Plugin.configSmartDirector.Value;
				}
				return true;
			}
		}

		private static TFS_Mimics DirectorOwner => VoiceDataBus.LocalMimics;

		private void SetCursorForGui(bool guiActive)
		{
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			if (guiActive && !_cursorOverrideActive)
			{
				_savedCursorLockMode = Cursor.lockState;
				_savedCursorVisible = Cursor.visible;
				Cursor.lockState = (CursorLockMode)0;
				Cursor.visible = true;
				_cursorOverrideActive = true;
			}
			else if (!guiActive && _cursorOverrideActive)
			{
				Cursor.lockState = _savedCursorLockMode;
				Cursor.visible = _savedCursorVisible;
				_cursorOverrideActive = false;
			}
		}

		private static bool IsDebugGuiAllowedHere()
		{
			if (!SemiFunc.RunIsLevel() && !SemiFunc.RunIsShop())
			{
				return SemiFunc.RunIsLobby();
			}
			return true;
		}

		private void DebugGuiUpdate()
		{
			//IL_0006: 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)
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ed: Unknown result type (might be due to invalid IL or missing references)
			EnsureWindowStateLoaded();
			KeyCode debugMenuKey = Plugin.GetDebugMenuKey();
			if (_keybindListeningEntry == null && Input.GetKeyDown(debugMenuKey))
			{
				if ((Input.GetKey((KeyCode)304) || Input.GetKey((KeyCode)303)) && _debugWindowOpen)
				{
					_debugWindowFocused = !_debugWindowFocused;
				}
				else
				{
					_debugWindowOpen = !_debugWindowOpen;
					_debugWindowFocused = _debugWindowOpen;
					if (_debugWindowOpen)
					{
						hudNextRefreshAt = 0f;
					}
					else
					{
						_fpmOpen = false;
						StopRecordingPreview();
					}
				}
			}
			if (!_debugWindowOpen || !_debugWindowFocused || _debugTab != 5)
			{
				_keybindListeningEntry = null;
			}
			if (_debugWindowOpen && !_debugWindowFocused && Input.GetMouseButtonDown(0))
			{
				Vector2 val = default(Vector2);
				((Vector2)(ref val))..ctor(Input.mousePosition.x, (float)Screen.height - Input.mousePosition.y);
				if (((Rect)(ref _debugWindowRect)).Contains(val))
				{
					_debugWindowFocused = true;
				}
			}
			bool cursorForGui = _debugWindowOpen && _debugWindowFocused;
			SetCursorForGui(cursorForGui);
			SaveWindowStateIfChanged();
			if (_debugWindowOpen)
			{
				bool num = SemiFunc.RunIsLevel();
				if (num && Time.time >= hudNextRefreshAt)
				{
					hudNextRefreshAt = Time.time + 0.25f;
					RefreshHudTargetsSnapshot();
				}
				if (_debugTab == 2)
				{
					RebuildAvatarMapIfNeeded();
				}
				if (Time.time >= _tabCacheNextRebuild)
				{
					_tabCacheNextRebuild = Time.time + 0.25f;
					RebuildActiveTabCache();
				}
				if (num && _showGizmos)
				{
					RefreshEnemyOverlays();
				}
			}
		}

		private void OnGUI()
		{
			//IL_0066: Unknown result type (might be due to invalid IL or missing references)
			//IL_0086: 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_00d6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00de: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f3: Expected O, but got Unknown
			//IL_00ee: Unknown result type (might be due to invalid IL or missing references)
			//IL_0121: Unknown result type (might be due to invalid IL or missing references)
			//IL_012d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0142: Expected O, but got Unknown
			//IL_013d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0142: Unknown result type (might be due to invalid IL or missing references)
			//IL_019a: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ae: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a7: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c8: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)photonView == (Object)null || !photonView.IsMine || !IsDebugGuiAllowedHere())
			{
				return;
			}
			EnsureGuiStyles();
			if (!_debugWindowOpen)
			{
				return;
			}
			if (_showGizmos && SemiFunc.RunIsLevel())
			{
				DrawWorldGizmos();
			}
			if (_fpmOpen)
			{
				GUI.color = new Color(0f, 0f, 0f, 0.65f);
				GUI.DrawTexture(new Rect(0f, 0f, (float)Screen.width, (float)Screen.height), (Texture)(object)_txWhite);
				GUI.color = Color.white;
				float num = 440f;
				float num2 = 390f;
				Rect val = default(Rect);
				((Rect)(ref val))..ctor(((float)Screen.width - num) * 0.5f, ((float)Screen.height - num2) * 0.5f, num, num2);
				GUI.Window(9901, val, new WindowFunction(DrawForcePlayModal), string.Empty, _gsWindow);
				return;
			}
			ClampWindowToScreen();
			if (_debugWindowCollapsed)
			{
				((Rect)(ref _debugWindowRect)).height = GetBodyTopOffset() - 2f;
			}
			_debugWindowRect = GUI.Window(9900, _debugWindowRect, new WindowFunction(DrawMainWindow), string.Empty, _gsWindow);
			if (!_debugWindowCollapsed)
			{
				HandleResizeInput();
				Rect val2 = new Rect(((Rect)(ref _debugWindowRect)).x + ((Rect)(ref _debugWindowRect)).width - 18f, ((Rect)(ref _debugWindowRect)).y + ((Rect)(ref _debugWindowRect)).height - 18f, 18f, 18f);
				GUI.color = (_isResizing ? CAccent : CTextDim);
				GUI.Label(val2, "◢", _gsSmall);
				GUI.color = Color.white;
			}
		}

		private void HandleResizeInput()
		{
			//IL_005a: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00af: Invalid comparison between Unknown and I4
			//IL_0129: Unknown result type (might be due to invalid IL or missing references)
			//IL_012f: Invalid comparison between Unknown and I4
			//IL_00b2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d9: 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)
			//IL_006c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0081: Unknown result type (might be due to invalid IL or missing references)
			//IL_0086: Unknown result type (might be due to invalid IL or missing references)
			//IL_008d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0092: Unknown result type (might be due to invalid IL or missing references)
			Rect val = default(Rect);
			((Rect)(ref val))..ctor(((Rect)(ref _debugWindowRect)).x + ((Rect)(ref _debugWindowRect)).width - 18f, ((Rect)(ref _debugWindowRect)).y + ((Rect)(ref _debugWindowRect)).height - 18f, 18f, 18f);
			Event current = Event.current;
			if (!_isResizing && (int)current.type == 0 && current.button == 0 && ((Rect)(ref val)).Contains(current.mousePosition))
			{
				_isResizing = true;
				_resizeMouseStart = current.mousePosition;
				_resizeRectStart = _debugWindowRect;
				current.Use();
			}
			if (_isResizing)
			{
				if ((int)current.type == 3)
				{
					Vector2 val2 = current.mousePosition - _resizeMouseStart;
					((Rect)(ref _debugWindowRect)).width = Mathf.Max(560f, ((Rect)(ref _resizeRectStart)).width + val2.x);
					((Rect)(ref _debugWindowRect)).height = Mathf.Max(360f, ((Rect)(ref _resizeRectStart)).height + val2.y);
					_debugWindowExpandedHeight = ((Rect)(ref _debugWindowRect)).height;
					current.Use();
				}
				if ((int)current.type == 1)
				{
					_isResizing = false;
					current.Use();
				}
			}
		}

		private void ClampWindowToScreen()
		{
			((Rect)(ref _debugWindowRect)).width = Mathf.Min(((Rect)(ref _debugWindowRect)).width, Mathf.Max(560f, (float)Screen.width));
			((Rect)(ref _debugWindowRect)).x = Mathf.Clamp(((Rect)(ref _debugWindowRect)).x, 0f, Mathf.Max(0f, (float)Screen.width - ((Rect)(ref _debugWindowRect)).width));
			((Rect)(ref _debugWindowRect)).y = Mathf.Clamp(((Rect)(ref _debugWindowRect)).y, 0f, Mathf.Max(0f, (float)Screen.height - 40f));
		}

		private void SetWindowCollapsed(bool collapsed)
		{
			if (collapsed != _debugWindowCollapsed)
			{
				_debugWindowCollapsed = collapsed;
				if (collapsed)
				{
					_debugWindowExpandedHeight = ((Rect)(ref _debugWindowRect)).height;
					StopRecordingPreview();
				}
				else
				{
					((Rect)(ref _debugWindowRect)).height = Mathf.Max(360f, _debugWindowExpandedHeight);
				}
			}
		}

		private void DrawMainWindow(int id)
		{
			//IL_00b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cd: Unknown result type (might be due to invalid IL or missing references)
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_018f: Unknown result type (might be due to invalid IL or missing references)
			DrawWindowTitleBar();
			GUILayout.Space(4f);
			DrawStatusStrip();
			if (_debugWindowCollapsed)
			{
				GUI.DragWindow(new Rect(0f, 0f, ((Rect)(ref _debugWindowRect)).width - 60f, 28f));
				return;
			}
			GUILayout.Space(6f);
			float num = Mathf.Max(160f, ((Rect)(ref _debugWindowRect)).height - GetBodyTopOffset() - 12f);
			GUILayout.BeginHorizontal((GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(num) });
			DrawSidebar(num);
			Rect rect = GUILayoutUtility.GetRect(1f, num, (GUILayoutOption[])(object)new GUILayoutOption[2]
			{
				GUILayout.Width(1f),
				GUILayout.ExpandHeight(true)
			});
			GUI.color = CLine;
			GUI.DrawTexture(rect, (Texture)(object)_txWhite);
			GUI.color = Color.white;
			GUILayout.Space(8f);
			GUILayout.BeginVertical(Array.Empty<GUILayoutOption>());
			float scrollH = Mathf.Max(100f, num - 34f);
			switch (_debugTab)
			{
			case 0:
				DrawRecordingsTab(scrollH);
				break;
			case 1:
				DrawNearestMobsTab(scrollH);
				break;
			case 2:
				DrawPlayersTab(scrollH);
				break;
			case 3:
				DrawNetworkTab(scrollH);
				break;
			case 4:
				DrawOverlaysTab(scrollH);
				break;
			case 5:
				DrawSettingsTab(scrollH);
				break;
			case 6:
				DrawDirectorTab(scrollH);
				break;
			}
			GUILayout.EndVertical();
			GUILayout.EndHorizontal();
			GUI.DragWindow(new Rect(0f, 0f, ((Rect)(ref _debugWindowRect)).width - 60f, 28f));
		}

		private float GetBodyTopOffset()
		{
			int num = Mathf.Clamp(CountActivePlaybacks() - 1, 0, 3);
			return 116f + (float)num * 16f;
		}

		private void DrawSidebar(float height)
		{
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			//IL_007e: Expected O, but got Unknown
			//IL_0079: Unknown result type (might be due to invalid IL or missing references)
			//IL_007e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0080: 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_00fb: Unknown result type (might be due to invalid IL or missing references)
			//IL_010b: Unknown result type (might be due to invalid IL or missing references)
			GUILayout.BeginVertical((GUILayoutOption[])(object)new GUILayoutOption[2]
			{
				GUILayout.Width(112f),
				GUILayout.Height(height)
			});
			int[] tabOrder = TabOrder;
			foreach (int num in tabOrder)
			{
				bool flag = _debugTab == num;
				Rect rect = GUILayoutUtility.GetRect(new GUIContent(TabNames[num]), flag ? _gsNavItemActive : _gsNavItem, (GUILayoutOption[])(object)new GUILayoutOption[2]
				{
					GUILayout.Width(112f),
					GUILayout.Height(26f)
				});
				if (GUI.Button(rect, TabNames[num] + GetTabBadge(num), flag ? _gsNavItemActive : _gsNavItem) && _debugTab != num)
				{
					_debugTab = num;
					_tabCacheNextRebuild = 0f;
				}
				if (flag)
				{
					GUI.color = CAccent;
					GUI.DrawTexture(new Rect(((Rect)(ref rect)).x, ((Rect)(ref rect)).y + 4f, 2f, ((Rect)(ref rect)).height - 8f), (Texture)(object)_txWhite);
					GUI.color = Color.white;
				}
				GUILayout.Space(2f);
			}
			GUILayout.FlexibleSpace();
			GUI.enabled = SemiFunc.RunIsLevel();
			if (GUILayout.Button("▶  Force play", _gsBtnYellow, (GUILayoutOption[])(object)new GUILayoutOption[2]
			{
				GUILayout.Width(112f),
				GUILayout.Height(26f)
			}))
			{
				OpenForcePlayModal();
			}
			GUI.enabled = true;
			GUILayout.EndVertical();
		}

		private string GetTabBadge(int tab)
		{
			switch (tab)
			{
			case 0:
				if (cachedAudio.Count + _customAudioClips.Count <= 0)
				{
					return string.Empty;
				}
				return $"  {cachedAudio.Count + _customAudioClips.Count}";
			case 1:
				if (nearestPlaybackCandidatesHud.Count <= 0 || !SemiFunc.RunIsLevel())
				{
					return string.Empty;
				}
				return $"  {nearestPlaybackCandidatesHud.Count}";
			case 3:
				if (incomingAudioTransmissions.Count <= 0)
				{
					return string.Empty;
				}
				return $"  ●{incomingAudioTransmissions.Count}";
			case 6:
				if (_directorPending.Count <= 0)
				{
					return string.Empty;
				}
				return $"  ●{_directorPending.Count}";
			default:
				return string.Empty;
			}
		}

		private static string GetWindowStatePath()
		{
			return Path.Combine(Paths.ConfigPath, "TFS_Mimics.window.txt");
		}

		private void EnsureWindowStateLoaded()
		{
			//IL_0081: Unknown result type (might be due to invalid IL or missing references)
			//IL_0086: Unknown result type (might be due to invalid IL or missing references)
			if (_windowStateLoaded)
			{
				return;
			}
			_windowStateLoaded = true;
			try
			{
				string windowStatePath = GetWindowStatePath();
				if (File.Exists(windowStatePath))
				{
					string[] array = File.ReadAllText(windowStatePath).Trim().Split(';');
					if (array.Length >= 7)
					{
						CultureInfo invariantCulture = CultureInfo.InvariantCulture;
						_debugWindowRect = new Rect(float.Parse(array[0], invariantCulture), float.Parse(array[1], invariantCulture), Mathf.Max(560f, float.Parse(array[2], invariantCulture)), Mathf.Max(360f, float.Parse(array[3], invariantCulture)));
						_debugTab = Mathf.Clamp(int.Parse(array[4], invariantCulture), 0, TabNames.Length - 1);
						_debugWindowCollapsed = array[5] == "1";
						_debugWindowExpandedHeight = Mathf.Max(360f, float.Parse(array[6], invariantCulture));
						_windowStateSaved = SerializeWindowState();
					}
				}
			}
			catch (Exception ex)
			{
				Log.LogWarning((object)("Failed to load debug window state: " + ex.Message));
			}
		}

		private string SerializeWindowState()
		{
			CultureInfo invariantCulture = CultureInfo.InvariantCulture;
			float num = (_debugWindowCollapsed ? _debugWindowExpandedHeight : ((Rect)(ref _debugWindowRect)).height);
			return string.Join(";", Mathf.Round(((Rect)(ref _debugWindowRect)).x).ToString(invariantCulture), Mathf.Round(((Rect)(ref _debugWindowRect)).y).ToString(invariantCulture), Mathf.Round(((Rect)(ref _debugWindowRect)).width).ToString(invariantCulture), Mathf.Round(num).ToString(invariantCulture), _debugTab.ToString(invariantCulture), _debugWindowCollapsed ? "1" : "0", Mathf.Round(_debugWindowExpandedHeight).ToString(invariantCulture));
		}

		private void SaveWindowStateIfChanged()
		{
			if (!_windowStateLoaded || _isResizing || Time.unscaledTime < _windowStateNextSaveAt)
			{
				return;
			}
			_windowStateNextSaveAt = Time.unscaledTime + 1f;
			string text = SerializeWindowState();
			if (text == _windowStateSaved)
			{
				return;
			}
			try
			{
				File.WriteAllText(GetWindowStatePath(), text);
				_windowStateSaved = text;
			}
			catch (Exception ex)
			{
				Log.LogWarning((object)("Failed to save debug window state: " + ex.Message));
				_windowStateNextSaveAt = Time.unscaledTime + 30f;
			}
		}

		private void EnsureGuiStyles()
		{
			//IL_0013: 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_0037: Unknown result type (might be due to invalid IL or missing references)
			//IL_0049: 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_006d: Unknown result type (might be due to invalid IL or missing references)
			//IL_007f: 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_00a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e9: Unknown result type (might be due to invalid IL or missing references)
			//IL_010a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0120: Unknown result type (might be due to invalid IL or missing references)
			//IL_0125: Unknown result type (might be due to invalid IL or missing references)
			//IL_012d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0137: Expected O, but got Unknown
			//IL_0137: Unknown result type (might be due to invalid IL or missing references)
			//IL_0148: Unknown result type (might be due to invalid IL or missing references)
			//IL_014e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0158: Unknown result type (might be due to invalid IL or missing references)
			//IL_0169: Unknown result type (might be due to invalid IL or missing references)
			//IL_016f: Unknown result type (might be due to invalid IL or missing references)
			//IL_017e: Expected O, but got Unknown
			//IL_0189: Unknown result type (might be due to invalid IL or missing references)
			//IL_018e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0196: Unknown result type (might be due to invalid IL or missing references)
			//IL_019d: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ad: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01bc: Expected O, but got Unknown
			//IL_01c1: Expected O, but got Unknown
			//IL_01cc: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d1: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d9: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e6: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f5: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ff: Expected O, but got Unknown
			//IL_0204: Expected O, but got Unknown
			//IL_020f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0214: Unknown result type (might be due to invalid IL or missing references)
			//IL_021c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0222: Unknown result type (might be due to invalid IL or missing references)
			//IL_022c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0231: Unknown result type (might be due to invalid IL or missing references)
			//IL_023b: Expected O, but got Unknown
			//IL_0240: Expected O, but got Unknown
			//IL_0247: Unknown result type (might be due to invalid IL or missing references)
			//IL_024c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0252: Unknown result type (might be due to invalid IL or missing references)
			//IL_0261: Expected O, but got Unknown
			//IL_0268: Unknown result type (might be due to invalid IL or missing references)
			//IL_026d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0275: Unknown result type (might be due to invalid IL or missing references)
			//IL_027b: Unknown result type (might be due to invalid IL or missing references)
			//IL_028a: Expected O, but got Unknown
			//IL_0295: Unknown result type (might be due to invalid IL or missing references)
			//IL_029a: Unknown result type (might be due to invalid IL or missing references)
			//IL_02a2: Unknown result type (might be due to invalid IL or missing references)
			//IL_02a7: Unknown result type (might be due to invalid IL or missing references)
			//IL_02b1: Expected O, but got Unknown
			//IL_02b1: Unknown result type (might be due to invalid IL or missing references)
			//IL_02c2: Unknown result type (might be due to invalid IL or missing references)
			//IL_02c8: Unknown result type (might be due to invalid IL or missing references)
			//IL_02d2: Unknown result type (might be due to invalid IL or missing references)
			//IL_02e3: 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_02f3: Unknown result type (might be due to invalid IL or missing references)
			//IL_0304: Unknown result type (might be due to invalid IL or missing references)
			//IL_030a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0319: Expected O, but got Unknown
			//IL_0320: Unknown result type (might be due to invalid IL or missing references)
			//IL_0325: Unknown result type (might be due to invalid IL or missing references)
			//IL_032a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0334: Expected O, but got Unknown
			//IL_0334: Unknown result type (might be due to invalid IL or missing references)
			//IL_033b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0348: Expected O, but got Unknown
			//IL_034f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0354: Unknown result type (might be due to invalid IL or missing references)
			//IL_0365: Unknown result type (might be due to invalid IL or missing references)
			//IL_036b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0375: 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_038c: Unknown result type (might be due to invalid IL or missing references)
			//IL_039b: Expected O, but got Unknown
			//IL_03a2: Unknown result type (might be due to invalid IL or missing references)
			//IL_03a7: Unknown result type (might be due to invalid IL or missing references)
			//IL_03be: Unknown result type (might be due to invalid IL or missing references)
			//IL_03cd: Unknown result type (might be due to invalid IL or missing references)
			//IL_03d3: Unknown result type (might be due to invalid IL or missing references)
			//IL_03dd: Unknown result type (might be due to invalid IL or missing references)
			//IL_03ee: Unknown result type (might be due to invalid IL or missing references)
			//IL_03f4: Unknown result type (might be due to invalid IL or missing references)
			//IL_0403: Expected O, but got Unknown
			//IL_040a: Unknown result type (might be due to invalid IL or missing references)
			//IL_040f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0426: Unknown result type (might be due to invalid IL or missing references)
			//IL_0435: Unknown result type (might be due to invalid IL or missing references)
			//IL_043b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0445: Unknown result type (might be due to invalid IL or missing references)
			//IL_0456: Unknown result type (might be due to invalid IL or missing references)
			//IL_046b: Unknown result type (might be due to invalid IL or missing references)
			//IL_047a: Expected O, but got Unknown
			//IL_0481: Unknown result type (might be due to invalid IL or missing references)
			//IL_0486: Unknown result type (might be due to invalid IL or missing references)
			//IL_0497: Unknown result type (might be due to invalid IL or missing references)
			//IL_049d: Unknown result type (might be due to invalid IL or missing references)
			//IL_04a7: Unknown result type (might be due to invalid IL or missing references)
			//IL_04b8: Unknown result type (might be due to invalid IL or missing references)
			//IL_04be: Unknown result type (might be due to invalid IL or missing references)
			//IL_04cd: Expected O, but got Unknown
			//IL_04d4: Unknown result type (might be due to invalid IL or missing references)
			//IL_04d9: Unknown result type (might be due to invalid IL or missing references)
			//IL_04e0: Unknown result type (might be due to invalid IL or missing references)
			//IL_04f1: Unknown result type (might be due to invalid IL or missing references)
			//IL_04f7: Unknown result type (might be due to invalid IL or missing references)
			//IL_0506: Expected O, but got Unknown
			//IL_0511: Unknown result type (might be due to invalid IL or missing references)
			//IL_0516: Unknown result type (might be due to invalid IL or missing references)
			//IL_051e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0525: Unknown result type (might be due to invalid IL or missing references)
			//IL_052b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0535: Expected O, but got Unknown
			//IL_0535: Unknown result type (might be due to invalid IL or missing references)
			//IL_0541: Unknown result type (might be due to invalid IL or missing references)
			//IL_0547: 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_0562: Unknown result type (might be due to invalid IL or missing references)
			//IL_0568: Unknown result type (might be due to invalid IL or missing references)
			//IL_0572: Unknown result type (might be due to invalid IL or missing references)
			//IL_0583: Unknown result type (might be due to invalid IL or missing references)
			//IL_0589: Unknown result type (might be due to invalid IL or missing references)
			//IL_0598: Expected O, but got Unknown
			//IL_059f: Unknown result type (might be due to invalid IL or missing references)
			//IL_05a4: Unknown result type (might be due to invalid IL or missing references)
			//IL_05ab: Unknown result type (might be due to invalid IL or missing references)
			//IL_05b7: Unknown result type (might be due to invalid IL or missing references)
			//IL_05bd: Unknown result type (might be due to invalid IL or missing references)
			//IL_05c7: Unknown result type (might be due to invalid IL or missing references)
			//IL_05d3: Unknown result type (might be due to invalid IL or missing references)
			//IL_05d9: Unknown result type (might be due to invalid IL or missing references)
			//IL_05e8: Expected O, but got Unknown
			//IL_05f3: Unknown result type (might be due to invalid IL or missing references)
			//IL_05f8: Unknown result type (might be due to invalid IL or missing references)
			//IL_0600: Unknown result type (might be due to invalid IL or missing references)
			//IL_0607: Unknown result type (might be due to invalid IL or missing references)
			//IL_060c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0616: Expected O, but got Unknown
			//IL_0616: Unknown result type (might be due to invalid IL or missing references)
			//IL_061b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0625: Expected O, but got Unknown
			//IL_0625: Unknown result type (might be due to invalid IL or missing references)
			//IL_0636: Unknown result type (might be due to invalid IL or missing references)
			//IL_063c: Unknown result type (might be due to invalid IL or missing references)
			//IL_064b: Expected O, but got Unknown
			//IL_0661: Unknown result type (might be due to invalid IL or missing references)
			//IL_0677: Unknown result type (might be due to invalid IL or missing references)
			//IL_067c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0684: Unknown result type (might be due to invalid IL or missing references)
			//IL_068b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0690: Unknown result type (might be due to invalid IL or missing references)
			//IL_069a: Expected O, but got Unknown
			//IL_069a: Unknown result type (might be due to invalid IL or missing references)
			//IL_06a6: Unknown result type (might be due to invalid IL or missing references)
			//IL_06ac: Unknown result type (might be due to invalid IL or missing references)
			//IL_06b6: Unknown result type (might be due to invalid IL or missing references)
			//IL_06c7: Unknown result type (might be due to invalid IL or missing references)
			//IL_06cd: Unknown result type (might be due to invalid IL or missing references)
			//IL_06d7: Unknown result type (might be due to invalid IL or missing references)
			//IL_06e8: Unknown result type (might be due to invalid IL or missing references)
			//IL_06ee: Unknown result type (might be due to invalid IL or missing references)
			//IL_06fd: Expected O, but got Unknown
			//IL_0704: Unknown result type (might be due to invalid IL or missing references)
			//IL_0709: Unknown result type (might be due to invalid IL or missing references)
			//IL_0710: Unknown result type (might be due to invalid IL or missing references)
			//IL_0721: Unknown result type (might be due to invalid IL or missing references)
			//IL_0727: Unknown result type (might be due to invalid IL or missing references)
			//IL_0731: Unknown result type (might be due to invalid IL or missing references)
			//IL_0742: Unknown result type (might be due to invalid IL or missing references)
			//IL_0748: Unknown result type (might be due to invalid IL or missing references)
			//IL_0757: Expected O, but got Unknown
			//IL_075e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0763: Unknown result type (might be due to invalid IL or missing references)
			//IL_076b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0772: Unknown result type (might be due to invalid IL or missing references)
			//IL_0778: Unknown result type (might be due to invalid IL or missing references)
			//IL_0787: Expected O, but got Unknown
			//IL_0792: Unknown result type (might be due to invalid IL or missing references)
			//IL_0797: 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_07a6: Expected O, but got Unknown
			//IL_07a6: Unknown result type (might be due to invalid IL or missing references)
			//IL_07b7: Unknown result type (might be due to invalid IL or missing references)
			//IL_07bd: Unknown result type (might be due to invalid IL or missing references)
			//IL_07cc: Expected O, but got Unknown
			//IL_07d2: Unknown result type (might be due to invalid IL or missing references)
			//IL_07d7: Unknown result type (might be due to invalid IL or missing references)
			//IL_07dc: Unknown result type (might be due to invalid IL or missing references)
			//IL_07e6: Expected O, but got Unknown
			//IL_07e6: Unknown result type (might be due to invalid IL or missing references)
			//IL_07f7: Expected O, but got Unknown
			//IL_07fe: Unknown result type (might be due to invalid IL or missing references)
			//IL_0803: Unknown result type (might be due to invalid IL or missing references)
			//IL_0814: Expected O, but got Unknown
			if (!_guiStylesInit)
			{
				_guiStylesInit = true;
				_txWhite = MakeTex(1, 1, Color.white);
				_txBgDark = MakeTex(1, 1, CBgDark);
				_txBgPanel = MakeTex(1, 1, CBgPanel);
				_txBgHover = MakeTex(1, 1, CBgHover);
				_txAccent = MakeTex(1, 1, CAccent);
				_txAccentDim = MakeTex(1, 1, CAccentDim);
				_txGreen = MakeTex(1, 1, CGreen);
				_txRed = MakeTex(1, 1, CRed);
				_txYellow = MakeTex(1, 1, CYellow);
				Texture2D background = MakeTex(1, 1, new Color(0f, 0f, 0f, 0f));
				Texture2D background2 = MakeTex(1, 1, new Color(1f, 1f, 1f, 0.025f));
				Texture2D background3 = MakeTex(1, 1, new Color(0.16f, 0.38f, 0.62f, 0.45f));
				GUIStyle val = new GUIStyle(GUI.skin.window)
				{
					padding = new RectOffset(10, 10, 8, 10)
				};
				val.normal.background = _txBgDark;
				val.normal.textColor = CText;
				val.onNormal.background = _txBgDark;
				val.onNormal.textColor = CText;
				_gsWindow = val;
				GUIStyle val2 = new GUIStyle(GUI.skin.label)
				{
					fontSize = 13,
					fontStyle = (FontStyle)1
				};
				val2.normal.textColor = CAccent;
				val2.padding = new RectOffset(0, 0, 2, 2);
				_gsTitle = val2;
				GUIStyle val3 = new GUIStyle(GUI.skin.label)
				{
					fontSize = 12,
					fontStyle = (FontStyle)1
				};
				val3.normal.textColor = CText;
				val3.padding = new RectOffset(0, 0, 2, 2);
				_gsH1 = val3;
				GUIStyle val4 = new GUIStyle(GUI.skin.label)
				{
					fontSize = 11
				};
				val4.normal.textColor = CText;
				val4.padding = new RectOffset(2, 2, 1, 1);
				_gsLabel = val4;
				GUIStyle val5 = new GUIStyle(_gsLabel);
				val5.normal.textColor = CTextDim;
				_gsLabelDim = val5;
				GUIStyle val6 = new GUIStyle(_gsLabel)
				{
					fontSize = 10
				};
				val6.normal.textColor = CTextDim;
				_gsSmall = val6;
				GUIStyle val7 = new GUIStyle(GUI.skin.button)
				{
					fontSize = 11,
					padding = new RectOffset(8, 8, 4, 4)
				};
				val7.normal.background = _txBgPanel;
				val7.normal.textColor = CText;
				val7.hover.background = _txBgHover;
				val7.hover.textColor = Color.white;
				val7.active.background = _txAccent;
				val7.active.textColor = Color.white;
				_gsBtn = val7;
				_gsIconBtn = new GUIStyle(_gsBtn)
				{
					padding = new RectOffset(0, 0, 0, 0),
					alignment = (TextAnchor)4,
					fontSize = 11
				};
				GUIStyle val8 = new GUIStyle(_gsBtn);
				val8.normal.background = _txAccentDim;
				val8.normal.textColor = Color.white;
				val8.hover.background = _txAccent;
				val8.hover.textColor = Color.white;
				_gsBtnPrimary = val8;
				GUIStyle val9 = new GUIStyle(_gsBtn);
				val9.normal.background = MakeTex(1, 1, new Color(0.4f, 0.08f, 0.08f));
				val9.normal.textColor = CRed;
				val9.hover.background = _txRed;
				val9.hover.textColor = Color.white;
				_gsBtnDanger = val9;
				GUIStyle val10 = new GUIStyle(_gsBtn);
				val10.normal.background = MakeTex(1, 1, new Color(0.3f, 0.24f, 0.04f));
				val10.normal.textColor = CYellow;
				val10.hover.background = _txYellow;
				val10.hover.textColor = new Color(0.08f, 0.06f, 0f);
				_gsBtnYellow = val10;
				GUIStyle val11 = new GUIStyle(_gsBtn);
				val11.normal.background = _txBgPanel;
				val11.normal.textColor = CTextDim;
				val11.hover.background = _txBgHover;
				val11.hover.textColor = CText;
				_gsTabBtn = val11;
				GUIStyle val12 = new GUIStyle(_gsTabBtn)
				{
					fontStyle = (FontStyle)1
				};
				val12.normal.background = _txAccentDim;
				val12.normal.textColor = Color.white;
				_gsTabBtnActive = val12;
				GUIStyle val13 = new GUIStyle(GUI.skin.button)
				{
					fontSize = 11,
					alignment = (TextAnchor)3,
					padding = new RectOffset(10, 6, 4, 4)
				};
				val13.normal.background = background;
				val13.normal.textColor = CTextDim;
				val13.hover.background = _txBgHover;
				val13.hover.textColor = CText;
				val13.active.background = _txAccentDim;
				val13.active.textColor = Color.white;
				_gsNavItem = val13;
				GUIStyle val14 = new GUIStyle(_gsNavItem)
				{
					fontStyle = (FontStyle)1
				};
				val14.normal.background = background3;
				val14.normal.textColor = Color.white;
				val14.hover.background = background3;
				val14.hover.textColor = Color.white;
				_gsNavItemActive = val14;
				GUIStyle val15 = new GUIStyle(GUI.skin.label)
				{
					fontSize = 10,
					alignment = (TextAnchor)4,
					padding = new RectOffset(6, 6, 2, 2),
					margin = new RectOffset(2, 2, 3, 3)
				};
				val15.normal.background = _txBgPanel;
				val15.normal.textColor = CTextDim;
				_gsChip = val15;
				Texture2D background4 = MakeTex(1, 1, new Color(0f, 0f, 0f, 0f));
				GUIStyle val16 = new GUIStyle(GUI.skin.button)
				{
					fontSize = 11,
					alignment = (TextAnchor)3,
					padding = new RectOffset(6, 6, 4, 4)
				};
				val16.normal.background = background4;
				val16.normal.textColor = CText;
				val16.hover.background = _txBgHover;
				val16.hover.textColor = Color.white;
				val16.active.background = _txAccentDim;
				val16.active.textColor = Color.white;
				_gsListItem = val16;
				GUIStyle val17 = new GUIStyle(_gsListItem)
				{
					fontStyle = (FontStyle)1
				};
				val17.normal.background = _txAccentDim;
				val17.normal.textColor = Color.white;
				val17.hover.background = _txAccent;
				val17.hover.textColor = Color.white;
				_gsListItemSel = val17;
				GUIStyle val18 = new GUIStyle(_gsH1)
				{
					fontSize = 13,
					alignment = (TextAnchor)4
				};
				val18.normal.textColor = CAccent;
				_gsModalTitle = val18;
				GUIStyle val19 = new GUIStyle(GUI.skin.box)
				{
					padding = new RectOffset(6, 6, 5, 5)
				};
				val19.normal.background = _txBgPanel;
				val19.normal.textColor = CText;
				_gsPanelBox = val19;
				GUIStyle val20 = new GUIStyle(GUIStyle.none)
				{
					padding = new RectOffset(4, 4, 3, 3)
				};
				val20.normal.background = background;
				_gsRow = val20;
				GUIStyle val21 = new GUIStyle(_gsRow);
				val21.normal.background = background2;
				_gsRowAlt = val21;
			}
		}

		private static Texture2D MakeTex(int w, int h, Color col)
		{
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: 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_002d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: Expected O, but got Unknown
			Color[] array = (Color[])(object)new Color[w * h];
			for (int i = 0; i < array.Length; i++)
			{
				array[i] = col;
			}
			Texture2D val = new Texture2D(w, h);
			val.SetPixels(array);
			val.Apply();
			return val;
		}

		private void DrawDirectorTab(float scrollH)
		{
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0056: Unknown result type (might be due to invalid IL or missing references)
			//IL_004f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0089: Unknown result type (might be due to invalid IL or missing references)
			//IL_00aa: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c9: Unknown result type (might be due to invalid IL or missing references)
			//IL_0297: Unknown result type (might be due to invalid IL or missing references)
			//IL_02b6: Unknown result type (might be due to invalid IL or missing references)
			//IL_02cc: Unknown result type (might be due to invalid IL or missing references)
			//IL_02f0: Unknown result type (might be due to invalid IL or missing references)
			//IL_02f5: Unknown result type (might be due to invalid IL or missing references)
			//IL_040e: Unknown result type (might be due to invalid IL or missing references)
			//IL_042d: Unknown result type (might be due to invalid IL or missing references)
			//IL_033f: Unknown result type (might be due to invalid IL or missing references)
			//IL_038c: Unknown result type (might be due to invalid IL or missing references)
			//IL_03c1: Unknown result type (might be due to invalid IL or missing references)
			//IL_0700: Unknown result type (might be due to invalid IL or missing references)
			//IL_071f: Unknown result type (might be due to invalid IL or missing references)
			//IL_04c8: Unknown result type (might be due to invalid IL or missing references)
			//IL_0516: Unknown result type (might be due to invalid IL or missing references)
			//IL_050f: Unknown result type (might be due to invalid IL or missing references)
			//IL_054d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0587: Unknown result type (might be due to invalid IL or missing references)
			//IL_05aa: Unknown result type (might be due to invalid IL or missing references)
			//IL_05f4: Unknown result type (might be due to invalid IL or missing references)
			//IL_076a: Unknown result type (might be due to invalid IL or missing references)
			//IL_07a0: Unknown result type (might be due to invalid IL or missing references)
			//IL_07d6: Unknown result type (might be due to invalid IL or missing references)
			//IL_07f7: Unknown result type (might be due to invalid IL or missing references)
			//IL_0644: Unknown result type (might be due to invalid IL or missing references)
			//IL_0682: Unknown result type (might be due to invalid IL or missing references)
			//IL_069c: Unknown result type (might be due to invalid IL or missing references)
			bool isDirectorHost = IsDirectorHost;
			GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
			DrawChip(DirectorEnabled ? "smart director on" : "smart director off (random)", DirectorEnabled ? CGreen : CTextDim);
			DrawChip(isDirectorHost ? "you are the host" : "runs on the host", isDirectorHost ? CAccent : CTextDim);
			if (_directorPending.Count > 0)
			{
				DrawChip($"{_directorPending.Count} pending", CYellow);
			}
			GUILayout.FlexibleSpace();
			GUILayout.EndHorizontal();
			GUILayout.Space(3f);
			if (!isDirectorHost)
			{
				GUI.color = CTextDim;
				GUILayout.Label("  Only the host decides what plays. Open this tab as host to see decisions and events.", _gsLabel, Array.Empty<GUILayoutOption>());
				GUI.color = Color.white;
				return;
			}
			bool enabled = SemiFunc.RunIsLevel();
			GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
			GUI.enabled = enabled;
			if (GUILayout.Button("Tick now", _gsBtnPrimary, (GUILayoutOption[])(object)new GUILayoutOption[2]
			{
				GUILayout.Height(22f),
				GUILayout.ExpandWidth(false)
			}))
			{
				HostAuthorityTick();
			}
			GUILayout.Space(6f);
			GUILayout.Label("simulate:", _gsSmall, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.ExpandWidth(false) });
			if (GUILayout.Button("death", _gsBtn, (GUILayoutOption[])(object)new GUILayoutOption[2]
			{
				GUILayout.Height(22f),
				GUILayout.ExpandWidth(false)
			}))
			{
				DirectorSimulate(DirectorEventKind.Death);
			}
			if (GUILayout.Button("hurt", _gsBtn, (GUILayoutOption[])(object)new GUILayoutOption[2]
			{
				GUILayout.Height(22f),
				GUILayout.ExpandWidth(false)
			}))
			{
				DirectorSimulate(DirectorEventKind.Hurt);
			}
			if (GUILayout.Button("spotted", _gsBtn, (GUILayoutOption[])(object)new GUILayoutOption[2]
			{
				GUILayout.Height(22f),
				GUILayout.ExpandWidth(false)
			}))
			{
				DirectorSimulate(DirectorEventKind.Spotted);
			}
			if (GUILayout.Button("break", _gsBtn, (GUILayoutOption[])(object)new GUILayoutOption[2]
			{
				GUILayout.Height(22f),
				GUILayout.ExpandWidth(false)
			}))
			{
				DirectorSimulate(DirectorEventKind.Break);
			}
			if (GUILayout.Button("head", _gsBtn, (GUILayoutOption[])(object)new GUILayoutOption[2]
			{
				GUILayout.Height(22f),
				GUILayout.ExpandWidth(false)
			}))
			{
				DirectorSimulate(DirectorEventKind.HeadTalk);
			}
			if (GUILayout.Button("pickup", _gsBtn, (GUILayoutOption[])(object)new GUILayoutOption[2]
			{
				GUILayout.Height(22f),
				GUILayout.ExpandWidth(false)
			}))
			{
				DirectorSimulate(DirectorEventKind.Pickup);
			}
			GUI.enabled = true;
			GUILayout.FlexibleSpace();
			GUILayout.EndHorizontal();
			GUI.color = CTextDim;
			GUILayout.Label("  Simulations use your own voice and position, fire in ~1s and skip the real delays.", _gsSmall, Array.Empty<GUILayoutOption>());
			GUI.color = Color.white;
			GUILayout.Space(3f);
			_scrollDirector = GUILayout.BeginScrollView(_scrollDirector, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(Mathf.Max(80f, scrollH - 62f)) });
			if (_directorPending.Count > 0)
			{
				DrawSettingsSection("Pending events");
				foreach (DirectorPendingEvent item in _directorPending)
				{
					GUILayout.BeginHorizontal(_gsRow, Array.Empty<GUILayoutOption>());
					GUI.color = CYellow;
					GUILayout.Label($"{Mathf.Max(0f, item.FireAt - Time.time):F1}s", _gsSmall, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(40f) });
					GUI.color = CText;
					GUILayout.Label($"{item.Kind}: {item.Label}", _gsSmall, Array.Empty<GUILayoutOption>());
					GUI.color = Color.white;
					GUILayout.EndHorizontal();
				}
				GUILayout.Space(4f);
			}
			DrawSettingsSection("Decisions");
			if (_directorDecisions.Count == 0)
			{
				GUI.color = CTextDim;
				GUILayout.Label("  Nothing decided yet. Press \"Tick now\" or wait for the timer.", _gsSmall, Array.Empty<GUILayoutOption>());
				GUI.color = Color.white;
			}
			for (int num = _directorDecisions.Count - 1; num >= 0; num--)
			{
				DirectorDecision directorDecision = _directorDecisions[num];
				bool flag = _directorExpandedDecision == num;
				GUILayout.BeginVertical(_gsPanelBox, Array.Empty<GUILayoutOption>());
				GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
				if (GUILayout.Button(flag ? "▼" : "▶", _gsIconBtn, (GUILayoutOption[])(object)new GUILayoutOption[2]
				{
					GUILayout.Width(20f),
					GUILayout.Height(18f)
				}))
				{
					_directorExpandedDecision = (flag ? (-1) : num);
				}
				GUI.color = CTextDim;
				GUILayout.Label(FormatAgo(directorDecision.Time), _gsSmall, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(52f) });
				GUI.color = ((directorDecision.Reason == "timer") ? CAccent : CYellow);
				GUILayout.Label(FitHudText(directorDecision.Reason, 34), _gsSmall, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.ExpandWidth(false) });
				GUILayout.FlexibleSpace();
				GUI.color = CTextDim;
				GUILayout.Label($"score {directorDecision.Score:F2}", _gsSmall, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.ExpandWidth(false) });
				GUI.color = Color.white;
				GUILayout.EndHorizontal();
				GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
				GUILayout.Space(24f);
				GUI.color = CGreen;
				GUILayout.Label(FitHudText(directorDecision.Sound, 22) + "  →  " + FitHudText(directorDecision.Enemies, 30), _gsLabel, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.ExpandWidth(false) });
				GUI.color = CTextDim;
				GUILayout.Label(string.Format("{0} listener{1}", directorDecision.Listeners, (directorDecision.Listeners != 1) ? "s" : ""), _gsSmall, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.ExpandWidth(false) });
				GUI.color = Color.white;
				GUILayout.EndHorizontal();
				if (flag)
				{
					foreach (string detail in directorDecision.Details)
					{
						GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
						GUILayout.Space(24f);
						GUI.color = CTextDim;
						GUILayout.Label(detail, _gsSmall, Array.Empty<GUILayoutOption>());
						GUI.color = Color.white;
						GUILayout.EndHorizontal();
					}
				}
				GUILayout.EndVertical();
				GUILayout.Space(2f);
			}
			GUILayout.Space(4f);
			DrawSettingsSection("Event feed");
			if (_directorFeed.Count == 0)
			{
				GUI.color = CTextDim;
				GUILayout.Label("  No events yet.", _gsSmall, Array.Empty<GUILayoutOption>());
				GUI.color = Color.white;
			}
			for (int num2 = _directorFeed.Count - 1; num2 >= 0; num2--)
			{
				DirectorFeedEntry directorFeedEntry = _directorFeed[num2];
				GUILayout.BeginHorizontal((num2 % 2 == 0) ? _gsRow : _gsRowAlt, Array.Empty<GUILayoutOption>());
				GUI.color = CTextDim;
				GUILayout.Label(FormatAgo(directorFeedEntry.Time), _gsSmall, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(52f) });
				GUI.color = directorFeedEntry.Color;
				GUILayout.Label(FitHudText(directorFeedEntry.Kind, 12), _gsSmall, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(70f) });
				GUI.color = CText;
				GUILayout.Label(directorFeedEntry.Text, _gsSmall, Array.Empty<GUILayoutOption>());
				GUI.color = Color.white;
				GUILayout.EndHorizontal();
			}
			GUILayout.EndScrollView();
		}

		private static string FormatAgo(float time)
		{
			float num = Time.time - time;
			if (!(num < 60f))
			{
				return $"{num / 60f:F0}m ago";
			}
			return $"{num:F0}s ago";
		}

		private void OpenForcePlayModal()
		{
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_0037: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0042: Unknown result type (might be due to invalid IL or missing references)
			//IL_0048: 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)
			//IL_0053: 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)
			_fpmOpen = true;
			_fpmPage = 0;
			_fpmPlayerIdx = -1;
			_fpmClipIdx = -1;
			_fpmEnemyIdx = -1;
			_fpmFilterIdx = -1;
			_fpmHearYourself = true;
			_fpmScrollPlayer = Vector2.zero;
			_fpmScrollClip = Vector2.zero;
			_fpmScrollEnemy = Vector2.zero;
			_fpmScrollFilter = Vector2.zero;
			_fpmPagePlayer = 0;
			_fpmPageClip = 0;
			_fpmPageEnemy = 0;
			_fpmPageFilter = 0;
			BuildFpmPlayerList();
		}

		private void BuildFpmPlayerList()
		{
			string b = ((PhotonNetwork.LocalPlayer != null) ? GetPlayerPersistentId(PhotonNetwork.LocalPlayer) : string.Empty);
			HashSet<string> onlinePlayerIds = GetOnlinePlayerIds();
			Dictionary<string, FpmPlayerEntry> dictionary = new Dictionary<string, FpmPlayerEntry>(StringComparer.OrdinalIgnoreCase);
			for (int i = 0; i < cachedAudio.Count; i++)
			{
				CachedAudioEntry cachedAudioEntry = cachedAudio[i];
				if (cachedAudioEntry != null)
				{
					string text = ((!string.IsNullOrWhiteSpace(cachedAudioEntry.SourcePlayerId)) ? cachedAudioEntry.SourcePlayerId : $"actor_{cachedAudioEntry.SourceActor}");
					string displayName = ((!string.IsNullOrWhiteSpace(cachedAudioEntry.SourceName)) ? cachedAudioEntry.SourceName : text);
					if (!dictionary.TryGetValue(text, out var value))
					{
						value = (dictionary[text] = new FpmPlayerEntry
						{
							PlayerId = text,
							DisplayName = displayName,
							IsLocalPlayer = string.Equals(text, b, StringComparison.OrdinalIgnoreCase),
							IsOnline = onlinePlayerIds.Contains(text)
						});
					}
					value.CacheIndices.Add(i);
				}
			}
			_fpmPlayers = (from p in dictionary.Values
				orderby p.IsOnline descending, p.DisplayName
				select p).ToList();
		}

		private void BuildFpmEnemyList()
		{
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_0064: Unknown result type (might be due to invalid IL or missing references)
			//IL_0069: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c5: Unknown result type (might be due to invalid IL or missing references)
			_fpmEnemies = new List<FpmEnemyEntry>();
			Vector3 position = ((Component)this).transform.position;
			foreach (GameObject item in (from e in GetEnemiesList()
				where (Object)(object)e != (Object)null
				select e).ToList())
			{
				GameObject enemyAudioTarget = GetEnemyAudioTarget(item);
				Vector3 enemyDistancePosition = GetEnemyDistancePosition(item, enemyAudioTarget);
				int playbackTargetKey = GetPlaybackTargetKey(item, enemyAudioTarget);
				float