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 AspectNotifications Stand A Lone v0.1.0
AspectNotifications_Stand_A_Lone.dll
Decompiled a day agousing System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Versioning; using System.Text; using BepInEx; using BepInEx.Bootstrap; using BepInEx.Configuration; using HarmonyLib; using Microsoft.CodeAnalysis; using RiskOfOptions; using RiskOfOptions.OptionConfigs; using RiskOfOptions.Options; using RoR2; using UnityEngine; using UnityEngine.Events; [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("AspectNotifications_Stand_A_Lone")] [assembly: AssemblyConfiguration("Debug")] [assembly: AssemblyFileVersion("0.0.3.0")] [assembly: AssemblyInformationalVersion("0.0.3")] [assembly: AssemblyProduct("AspectNotifications_Stand_A_Lone")] [assembly: AssemblyTitle("AspectNotifications_Stand_A_Lone")] [assembly: AssemblyVersion("0.0.3.0")] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace AspectNotifications_Stand_A_Lone { [BepInPlugin("ChronicRick.AspectNotifications_Stand_A_Lone", "AspectNotifications_Stand_A_Lone", "0.1.0")] [BepInDependency(/*Could not decode attribute arguments.*/)] public sealed class Plugin : BaseUnityPlugin { private sealed class WindowsSound { public string Alias; public float Started; public float ExpectedSeconds; } private enum SoundSlot { S0, S1, S2, S3, S4, S5, S6, S7, S8, S9, S10, S11, S12, S13, S14, S15, S16, S17, S18, S19, S20, S21, S22, S23, S24, S25, S26, S27, S28, S29, S30, S31, S32, S33, S34, S35, S36, S37, S38, S39, S40, S41, S42, S43, S44, S45, S46, S47, S48, S49, S50, S51, S52, S53, S54, S55, S56, S57, S58, S59, S60, S61, S62, S63 } private sealed class Mp3DropdownOption : ChoiceOption { private readonly ConfigEntry<string> filename; private readonly List<string> filenames; private const int Capacity = 64; public override object Value { get { if (string.Equals(filename.Value, "Shuffle All", StringComparison.OrdinalIgnoreCase)) { return SoundSlot.S0; } int num = filenames.FindIndex((string f) => f.Equals(filename.Value, StringComparison.OrdinalIgnoreCase)); return (num >= 0 && num < 63) ? ((SoundSlot)(num + 1)) : SoundSlot.S0; } set { int num = Convert.ToInt32(value); filename.Value = ((num > 0 && num <= filenames.Count) ? filenames[num - 1] : "Shuffle All"); } } public int VisibleCount => Math.Min(64, filenames.Count + 1); public Mp3DropdownOption(ConfigEntry<string> filename, List<string> filenames) : base(new ChoiceConfig { name = "Select Sound", category = "Settings", description = "Choose Shuffle All or an MP3 file." }, (object)SoundSlot.S0) { //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_0011: 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_0032: Expected O, but got Unknown this.filename = filename; this.filenames = filenames; } protected override void SetProperties() { ((BaseOption)this).SetCategoryName("Settings", ((BaseOption)this).GetConfig()); ((BaseOption)this).SetName("Select Sound", ((BaseOption)this).GetConfig()); ((BaseOption)this).SetDescription("Choose Shuffle All or an MP3 file.", ((BaseOption)this).GetConfig()); } public override GameObject CreateOptionGameObject(GameObject prefab, Transform parent) { GameObject val = ((ChoiceOption)this).CreateOptionGameObject(prefab, parent); SoundDropdownLimiter soundDropdownLimiter = val.AddComponent<SoundDropdownLimiter>(); soundDropdownLimiter.dropdown = FindDropdown(val); soundDropdownLimiter.option = this; return val; } private static Component FindDropdown(GameObject obj) { Type type = typeof(ModSettingsManager).Assembly.GetType("RiskOfOptions.Components.Options.RooDropdown"); if (type == null) { type = typeof(ModSettingsManager).Assembly.GetTypes().FirstOrDefault((Type t) => t.Name == "RooDropdown"); } return (type == null) ? null : obj.GetComponentInChildren(type); } public void RefreshLabels() { if (string.IsNullOrEmpty(((BaseOption)this).ModGuid)) { return; } for (int i = 0; i < 64; i++) { string key = ("RISK_OF_OPTIONS." + ((BaseOption)this).ModGuid + "." + ((BaseOption)this).Category + "." + ((BaseOption)this).Name + "." + ((BaseOption)this).OptionTypeName + ".item.S" + i).Replace(" ", "_").ToUpperInvariant(); string value = ((i == 0) ? "Shuffle All" : ((i <= filenames.Count) ? filenames[i - 1] : "(unused)")); Type type = typeof(ModSettingsManager).Assembly.GetType("RiskOfOptions.Lib.LanguageApi"); FieldInfo fieldInfo = ((type == null) ? null : type.GetField("LanguageEntries", BindingFlags.Static | BindingFlags.NonPublic)); IDictionary dictionary = ((fieldInfo == null) ? null : (fieldInfo.GetValue(null) as IDictionary)); if (dictionary != null) { dictionary[key] = value; } } if (filenames.Count >= 64) { ((BaseUnityPlugin)instance).Logger.LogWarning((object)"[AUDIO] Dropdown supports the first 63 MP3 files; Shuffle All still uses every playable file."); } } } private sealed class SoundDropdownLimiter : MonoBehaviour { public Component dropdown; public Mp3DropdownOption option; private int previousCount = -1; private void LateUpdate() { if ((Object)(object)dropdown == (Object)null || option == null) { return; } int visibleCount = option.VisibleCount; PropertyInfo property = ((object)dropdown).GetType().GetProperty("choices"); if (!(property == null)) { string[] array = property.GetValue(dropdown, null) as string[]; if (array != null && array.Length >= visibleCount && (previousCount != visibleCount || array.Length != visibleCount)) { Array.Resize(ref array, visibleCount); property.SetValue(dropdown, array, null); previousCount = visibleCount; } } } } public const string Guid = "ChronicRick.AspectNotifications_Stand_A_Lone"; public const string Name = "AspectNotifications_Stand_A_Lone"; public const string Version = "0.1.0"; private static Plugin instance; private Harmony harmony; private string soundsPath; private ConfigEntry<float> volume; private ConfigEntry<string> folderPath; private ConfigEntry<string> playableStatus; private ConfigEntry<string> selected; private readonly List<string> playable = new List<string>(); private readonly HashSet<int> seen = new HashSet<int>(); private readonly Queue<int> seenOrder = new Queue<int>(); private readonly List<WindowsSound> active = new List<WindowsSound>(); private WindowsSound preview; private Mp3DropdownOption soundSelector; private bool scanRunning; private bool scanAgain; private int nextSoundId; private float nextCleanup; [DllImport("winmm.dll", CharSet = CharSet.Unicode, EntryPoint = "mciSendStringW")] private static extern uint MciSendString(string command, StringBuilder result, uint resultLength, IntPtr callback); [DllImport("winmm.dll", CharSet = CharSet.Unicode, EntryPoint = "mciGetErrorStringW")] [return: MarshalAs(UnmanagedType.Bool)] private static extern bool MciGetErrorString(uint code, StringBuilder buffer, uint length); private void Awake() { //IL_005c: Unknown result type (might be due to invalid IL or missing references) //IL_0066: Expected O, but got Unknown //IL_0129: Unknown result type (might be due to invalid IL or missing references) //IL_0133: Expected O, but got Unknown //IL_0181: Unknown result type (might be due to invalid IL or missing references) //IL_018e: Expected O, but got Unknown instance = this; soundsPath = Path.Combine(Paths.PluginPath, "AspectNotifications_Stand_A_Lone", "Sounds"); Directory.CreateDirectory(soundsPath); volume = ((BaseUnityPlugin)this).Config.Bind<float>("Settings", "Volume", 85f, new ConfigDescription("MP3 notification volume (1-100%).", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 100f), Array.Empty<object>())); folderPath = ((BaseUnityPlugin)this).Config.Bind<string>("Settings", "Folder Path", soundsPath, "Read-only information: put MP3 files in this folder."); playableStatus = ((BaseUnityPlugin)this).Config.Bind<string>("Settings", "MP3 Playable", "0/0 PLAYABLE", "Accepted MP3 files / total MP3 files scanned. WAV and other formats are ignored."); selected = ((BaseUnityPlugin)this).Config.Bind<string>("Settings", "Selected", "Shuffle All", "Selected MP3 filename or Shuffle All."); if (Chainloader.PluginInfos.ContainsKey("com.rune580.riskofoptions")) { try { RegisterOptions(); } catch (Exception ex) { ((BaseUnityPlugin)this).Logger.LogError((object)("RiskOfOptions registration: " + ex)); } } harmony = new Harmony("ChronicRick.AspectNotifications_Stand_A_Lone"); try { MethodInfo methodInfo = AccessTools.Method(typeof(GenericPickupController), "Start", (Type[])null, (Type[])null); if (methodInfo == null) { ((BaseUnityPlugin)this).Logger.LogError((object)"Pickup Start hook not found."); } else { harmony.Patch((MethodBase)methodInfo, (HarmonyMethod)null, new HarmonyMethod(typeof(Plugin), "PickupStart", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); } } catch (Exception ex2) { ((BaseUnityPlugin)this).Logger.LogError((object)("Pickup hook failed: " + ex2)); } ((MonoBehaviour)this).StartCoroutine(ScanAfterStartup()); ((BaseUnityPlugin)this).Logger.LogInfo((object)("v0.1.0 initialized. MP3-only Windows MCI, local playback. Folder: " + soundsPath)); } private void RegisterOptions() { //IL_0055: Unknown result type (might be due to invalid IL or missing references) //IL_0069: Expected O, but got Unknown //IL_0085: Unknown result type (might be due to invalid IL or missing references) //IL_008f: Expected O, but got Unknown //IL_008a: Unknown result type (might be due to invalid IL or missing references) //IL_009e: Expected O, but got Unknown //IL_00ba: Unknown result type (might be due to invalid IL or missing references) //IL_00c4: Expected O, but got Unknown //IL_00bf: Unknown result type (might be due to invalid IL or missing references) //IL_00d3: Expected O, but got Unknown //IL_00da: Unknown result type (might be due to invalid IL or missing references) //IL_00ee: Expected O, but got Unknown //IL_010a: Unknown result type (might be due to invalid IL or missing references) //IL_0114: Expected O, but got Unknown //IL_010f: Unknown result type (might be due to invalid IL or missing references) //IL_0123: Expected O, but got Unknown //IL_012a: Unknown result type (might be due to invalid IL or missing references) //IL_013e: Expected O, but got Unknown ModSettingsManager.SetModDescription("Plays a random MP3 when an Aspect drops. Local Windows playback only.", "ChronicRick.AspectNotifications_Stand_A_Lone", "AspectNotifications_Stand_A_Lone"); soundSelector = new Mp3DropdownOption(selected, playable); ModSettingsManager.AddOption((BaseOption)(object)soundSelector, "ChronicRick.AspectNotifications_Stand_A_Lone", "AspectNotifications_Stand_A_Lone"); soundSelector.RefreshLabels(); ModSettingsManager.AddOption((BaseOption)new SliderOption(volume), "ChronicRick.AspectNotifications_Stand_A_Lone", "AspectNotifications_Stand_A_Lone"); ModSettingsManager.AddOption((BaseOption)new GenericButtonOption("Play", "Settings", "Preview a random playable MP3", "Play", new UnityAction(PlayPreview)), "ChronicRick.AspectNotifications_Stand_A_Lone", "AspectNotifications_Stand_A_Lone"); ModSettingsManager.AddOption((BaseOption)new GenericButtonOption("Stop", "Settings", "Stop the current preview", "Stop", new UnityAction(StopPreview)), "ChronicRick.AspectNotifications_Stand_A_Lone", "AspectNotifications_Stand_A_Lone"); ModSettingsManager.AddOption((BaseOption)new StringInputFieldOption(folderPath), "ChronicRick.AspectNotifications_Stand_A_Lone", "AspectNotifications_Stand_A_Lone"); ModSettingsManager.AddOption((BaseOption)new GenericButtonOption("Refresh", "Settings", "Rescan MP3 files and update dropdown choices", "Refresh", new UnityAction(RequestScan)), "ChronicRick.AspectNotifications_Stand_A_Lone", "AspectNotifications_Stand_A_Lone"); ModSettingsManager.AddOption((BaseOption)new StringInputFieldOption(playableStatus), "ChronicRick.AspectNotifications_Stand_A_Lone", "AspectNotifications_Stand_A_Lone"); } private IEnumerator ScanAfterStartup() { yield return null; RequestScan(); } private void RequestScan() { if (scanRunning) { scanAgain = true; } else { ((MonoBehaviour)this).StartCoroutine(ScanCoroutine()); } } private IEnumerator ScanCoroutine() { do { scanRunning = true; scanAgain = false; string[] files; try { files = (from f in Directory.GetFiles(soundsPath, "*", SearchOption.TopDirectoryOnly) where Path.GetExtension(f).Equals(".mp3", StringComparison.OrdinalIgnoreCase) select f).OrderBy<string, string>((string f) => Path.GetFileName(f), StringComparer.OrdinalIgnoreCase).ToArray(); } catch (Exception ex) { ((BaseUnityPlugin)this).Logger.LogError((object)("[AUDIO] Scan failed: " + ex)); playableStatus.Value = "0/0 PLAYABLE (scan failed)"; scanRunning = false; break; } List<string> found = new List<string>(); string[] array = files; foreach (string file in array) { string alias = NewAlias(); string error = ""; bool accepted = false; try { if (new FileInfo(file).Length > 0 && OpenMci(file, alias, out error)) { accepted = true; CloseMci(alias); } else if (new FileInfo(file).Length <= 0) { error = "Empty file"; } } catch (Exception ex2) { error = ex2.Message; } if (accepted) { found.Add(Path.GetFileName(file)); ((BaseUnityPlugin)this).Logger.LogInfo((object)("[AUDIO] AVAILABLE " + Path.GetFileName(file))); } else { ((BaseUnityPlugin)this).Logger.LogWarning((object)("[AUDIO] UNAVAILABLE " + Path.GetFileName(file) + ": " + error)); } yield return null; } playable.Clear(); playable.AddRange(found); if (soundSelector != null) { soundSelector.RefreshLabels(); } if (!string.Equals(selected.Value, "Shuffle All", StringComparison.OrdinalIgnoreCase) && !playable.Any((string x) => x.Equals(selected.Value, StringComparison.OrdinalIgnoreCase))) { selected.Value = "Shuffle All"; } playableStatus.Value = playable.Count + "/" + files.Length + " PLAYABLE"; ((BaseUnityPlugin)this).Logger.LogInfo((object)("[AUDIO] " + playableStatus.Value)); scanRunning = false; } while (scanAgain); } private string NewAlias() { int num = ++nextSoundId; return "an" + num; } private static string MciError(uint code) { StringBuilder stringBuilder = new StringBuilder(512); return MciGetErrorString(code, stringBuilder, (uint)stringBuilder.Capacity) ? stringBuilder.ToString() : ("MCI error " + code); } private static bool Mci(string command, out string error) { uint num = MciSendString(command, null, 0u, IntPtr.Zero); error = ((num == 0) ? "" : MciError(num)); return num == 0; } private static string QueryMci(string command) { StringBuilder stringBuilder = new StringBuilder(256); uint num = MciSendString(command, stringBuilder, (uint)stringBuilder.Capacity, IntPtr.Zero); return (num == 0) ? stringBuilder.ToString() : ("ERR " + MciError(num)); } private static bool OpenMci(string file, string alias, out string error) { if (file.IndexOf('"') >= 0) { error = "Filename contains a quote"; return false; } return Mci("open \"" + file + "\" alias " + alias, out error); } private static void CloseMci(string alias) { Mci("close " + alias, out var _); } private static void StopMci(string alias) { Mci("stop " + alias, out var _); CloseMci(alias); } private WindowsSound PlayRandomMp3() { if (playable.Count == 0) { ((BaseUnityPlugin)this).Logger.LogWarning((object)"[AUDIO] No playable MP3 files. Press Refresh."); return null; } string text; if (string.Equals(selected.Value, "Shuffle All", StringComparison.OrdinalIgnoreCase)) { text = playable[Random.Range(0, playable.Count)]; } else { text = playable.FirstOrDefault((string x) => x.Equals(selected.Value, StringComparison.OrdinalIgnoreCase)); if (text == null) { ((BaseUnityPlugin)this).Logger.LogWarning((object)("[AUDIO] Selected MP3 not playable: " + selected.Value + "; choose a valid MP3 or Shuffle All.")); return null; } } string text2 = Path.Combine(soundsPath, text); if (!File.Exists(text2)) { ((BaseUnityPlugin)this).Logger.LogWarning((object)("[AUDIO] Missing " + text + "; press Refresh.")); return null; } string text3 = NewAlias(); if (!OpenMci(text2, text3, out var error)) { ((BaseUnityPlugin)this).Logger.LogWarning((object)("[AUDIO] Open failed " + text + ": " + error)); return null; } if (!Mci("setaudio " + text3 + " volume to " + Mathf.RoundToInt(Mathf.Clamp(volume.Value, 1f, 100f) * 10f), out error)) { ((BaseUnityPlugin)this).Logger.LogWarning((object)("[AUDIO] Volume control unsupported: " + error)); } if (!Mci("play " + text3 + " from 0", out error)) { ((BaseUnityPlugin)this).Logger.LogWarning((object)("[AUDIO] Play failed " + text + ": " + error)); CloseMci(text3); return null; } string s = QueryMci("status " + text3 + " length"); int result; float expectedSeconds = (int.TryParse(s, out result) ? ((float)result / 1000f) : 0f); WindowsSound windowsSound = new WindowsSound { Alias = text3, Started = Time.realtimeSinceStartup, ExpectedSeconds = expectedSeconds }; active.Add(windowsSound); ((BaseUnityPlugin)this).Logger.LogInfo((object)("[AUDIO] PLAY " + text + " alias=" + text3 + " expected=" + expectedSeconds.ToString("F2") + "s")); return windowsSound; } private void PlayPreview() { StopPreview(); preview = PlayRandomMp3(); } private void StopPreview() { if (preview != null) { StopMci(preview.Alias); active.Remove(preview); preview = null; } } private void Update() { if (Time.realtimeSinceStartup < nextCleanup) { return; } nextCleanup = Time.realtimeSinceStartup + 0.25f; for (int num = active.Count - 1; num >= 0; num--) { WindowsSound windowsSound = active[num]; string text = QueryMci("status " + windowsSound.Alias + " mode"); if (text.Equals("stopped", StringComparison.OrdinalIgnoreCase) || text.StartsWith("ERR", StringComparison.OrdinalIgnoreCase) || (windowsSound.ExpectedSeconds > 0f && Time.realtimeSinceStartup - windowsSound.Started > windowsSound.ExpectedSeconds + 10f) || Time.realtimeSinceStartup - windowsSound.Started > 300f) { CloseMci(windowsSound.Alias); if (preview == windowsSound) { preview = null; } active.RemoveAt(num); } } } private static void PickupStart(GenericPickupController __instance) { if ((Object)(object)instance != (Object)null && (Object)(object)__instance != (Object)null) { ((MonoBehaviour)instance).StartCoroutine(instance.CheckPickup(__instance)); } } private IEnumerator CheckPickup(GenericPickupController pickup) { yield return (object)new WaitForSeconds(0.25f); if (!Object.op_Implicit((Object)(object)pickup)) { yield break; } int instanceId = ((Object)pickup).GetInstanceID(); if (seen.Contains(instanceId)) { yield break; } PickupDef def = PickupCatalog.GetPickupDef(pickup.Network_pickupState.pickupIndex); if (def == null) { yield break; } string internalName = ""; if ((int)def.itemIndex != -1) { ItemDef item = ItemCatalog.GetItemDef(def.itemIndex); if ((Object)(object)item != (Object)null) { internalName = ((Object)item).name ?? ""; } } else if ((int)def.equipmentIndex != -1) { EquipmentDef equipment = EquipmentCatalog.GetEquipmentDef(def.equipmentIndex); if ((Object)(object)equipment != (Object)null) { internalName = ((Object)equipment).name ?? ""; } } if (IsAspect(def, internalName)) { seen.Add(instanceId); seenOrder.Enqueue(instanceId); if (seenOrder.Count > 4096) { seen.Remove(seenOrder.Dequeue()); } ((BaseUnityPlugin)this).Logger.LogInfo((object)("[ASPECT] Detected " + internalName)); PlayRandomMp3(); } } private static bool IsEliteEquipment(EquipmentIndex index) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) try { return (Object)(object)EliteCatalog.GetEliteDefFromEquipmentIndex(index) != (Object)null; } catch { return false; } } private static bool IsMappedZetAspect(ItemIndex item) { //IL_00b4: Unknown result type (might be due to invalid IL or missing references) //IL_00b9: 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) try { Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies(); foreach (Assembly assembly in assemblies) { Type type = assembly.GetType("TPDespair.ZetAspects.Catalog", throwOnError: false); if (type == null) { continue; } FieldInfo field = type.GetField("equipToItem", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); IDictionary dictionary = ((field == null) ? null : (field.GetValue(null) as IDictionary)); if (dictionary == null) { return false; } foreach (DictionaryEntry item2 in dictionary) { if (item2.Key is EquipmentIndex && item2.Value is ItemIndex && (ItemIndex)item2.Value == item && IsEliteEquipment((EquipmentIndex)item2.Key)) { return true; } } return false; } } catch (Exception ex) { Plugin plugin = instance; if (plugin != null) { ((BaseUnityPlugin)plugin).Logger.LogWarning((object)("[DETECT] ZetAspects mapping error: " + ex.Message)); } } return false; } private static bool IsAspect(PickupDef def, string name) { //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Invalid comparison between Unknown and I4 //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Invalid comparison between Unknown and I4 //IL_0037: Unknown result type (might be due to invalid IL or missing references) if ((int)def.equipmentIndex != -1 && IsEliteEquipment(def.equipmentIndex)) { return true; } if ((int)def.itemIndex != -1 && IsMappedZetAspect(def.itemIndex)) { return true; } return !string.IsNullOrEmpty(name) && new string[3] { "ZetAspect", "Affix", "Aspect" }.Any((string s) => name.IndexOf(s, StringComparison.OrdinalIgnoreCase) >= 0); } private void OnDestroy() { ((MonoBehaviour)this).StopAllCoroutines(); StopPreview(); WindowsSound[] array = active.ToArray(); foreach (WindowsSound windowsSound in array) { StopMci(windowsSound.Alias); } active.Clear(); Harmony obj = harmony; if (obj != null) { obj.UnpatchSelf(); } if ((Object)(object)instance == (Object)(object)this) { instance = null; } } } }