Please disclose if any significant portion of your mod was created using AI tools by adding the 'AI Generated' category. Failing to do so may result in the mod being removed from Thunderstore.
Decompiled source of OptimizeSkinWalkers v1.0.1
plugins/OptimizeSkinWalkers.dll
Decompiled 2 years agousing 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("OptimizeSkinWalkers")] [assembly: AssemblyConfiguration("Debug")] [assembly: AssemblyDescription("Skinwalker Optimisation attempt")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0")] [assembly: AssemblyProduct("OptimizeSkinWalkers")] [assembly: AssemblyTitle("OptimizeSkinWalkers")] [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 OptimizeSkinWalkers { [BepInPlugin("OptimizeSkinWalkers", "OptimizeSkinWalkers", "1.0.0")] public class OptimizeSkinWalker : BaseUnityPlugin { private readonly Harmony harmony = new Harmony("lynxdev.OptimizeSkinWalker"); public static OptimizeSkinWalker Instance; private void Awake() { //IL_009d: Unknown result type (might be due to invalid IL or missing references) //IL_00a3: Expected O, but got Unknown //IL_00d8: Unknown result type (might be due to invalid IL or missing references) //IL_00dd: Unknown result type (might be due to invalid IL or missing references) //IL_00e0: Unknown result type (might be due to invalid IL or missing references) //IL_00e3: Invalid comparison between Unknown and I4 //IL_00ee: 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(); InitializeNetworkVariableSerializationTypes(); SkinwalkerLogger.Initialize("OptimizeSkinWalkers"); SkinwalkerLogger.Log("SKINWALKER MOD STARTING UP 1.0.0"); SkinwalkerConfig.InitConfig(((BaseUnityPlugin)this).Config); 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() { if (SkinwalkerNetworkManager.Instance.VoiceLineFrequency.Value <= 0f) { nextTimeToPlayAudio = Time.time + 100000000f; } else { nextTimeToPlayAudio = Time.time + Random.Range(15f, 40f) / 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; FieldInfo[] array2 = array; foreach (FieldInfo fieldInfo in array2) { fieldInfo.SetValue(val, fieldInfo.GetValue(original)); } return (T)(object)((val is T) ? val : null); } } public static class SkinwalkerConfig { public static Dictionary<VoiceEnabled, ConfigEntry<bool>> ConfigEntries = new Dictionary<VoiceEnabled, ConfigEntry<bool>>(); public static ConfigEntry<float> VoiceLineFrequency; public static void InitConfig(ConfigFile configFile) { VoiceLineFrequency = configFile.Bind<float>("Voice Settings", "VoiceLineFrequency", 1f, "1 is the default, and voice lines will occur every " + 15f + " to " + 40f + " seconds per enemy. Setting this to 2 means they will occur twice as often, 0.5 means half as often, etc."); SkinwalkerLogger.Log($"VoiceLineFrequency; VALUE LOADED FROM CONFIG: {VoiceLineFrequency.Value}"); foreach (VoiceEnabled value2 in Enum.GetValues(typeof(VoiceEnabled))) { string text = ""; bool flag; switch (value2) { case VoiceEnabled.OtherOutsideEnemies: text = "Every outside enemies that aren't in the list above"; flag = false; 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 const float FOLDER_SCAN_INTERVAL = 8f; private List<AudioClip> cachedAudio = new List<AudioClip>(); private RoundManager roundManager; private bool cleaningAudioCache; private string audioFolderPath; private int skinwalkerCheckedCount; private float nextTimeToCheckFolder; public static SkinwalkerModPersistent Instance { get; private set; } private void Awake() { //IL_0044: 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("Skinwalker Mod Object Initialized"); ((Component)this).transform.position = Vector3.zero; audioFolderPath = Path.Combine(Application.dataPath, "..", "Dissonance_Diagnostics"); InitializeAudioFolder(); EnableRecording(); } private void Update() { if (Directory.Exists(audioFolderPath)) { if (Time.realtimeSinceStartup > nextTimeToCheckFolder) { nextTimeToCheckFolder = Time.realtimeSinceStartup + 8f; ScanWavFiles(); } HandleRoundManagerState(); HandleSkinwalkerBehaviour(); } } private void OnApplicationQuit() { DisableRecording(); if (Directory.Exists(audioFolderPath)) { Directory.Delete(audioFolderPath, 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 InitializeAudioFolder() { if (Directory.Exists(audioFolderPath)) { Directory.Delete(audioFolderPath, recursive: true); } Directory.CreateDirectory(audioFolderPath); } private void EnableRecording() { DebugSettings.Instance.EnablePlaybackDiagnostics = true; DebugSettings.Instance.RecordFinalAudio = true; } private void ScanWavFiles() { string[] files = Directory.GetFiles(audioFolderPath); string[] array = files; foreach (string path in array) { ((MonoBehaviour)this).StartCoroutine(CacheWavFile(path)); } } 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 path) { UnityWebRequest request = UnityWebRequestMultimedia.GetAudioClip(path, (AudioType)20); yield return request.SendWebRequest(); while ((int)request.result == 0) { yield return null; } if ((int)request.result == 1) { AudioClip audioClip = DownloadHandlerAudioClip.GetContent(request); if (audioClip.length > 0.9f) { cachedAudio.Add(audioClip); } File.Delete(path); request.Dispose(); } } private void DisableRecording() { DebugSettings.Instance.EnablePlaybackDiagnostics = false; DebugSettings.Instance.RecordFinalAudio = false; } public bool TryGetSample(out AudioClip audioClip) { audioClip = null; if (cachedAudio.Count > 0) { int index = Random.Range(0, cachedAudio.Count - 1); audioClip = cachedAudio[index]; cachedAudio.RemoveAt(index); if (!cleaningAudioCache && cachedAudio.Count > 200) { ((MonoBehaviour)this).StartCoroutine(CleanAudioCache()); } if ((Object)(object)audioClip == (Object)null) { return false; } return true; } return false; } private IEnumerator CleanAudioCache() { cleaningAudioCache = true; while (cachedAudio.Count > 200) { cachedAudio.RemoveAt(Random.Range(0, cachedAudio.Count)); yield return null; } cleaningAudioCache = false; } public void ClearCache() { cachedAudio.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("__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 = "OptimizeSkinWalkers"; public const string PLUGIN_NAME = "OptimizeSkinWalkers"; public const string PLUGIN_VERSION = "1.0.0"; } }