Decompiled source of OptimizedSkinwalkers v1.1.0

plugins/lynxdev.OptimizedSkinwalkers.dll

Decompiled 3 days ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using Dissonance;
using Dissonance.Config;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using Unity.Netcode;
using UnityEngine;
using UnityEngine.Networking;
using UnityEngine.SceneManagement;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("lynxdev.OptimizedSkinwalkers")]
[assembly: AssemblyConfiguration("Debug")]
[assembly: AssemblyDescription("Attempt to optimize Skinwalkers")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("lynxdev.OptimizedSkinwalkers")]
[assembly: AssemblyTitle("lynxdev.OptimizedSkinwalkers")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.0.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace OptimizedSkinwalkers
{
	[BepInPlugin("lynxdev.OptimizedSkinwalkers", "lynxdev.OptimizedSkinwalkers", "1.0.0")]
	public class OptimizedSkinwalkersPlugin : BaseUnityPlugin
	{
		private readonly Harmony harmony = new Harmony("lynxdev.OptimizedSkinwalkers");

		public static OptimizedSkinwalkersPlugin Instance;

		private void Awake()
		{
			//IL_00c3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c9: Expected O, but got Unknown
			//IL_0100: Unknown result type (might be due to invalid IL or missing references)
			//IL_0105: Unknown result type (might be due to invalid IL or missing references)
			//IL_0108: Unknown result type (might be due to invalid IL or missing references)
			//IL_010b: Invalid comparison between Unknown and I4
			//IL_0116: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)Instance == (Object)null)
			{
				Instance = this;
			}
			else if ((Object)(object)Instance != (Object)(object)this)
			{
				Object.Destroy((Object)(object)this);
				return;
			}
			harmony.PatchAll(Assembly.GetExecutingAssembly());
			InvokeAssemblyMethods();
			SkinwalkerLogger.Initialize("lynxdev.OptimizedSkinwalkers");
			SkinwalkerLogger.Log("SKINWALKER MOD STARTING UP 1.0.0");
			SkinwalkerConfig.InitConfig(((BaseUnityPlugin)this).Config);
			if (SkinwalkerConfig.VoiceLineFrequency.Value == 0f)
			{
				SkinwalkerLogger.LogWarning("VoiceLineFrequency set to 0. Aborting mod initialization");
				return;
			}
			InitializeNetworkVariableSerializationTypes();
			SceneManager.sceneLoaded += SkinwalkerNetworkManagerHandler.ClientConnectInitializer;
			GameObject val = new GameObject("Skinwalker Mod");
			val.AddComponent<SkinwalkerModPersistent>();
			((Object)val).hideFlags = (HideFlags)61;
			Object.DontDestroyOnLoad((Object)(object)val);
			foreach (LogCategory value in Enum.GetValues(typeof(LogCategory)))
			{
				if ((int)value != 0)
				{
					Logs.SetLogLevel(value, (LogLevel)4);
				}
			}
		}

		private void InvokeAssemblyMethods()
		{
			Type[] types = Assembly.GetExecutingAssembly().GetTypes();
			Type[] array = types;
			foreach (Type type in array)
			{
				MethodInfo[] methods = type.GetMethods(BindingFlags.Instance | BindingFlags.Static | BindingFlags.NonPublic);
				MethodInfo[] array2 = methods;
				foreach (MethodInfo methodInfo in array2)
				{
					object[] customAttributes = methodInfo.GetCustomAttributes(typeof(RuntimeInitializeOnLoadMethodAttribute), inherit: false);
					if (customAttributes.Length != 0)
					{
						methodInfo.Invoke(null, null);
					}
				}
			}
		}

		private void InitializeNetworkVariableSerializationTypes()
		{
			NetworkVariableSerializationTypes.InitializeSerializer_UnmanagedByMemcpy<bool>();
			NetworkVariableSerializationTypes.InitializeEqualityChecker_UnmanagedIEquatable<bool>();
			NetworkVariableSerializationTypes.InitializeSerializer_UnmanagedByMemcpy<float>();
			NetworkVariableSerializationTypes.InitializeEqualityChecker_UnmanagedIEquatable<float>();
		}
	}
	public enum VoiceEnabled
	{
		BaboonHawk,
		Bracken,
		BunkerSpider,
		Centipede,
		CoilHead,
		EyelessDog,
		ForestGiant,
		GhostGirl,
		GiantWorm,
		HoardingBug,
		Hygrodere,
		Jester,
		Masked,
		Nutcracker,
		SporeLizard,
		Thumper,
		Butler,
		ButlerBees,
		OldBird,
		FlowerSnake,
		OtherOutsideEnemies,
		OtherInsideEnemies
	}
	public class SkinwalkerBehaviour : MonoBehaviour
	{
		private AudioSource audioSource;

		public const float PLAY_INTERVAL_MIN = 15f;

		public const float PLAY_INTERVAL_MAX = 40f;

		private const float MAX_DIST = 100f;

		private float nextTimeToPlayAudio;

		private EnemyAI ai;

		public void Initialize(EnemyAI ai)
		{
			this.ai = ai;
			audioSource = ai.creatureVoice;
			SetNextTime();
		}

		private void Update()
		{
			if (Time.time > nextTimeToPlayAudio)
			{
				AttemptPlaySound();
				SetNextTime();
			}
		}

		private void AttemptPlaySound()
		{
			//IL_00cb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d8: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)StartOfRound.Instance == (Object)null || (Object)(object)StartOfRound.Instance.localPlayerController == (Object)null || (Object)(object)ai == (Object)null || ai.isEnemyDead)
			{
				return;
			}
			EnemyAI obj = ai;
			DressGirlAI val = (DressGirlAI)(object)((obj is DressGirlAI) ? obj : null);
			if (val == null || (!((Object)(object)val.hauntingPlayer != (Object)(object)StartOfRound.Instance.localPlayerController) && (val.staringInHaunt || ((EnemyAI)val).moveTowardsDestination)))
			{
				Vector3 val2 = (StartOfRound.Instance.localPlayerController.isPlayerDead ? ((Component)StartOfRound.Instance.spectateCamera).transform.position : ((Component)StartOfRound.Instance.localPlayerController).transform.position);
				if (Vector3.Distance(val2, ((Component)this).transform.position) < 100f && SkinwalkerModPersistent.Instance.TryGetSample(out var audioClip))
				{
					audioSource.PlayOneShot(audioClip);
				}
			}
		}

		private void SetNextTime()
		{
			float num = Random.Range(15f, 40f);
			nextTimeToPlayAudio = Time.time + num / SkinwalkerNetworkManager.Instance.VoiceLineFrequency.Value;
		}

		private T CopyComponent<T>(T original, GameObject destination) where T : Component
		{
			Type type = ((object)original).GetType();
			Component val = destination.AddComponent(type);
			FieldInfo[] fields = type.GetFields();
			FieldInfo[] array = fields;
			foreach (FieldInfo fieldInfo in array)
			{
				fieldInfo.SetValue(val, fieldInfo.GetValue(original));
			}
			T val2 = (T)(object)((val is T) ? val : null);
			return (val2 != null) ? val2 : default(T);
		}
	}
	public static class SkinwalkerConfig
	{
		public const float DEFAULT_FOLDER_SCAN_INTERVAL = 8f;

		public const int CUSTOM_SOUND_FREQUENCY_MIN = 0;

		public const int CUSTOM_SOUND_FREQUENCY_MAX = 100;

		private const float DEFAULT_FREQUENCY = 1f;

		private const string EXTRA_SETTINGS = "Extra Settings";

		public static ConfigEntry<float> VoiceLineFrequency;

		public static ConfigEntry<bool> KeepFilesBetweenSessions;

		public static ConfigEntry<float> TimeForFileCaching;

		public static ConfigEntry<bool> AddCustomFiles;

		public static ConfigEntry<float> CustomSoundFrequency;

		public static Dictionary<VoiceEnabled, ConfigEntry<bool>> ConfigEntries = new Dictionary<VoiceEnabled, ConfigEntry<bool>>();

		public static void InitConfig(ConfigFile configFile)
		{
			VoiceLineFrequency = configFile.Bind<float>("Voice Settings", "VoiceLineFrequency", 1f, $"{1f} is the default, and voice lines will occur every {15f} to {40f} seconds per enemy." + "\nSetting this to 2 means they will occur twice as often, 0.5 means half as often, etc.\nSetting this to 0 disables the mod.");
			SkinwalkerLogger.Log($"VoiceLineFrequency; VALUE LOADED FROM CONFIG: {VoiceLineFrequency.Value}");
			GenerateMonsterVoicesConfig(configFile);
			KeepFilesBetweenSessions = configFile.Bind<bool>("Extra Settings", "Keep Files Between Sessions", false, "If set to true, the content of Dissonance_Diagnostics won't be deleted on boot, keeping remaining sound files from previous sessions.");
			SkinwalkerLogger.Log($"KeepFilesBetweenSessions; VALUE LOADED FROM CONFIG: {KeepFilesBetweenSessions.Value}");
			TimeForFileCaching = configFile.Bind<float>("Extra Settings", "Time For File Caching", 8f, "Dictates the interval (in seconds) at which we collect player recordings. Once recordings are collected, they're immediately deleted.\nA higher number would increase the likelyhood of clips remaining for future sessions." + $"\nValues under the default {8f} seconds will be ignored.");
			SkinwalkerLogger.Log($"TimeForFileCaching; VALUE LOADED FROM CONFIG: {TimeForFileCaching.Value}");
			AddCustomFiles = configFile.Bind<bool>("Extra Settings", "Add custom sounds", false, "If set to true, will create a folder Custom_Sounds in which you can put your own audio files.\nNote that other players won't be able to hear these sounds, only you, therefore the folder content should be shared between players.\nUnlike the recorded voice lines, these files won't be deleted.");
			SkinwalkerLogger.Log($"AddCustomFiles; VALUE LOADED FROM CONFIG: {AddCustomFiles.Value}");
			CustomSoundFrequency = configFile.Bind<float>("Extra Settings", "Custom sounds frequency", 50f, $"Value between {0} and {100}. Dictates the frequency at which to play custom sounds vs recorded lines." + $"\nIf set to {0}, only the recorded lines will play, deactivating the previous option." + $"\nIf set to {100}, only the custom sounds will play, disabling the voice line recording.");
			SkinwalkerLogger.Log($"CustomSoundFrequency; VALUE LOADED FROM CONFIG: {CustomSoundFrequency.Value}");
		}

		private static void GenerateMonsterVoicesConfig(ConfigFile configFile)
		{
			foreach (VoiceEnabled value2 in Enum.GetValues(typeof(VoiceEnabled)))
			{
				string text = "";
				bool flag;
				switch (value2)
				{
				case VoiceEnabled.OtherOutsideEnemies:
					flag = false;
					text = "Every OUTSIDE enemies that aren't in the list above.";
					break;
				case VoiceEnabled.OtherInsideEnemies:
					flag = true;
					text = "Every INSIDE enemies that aren't in the list above.";
					break;
				default:
					flag = true;
					break;
				}
				ConfigEntry<bool> value = configFile.Bind<bool>("Monster Voices", value2.ToString(), flag, text);
				ConfigEntries.Add(value2, value);
				SkinwalkerLogger.Log($"VoiceEnabled_{value2}; VALUE LOADED FROM CONFIG: {ConfigEntries[value2].Value}");
			}
		}
	}
	public static class SkinwalkerLogger
	{
		internal static ManualLogSource logSource;

		public static void Initialize(string modGUID)
		{
			logSource = Logger.CreateLogSource(modGUID);
		}

		public static void Log(object message)
		{
			logSource.LogInfo(message);
		}

		public static void LogError(object message)
		{
			logSource.LogError(message);
		}

		public static void LogWarning(object message)
		{
			logSource.LogWarning(message);
		}
	}
	public class SkinwalkerModPersistent : MonoBehaviour
	{
		private const int MAX_CACHED_AUDIO = 200;

		private List<AudioClip> cachedRecordedAudio = new List<AudioClip>();

		private List<AudioClip> cachedPersistentAudio = new List<AudioClip>();

		private RoundManager roundManager;

		private bool isCleaningAudioCache;

		private string recordedAudioFolderPath;

		private string persistentAudioFolderPath;

		private int skinwalkerCheckedCount;

		private float folderScanRate;

		private float nextTimeToCheckFolder;

		public static SkinwalkerModPersistent Instance { get; private set; }

		private bool IsVoiceRecordingEnabled => !SkinwalkerConfig.AddCustomFiles.Value || !(SkinwalkerConfig.CustomSoundFrequency.Value >= 100f);

		private bool AreCustomSoundsEnabled => SkinwalkerConfig.AddCustomFiles.Value && SkinwalkerConfig.CustomSoundFrequency.Value > 0f;

		private void Awake()
		{
			//IL_007a: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)Instance == (Object)null)
			{
				Instance = this;
			}
			else if ((Object)(object)Instance != (Object)(object)this)
			{
				Object.Destroy((Object)(object)this);
			}
			SkinwalkerLogger.Log("SkinwalkerModPersistent Initialized");
			SkinwalkerLogger.Log($"IsVoiceRecordingEnabled {IsVoiceRecordingEnabled}");
			SkinwalkerLogger.Log($"AreCustomSoundsEnabled {AreCustomSoundsEnabled}");
			((Component)this).transform.position = Vector3.zero;
			recordedAudioFolderPath = Path.Combine(Application.dataPath, "..", "Dissonance_Diagnostics");
			persistentAudioFolderPath = Path.Combine(Application.dataPath, "..", "Custom_Sounds");
			InitializeAudioFolders();
			folderScanRate = Mathf.Max(8f, SkinwalkerConfig.TimeForFileCaching.Value);
			if (IsVoiceRecordingEnabled)
			{
				EnableRecording();
			}
		}

		private IEnumerator Start()
		{
			if (AreCustomSoundsEnabled)
			{
				string[] audioFilePaths = Directory.GetFiles(persistentAudioFolderPath);
				yield return ((MonoBehaviour)this).StartCoroutine(CacheWavFile(audioFilePaths, cachedPersistentAudio, deleteAfterCaching: false));
			}
		}

		private void Update()
		{
			if ((!IsVoiceRecordingEnabled || Directory.Exists(recordedAudioFolderPath)) && (!AreCustomSoundsEnabled || Directory.Exists(persistentAudioFolderPath)))
			{
				if (Time.realtimeSinceStartup > nextTimeToCheckFolder)
				{
					nextTimeToCheckFolder = Time.realtimeSinceStartup + folderScanRate;
					ScanWavFiles();
				}
				HandleRoundManagerState();
				HandleSkinwalkerBehaviour();
			}
		}

		private void OnApplicationQuit()
		{
			DisableRecording();
			if (!SkinwalkerConfig.KeepFilesBetweenSessions.Value && Directory.Exists(recordedAudioFolderPath))
			{
				Directory.Delete(recordedAudioFolderPath, recursive: true);
			}
		}

		private void HandleRoundManagerState()
		{
			if ((Object)(object)roundManager == (Object)null && (Object)(object)RoundManager.Instance != (Object)null)
			{
				roundManager = RoundManager.Instance;
				skinwalkerCheckedCount = RoundManager.Instance.SpawnedEnemies.Count;
			}
		}

		private void HandleSkinwalkerBehaviour()
		{
			if ((Object)(object)RoundManager.Instance == (Object)null)
			{
				return;
			}
			int count = RoundManager.Instance.SpawnedEnemies.Count;
			if (skinwalkerCheckedCount == count)
			{
				return;
			}
			if (skinwalkerCheckedCount < count)
			{
				SkinwalkerBehaviour skinwalkerBehaviour = default(SkinwalkerBehaviour);
				foreach (EnemyAI spawnedEnemy in RoundManager.Instance.SpawnedEnemies)
				{
					if (IsEnemyEnabled(spawnedEnemy) && !((Component)spawnedEnemy).TryGetComponent<SkinwalkerBehaviour>(ref skinwalkerBehaviour))
					{
						((Component)spawnedEnemy).gameObject.AddComponent<SkinwalkerBehaviour>().Initialize(spawnedEnemy);
					}
				}
			}
			skinwalkerCheckedCount = count;
		}

		private void InitializeAudioFolders()
		{
			if (IsVoiceRecordingEnabled)
			{
				if (!Directory.Exists(recordedAudioFolderPath))
				{
					Directory.CreateDirectory(recordedAudioFolderPath);
				}
				else if (!SkinwalkerConfig.KeepFilesBetweenSessions.Value)
				{
					Directory.Delete(recordedAudioFolderPath, recursive: true);
					Directory.CreateDirectory(recordedAudioFolderPath);
				}
			}
			if (AreCustomSoundsEnabled && !Directory.Exists(persistentAudioFolderPath))
			{
				Directory.CreateDirectory(persistentAudioFolderPath);
			}
		}

		private void EnableRecording()
		{
			DebugSettings.Instance.EnablePlaybackDiagnostics = true;
			DebugSettings.Instance.RecordFinalAudio = true;
		}

		private void ScanWavFiles()
		{
			string[] files = Directory.GetFiles(recordedAudioFolderPath);
			if (files.Length != 0)
			{
				((MonoBehaviour)this).StartCoroutine(CacheWavFile(files, cachedRecordedAudio, deleteAfterCaching: true));
			}
		}

		private bool IsEnemyEnabled(EnemyAI enemy)
		{
			if ((Object)(object)enemy == (Object)null)
			{
				SkinwalkerLogger.LogError("enemy was null");
				return false;
			}
			if (!(enemy is MaskedPlayerEnemy))
			{
				if (!(enemy is NutcrackerEnemyAI))
				{
					if (!(enemy is BaboonBirdAI))
					{
						if (!(enemy is FlowermanAI))
						{
							if (!(enemy is SandSpiderAI))
							{
								if (!(enemy is CentipedeAI))
								{
									if (!(enemy is SpringManAI))
									{
										if (!(enemy is MouthDogAI))
										{
											if (!(enemy is ForestGiantAI))
											{
												if (!(enemy is DressGirlAI))
												{
													if (!(enemy is SandWormAI))
													{
														if (!(enemy is HoarderBugAI))
														{
															if (!(enemy is BlobAI))
															{
																if (!(enemy is JesterAI))
																{
																	if (!(enemy is PufferAI))
																	{
																		if (!(enemy is CrawlerAI))
																		{
																			if (!(enemy is ButlerEnemyAI))
																			{
																				if (!(enemy is ButlerBeesEnemyAI))
																				{
																					if (!(enemy is RadMechAI))
																					{
																						if (enemy is FlowerSnakeEnemy)
																						{
																							return SkinwalkerNetworkManager.Instance.NetworkVariables[VoiceEnabled.FlowerSnake].Value;
																						}
																						if (enemy.enemyType.isOutsideEnemy)
																						{
																							return SkinwalkerNetworkManager.Instance.NetworkVariables[VoiceEnabled.OtherOutsideEnemies].Value;
																						}
																						return SkinwalkerNetworkManager.Instance.NetworkVariables[VoiceEnabled.OtherInsideEnemies].Value;
																					}
																					return SkinwalkerNetworkManager.Instance.NetworkVariables[VoiceEnabled.OldBird].Value;
																				}
																				return SkinwalkerNetworkManager.Instance.NetworkVariables[VoiceEnabled.ButlerBees].Value;
																			}
																			return SkinwalkerNetworkManager.Instance.NetworkVariables[VoiceEnabled.Butler].Value;
																		}
																		return SkinwalkerNetworkManager.Instance.NetworkVariables[VoiceEnabled.Thumper].Value;
																	}
																	return SkinwalkerNetworkManager.Instance.NetworkVariables[VoiceEnabled.SporeLizard].Value;
																}
																return SkinwalkerNetworkManager.Instance.NetworkVariables[VoiceEnabled.Jester].Value;
															}
															return SkinwalkerNetworkManager.Instance.NetworkVariables[VoiceEnabled.Hygrodere].Value;
														}
														return SkinwalkerNetworkManager.Instance.NetworkVariables[VoiceEnabled.HoardingBug].Value;
													}
													return SkinwalkerNetworkManager.Instance.NetworkVariables[VoiceEnabled.GiantWorm].Value;
												}
												return SkinwalkerNetworkManager.Instance.NetworkVariables[VoiceEnabled.GhostGirl].Value;
											}
											return SkinwalkerNetworkManager.Instance.NetworkVariables[VoiceEnabled.ForestGiant].Value;
										}
										return SkinwalkerNetworkManager.Instance.NetworkVariables[VoiceEnabled.EyelessDog].Value;
									}
									return SkinwalkerNetworkManager.Instance.NetworkVariables[VoiceEnabled.CoilHead].Value;
								}
								return SkinwalkerNetworkManager.Instance.NetworkVariables[VoiceEnabled.Centipede].Value;
							}
							return SkinwalkerNetworkManager.Instance.NetworkVariables[VoiceEnabled.BunkerSpider].Value;
						}
						return SkinwalkerNetworkManager.Instance.NetworkVariables[VoiceEnabled.Bracken].Value;
					}
					return SkinwalkerNetworkManager.Instance.NetworkVariables[VoiceEnabled.BaboonHawk].Value;
				}
				return SkinwalkerNetworkManager.Instance.NetworkVariables[VoiceEnabled.Nutcracker].Value;
			}
			return SkinwalkerNetworkManager.Instance.NetworkVariables[VoiceEnabled.Masked].Value;
		}

		private IEnumerator CacheWavFile(string[] paths, List<AudioClip> referencedList, bool deleteAfterCaching)
		{
			foreach (string path in paths)
			{
				UnityWebRequest request = UnityWebRequestMultimedia.GetAudioClip(path, (AudioType)20);
				yield return request.SendWebRequest();
				while ((int)request.result == 0)
				{
					yield return null;
				}
				if ((int)request.result != 1)
				{
					SkinwalkerLogger.LogWarning($"Request failed for file at path: {path}\n Request Result: {request.result}");
					continue;
				}
				AudioClip audioClip = DownloadHandlerAudioClip.GetContent(request);
				if (audioClip.length > 0.9f)
				{
					referencedList.Add(audioClip);
				}
				if (deleteAfterCaching)
				{
					File.Delete(path);
				}
				request.Dispose();
			}
			if (!isCleaningAudioCache && cachedRecordedAudio.Count > 200)
			{
				((MonoBehaviour)this).StartCoroutine(CleanAudioCache());
			}
		}

		private void DisableRecording()
		{
			DebugSettings.Instance.EnablePlaybackDiagnostics = false;
			DebugSettings.Instance.RecordFinalAudio = false;
		}

		public bool TryGetSample(out AudioClip audioClip)
		{
			audioClip = null;
			bool flag;
			List<AudioClip> list;
			if (IsVoiceRecordingEnabled && AreCustomSoundsEnabled)
			{
				float num = Random.Range(0, 101);
				flag = num > SkinwalkerConfig.CustomSoundFrequency.Value;
				list = (flag ? cachedRecordedAudio : cachedPersistentAudio);
			}
			else if (IsVoiceRecordingEnabled)
			{
				list = cachedRecordedAudio;
				flag = true;
			}
			else
			{
				list = cachedPersistentAudio;
				flag = false;
			}
			if (list.Count == 0)
			{
				return false;
			}
			int index = Random.Range(0, list.Count);
			audioClip = list[index];
			if (flag)
			{
				list.RemoveAt(index);
			}
			if ((Object)(object)audioClip == (Object)null)
			{
				SkinwalkerLogger.LogWarning("TryGetSample.audioClip was null");
				return false;
			}
			return true;
		}

		private IEnumerator CleanAudioCache()
		{
			isCleaningAudioCache = true;
			while (cachedRecordedAudio.Count > 200)
			{
				cachedRecordedAudio.RemoveAt(Random.Range(0, cachedRecordedAudio.Count));
				yield return null;
			}
			isCleaningAudioCache = false;
		}

		public void ClearCache()
		{
			cachedRecordedAudio.Clear();
		}
	}
	public class SkinwalkerNetworkManager : NetworkBehaviour
	{
		public Dictionary<VoiceEnabled, NetworkVariable<bool>> NetworkVariables = new Dictionary<VoiceEnabled, NetworkVariable<bool>>();

		public NetworkVariable<float> VoiceLineFrequency;

		public static SkinwalkerNetworkManager Instance { get; private set; }

		private void Awake()
		{
			if ((Object)(object)Instance == (Object)null)
			{
				Instance = this;
			}
			else if ((Object)(object)Instance != (Object)(object)this)
			{
				Object.Destroy((Object)(object)this);
				return;
			}
			SkinwalkerLogger.Log("SkinwalkerNetworkManager Awake Called");
			VoiceLineFrequency = new NetworkVariable<float>(1f, (NetworkVariableReadPermission)0, (NetworkVariableWritePermission)0);
			BuildNetworkVariableDict();
		}

		public override void OnDestroy()
		{
			SkinwalkerLogger.Log("SkinwalkerNetworkManager OnDestroy");
			if ((Object)(object)SkinwalkerModPersistent.Instance != (Object)null)
			{
				SkinwalkerModPersistent.Instance.ClearCache();
			}
			Instance = null;
			((NetworkBehaviour)this).OnDestroy();
		}

		public override void OnNetworkSpawn()
		{
			SkinwalkerLogger.Log("OnNetworkSpawn");
			SetupConfig();
		}

		protected override void __initializeVariables()
		{
			SkinwalkerLogger.Log("called __initializeVariables");
			if (VoiceLineFrequency == null)
			{
				SkinwalkerLogger.LogError("SkinwalkerNetworkManager.VoiceLineFrequency cannot be null. All NetworkVariableBase instances must be initialized.");
				return;
			}
			((NetworkVariableBase)VoiceLineFrequency).Initialize((NetworkBehaviour)(object)this);
			((NetworkBehaviour)this).__nameNetworkVariable((NetworkVariableBase)(object)VoiceLineFrequency, "VoiceEnabled_VoiceLineFrequency");
			base.NetworkVariableFields.Add((NetworkVariableBase)(object)VoiceLineFrequency);
			for (int i = 0; i < NetworkVariables.Count; i++)
			{
				VoiceEnabled voiceEnabled = (VoiceEnabled)i;
				if (NetworkVariables[voiceEnabled] == null)
				{
					SkinwalkerLogger.LogError($"SkinwalkerNetworkManager.NetworkVariables.Key:{voiceEnabled} cannot be null. All NetworkVariableBase instances must be initialized.");
					break;
				}
				((NetworkVariableBase)NetworkVariables[voiceEnabled]).Initialize((NetworkBehaviour)(object)this);
				((NetworkBehaviour)this).__nameNetworkVariable((NetworkVariableBase)(object)NetworkVariables[voiceEnabled], "VoiceEnabled_" + voiceEnabled);
				base.NetworkVariableFields.Add((NetworkVariableBase)(object)NetworkVariables[voiceEnabled]);
			}
		}

		protected override string __getTypeName()
		{
			return "SkinwalkerNetworkManager";
		}

		private void BuildNetworkVariableDict()
		{
			for (int i = 0; i < Enum.GetValues(typeof(VoiceEnabled)).Length; i++)
			{
				VoiceEnabled key = (VoiceEnabled)i;
				NetworkVariable<bool> value = new NetworkVariable<bool>(true, (NetworkVariableReadPermission)0, (NetworkVariableWritePermission)0);
				NetworkVariables.Add(key, value);
			}
		}

		private void SetupConfig()
		{
			SkinwalkerLogger.Log("SetupConfig");
			if (GameNetworkManager.Instance.isHostingGame)
			{
				SkinwalkerLogger.Log("HOST SENDING CONFIG TO CLIENTS...");
				VoiceLineFrequency.Value = SkinwalkerConfig.VoiceLineFrequency.Value;
				for (int i = 0; i < NetworkVariables.Count; i++)
				{
					VoiceEnabled voiceEnabled = (VoiceEnabled)i;
					if (NetworkVariables[voiceEnabled] == null)
					{
						SkinwalkerLogger.LogError($"SkinwalkerNetworkManager.NetworkVariables.Key:{voiceEnabled} was null");
						return;
					}
					NetworkVariables[voiceEnabled].Value = SkinwalkerConfig.ConfigEntries[voiceEnabled].Value;
				}
				SkinwalkerLogger.Log("CONFIG SENT...");
			}
			else
			{
				SkinwalkerLogger.Log("Not the host, no config to send");
			}
		}
	}
	public class SkinwalkerNetworkManagerHandler
	{
		public static void ClientConnectInitializer(Scene sceneName, LoadSceneMode _)
		{
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: Expected O, but got Unknown
			if (((Scene)(ref sceneName)).name == "SampleSceneRelay")
			{
				GameObject val = new GameObject("SkinwalkerNetworkManager");
				val.AddComponent<NetworkObject>();
				val.AddComponent<SkinwalkerNetworkManager>();
				Debug.Log((object)"Initialized SkinwalkerNetworkManager");
			}
		}
	}
	public static class PluginInfo
	{
		public const string PLUGIN_GUID = "lynxdev.OptimizedSkinwalkers";

		public const string PLUGIN_NAME = "lynxdev.OptimizedSkinwalkers";

		public const string PLUGIN_VERSION = "1.0.0";
	}
}