Please disclose if your mod was created primarily 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 TouhouMeltdownBGM v1.0.7
plugins/TouhouMeltdownBGM/TouhouMeltdownBGM.dll
Decompiled a month agousing System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Reflection; using System.Runtime.CompilerServices; using BepInEx; using BepInEx.Configuration; using HarmonyLib; using UnityEngine; using UnityEngine.Networking; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)] [assembly: AssemblyVersion("0.0.0.0")] namespace TouhouMeltdownBGM; [BepInPlugin("com.cutyimodo.touhounuclearmeltdownbgm", "Touhou Meltdown BGM", "1.0.7")] public class Plugin : BaseUnityPlugin { [CompilerGenerated] private sealed class <FadeOutAndStop>d__19 : IEnumerator<object>, IDisposable, IEnumerator { private int <>1__state; private object <>2__current; public float duration; public Plugin <>4__this; private float <startVol>5__1; private float <elapsed>5__2; object IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <FadeOutAndStop>d__19(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <>1__state = -2; } private bool MoveNext() { switch (<>1__state) { default: return false; case 0: <>1__state = -1; if (!isPlaying || audioSource == null) { return false; } isPlaying = false; <startVol>5__1 = audioSource.volume; <elapsed>5__2 = 0f; break; case 1: <>1__state = -1; break; } if (<elapsed>5__2 < duration) { <elapsed>5__2 += Time.deltaTime; if (audioSource != null) { audioSource.volume = Mathf.Lerp(<startVol>5__1, 0f, <elapsed>5__2 / duration); } <>2__current = null; <>1__state = 1; return true; } if (audioSource != null) { audioSource.Stop(); audioSource.volume = <startVol>5__1; } ((BaseUnityPlugin)<>4__this).Logger.LogInfo((object)"Meltdown music stopped"); return false; } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } [CompilerGenerated] private sealed class <PlayMusic>d__18 : IEnumerator<object>, IDisposable, IEnumerator { private int <>1__state; private object <>2__current; public Plugin <>4__this; private float <timeout>5__1; private float <waited>5__2; private float <elapsed>5__3; private float <targetVol>5__4; object IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <PlayMusic>d__18(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <>1__state = -2; } private bool MoveNext() { //IL_0088: Unknown result type (might be due to invalid IL or missing references) //IL_008e: Invalid comparison between Unknown and I4 //IL_00b1: Unknown result type (might be due to invalid IL or missing references) //IL_00b7: Invalid comparison between Unknown and I4 switch (<>1__state) { default: return false; case 0: <>1__state = -1; if (isPlaying) { return false; } <timeout>5__1 = 10f; <waited>5__2 = 0f; goto IL_007c; case 1: <>1__state = -1; goto IL_007c; case 2: { <>1__state = -1; break; } IL_007c: if ((meltdownClip == null || (int)meltdownClip.loadState == 1) && <waited>5__2 < <timeout>5__1) { <waited>5__2 += Time.deltaTime; <>2__current = null; <>1__state = 1; return true; } if (meltdownClip == null || (int)meltdownClip.loadState != 2) { ((BaseUnityPlugin)<>4__this).Logger.LogError((object)$"Cannot play: audio clip not loaded (clip null: {meltdownClip == null})"); return false; } if (audioSource == null) { audioSource = ((Component)<>4__this).gameObject.AddComponent<AudioSource>(); audioSource.spatialBlend = 0f; audioSource.loop = true; audioSource.playOnAwake = false; audioSource.priority = 0; } audioSource.clip = meltdownClip; audioSource.volume = 0f; audioSource.Play(); isPlaying = true; <>4__this.SuppressOtherAudio(); ((BaseUnityPlugin)<>4__this).Logger.LogInfo((object)$"Playing meltdown music! (clip: {meltdownClip.length}s, {meltdownClip.channels}ch)"); <elapsed>5__3 = 0f; <targetVol>5__4 = volumeConfig.Value; break; } if (<elapsed>5__3 < 1f) { <elapsed>5__3 += Time.deltaTime; if (audioSource != null) { audioSource.volume = Mathf.Lerp(0f, <targetVol>5__4, <elapsed>5__3 / 1f); } <>2__current = null; <>1__state = 2; return true; } if (audioSource != null) { audioSource.volume = <targetVol>5__4; } return false; } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } [CompilerGenerated] private sealed class <PreloadAudio>d__13 : IEnumerator<object>, IDisposable, IEnumerator { private int <>1__state; private object <>2__current; public Plugin <>4__this; private string <fileUri>5__1; private float <timeout>5__2; private float <waited>5__3; private UnityWebRequest <request>5__4; object IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <PreloadAudio>d__13(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { int num = <>1__state; if (num == -3 || num == 1) { try { } finally { <>m__Finally1(); } } <fileUri>5__1 = null; <request>5__4 = null; <>1__state = -2; } private bool MoveNext() { //IL_0088: Unknown result type (might be due to invalid IL or missing references) //IL_0092: Expected O, but got Unknown //IL_01a8: Unknown result type (might be due to invalid IL or missing references) //IL_01ae: Invalid comparison between Unknown and I4 //IL_01cc: Unknown result type (might be due to invalid IL or missing references) //IL_01d2: Invalid comparison between Unknown and I4 //IL_022a: Unknown result type (might be due to invalid IL or missing references) bool result; try { switch (<>1__state) { default: result = false; goto end_IL_0000; case 0: <>1__state = -1; <fileUri>5__1 = "file:///" + <>4__this.musicPath.Replace("\\", "/"); <request>5__4 = UnityWebRequest.Get(<fileUri>5__1); <>1__state = -3; <request>5__4.downloadHandler = (DownloadHandler)new DownloadHandlerAudioClip(<fileUri>5__1, (AudioType)13); <>2__current = <request>5__4.SendWebRequest(); <>1__state = 1; result = true; goto end_IL_0000; case 1: <>1__state = -3; if (<request>5__4.isNetworkError || <request>5__4.isHttpError) { ((BaseUnityPlugin)<>4__this).Logger.LogError((object)("Failed to preload audio: " + <request>5__4.error)); result = false; <>m__Finally1(); } else { meltdownClip = DownloadHandlerAudioClip.GetContent(<request>5__4); <>m__Finally1(); <request>5__4 = null; if (meltdownClip != null) { <timeout>5__2 = 5f; <waited>5__3 = 0f; break; } ((BaseUnityPlugin)<>4__this).Logger.LogError((object)"Audio clip is null after preload"); result = false; } goto end_IL_0000; case 2: <>1__state = -1; break; } if ((int)meltdownClip.loadState == 1 && <waited>5__3 < <timeout>5__2) { <waited>5__3 += Time.deltaTime; <>2__current = null; <>1__state = 2; result = true; } else { if ((int)meltdownClip.loadState == 2) { ((BaseUnityPlugin)<>4__this).Logger.LogInfo((object)$"Preloaded NuclearFusion.mp3 ({meltdownClip.length}s, {meltdownClip.channels}ch)"); } else { ((BaseUnityPlugin)<>4__this).Logger.LogError((object)$"Audio preload failed, state: {meltdownClip.loadState}"); } result = false; } end_IL_0000:; } catch { //try-fault ((IDisposable)this).Dispose(); throw; } return result; } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } private void <>m__Finally1() { <>1__state = -1; if (<request>5__4 != null) { ((IDisposable)<request>5__4).Dispose(); } } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } internal static Plugin instance; internal static AudioClip meltdownClip; internal static AudioSource audioSource; internal static bool isPlaying; internal static bool wasTriggered; private bool wasInOrbit = true; internal static ConfigEntry<float> volumeConfig; private string musicPath; private Harmony harmony; private float suppressCheckTimer; private const float SUPPRESS_INTERVAL = 0.5f; private void Awake() { //IL_00aa: Unknown result type (might be due to invalid IL or missing references) //IL_00b4: Expected O, but got Unknown instance = this; volumeConfig = ((BaseUnityPlugin)this).Config.Bind<float>("General", "Volume", 0.8f, "Music volume (0.0 - 1.0)"); string directoryName = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location); musicPath = Path.Combine(directoryName, "NuclearFusion.mp3"); if (File.Exists(musicPath)) { ((BaseUnityPlugin)this).Logger.LogInfo((object)("Found music file at " + musicPath)); ((MonoBehaviour)this).StartCoroutine(PreloadAudio()); } else { ((BaseUnityPlugin)this).Logger.LogError((object)("Music file not found at " + musicPath)); } harmony = new Harmony("com.cutyimodo.touhounuclearmeltdownbgm"); PatchLungProp(); ((BaseUnityPlugin)this).Logger.LogInfo((object)"Touhou Meltdown BGM v1.0.7 loaded! (Harmony patch mode)"); } private void PatchLungProp() { //IL_00b4: Unknown result type (might be due to invalid IL or missing references) //IL_00c2: Expected O, but got Unknown Type type = null; Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies(); foreach (Assembly assembly in assemblies) { type = assembly.GetType("LungProp"); if (type != null) { break; } } if (type == null) { ((BaseUnityPlugin)this).Logger.LogError((object)"LungProp type not found! Cannot patch."); return; } MethodInfo method = type.GetMethod("EquipItem", BindingFlags.Instance | BindingFlags.Public); if (method == null) { ((BaseUnityPlugin)this).Logger.LogError((object)"LungProp.EquipItem method not found!"); return; } MethodInfo method2 = typeof(LungPropPatch).GetMethod("Prefix", BindingFlags.Static | BindingFlags.Public); harmony.Patch((MethodBase)method, new HarmonyMethod(method2), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); ((BaseUnityPlugin)this).Logger.LogInfo((object)"Patched LungProp.EquipItem successfully!"); } [IteratorStateMachine(typeof(<PreloadAudio>d__13))] private IEnumerator PreloadAudio() { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <PreloadAudio>d__13(0) { <>4__this = this }; } internal void TriggerMeltdownMusic() { if (!wasTriggered) { ((BaseUnityPlugin)this).Logger.LogInfo((object)"Apparatus pulled! Starting meltdown music..."); wasTriggered = true; ((MonoBehaviour)this).StartCoroutine(PlayMusic()); } } private void Update() { if (GetIsDisconnecting() && (isPlaying || wasTriggered)) { ((BaseUnityPlugin)this).Logger.LogInfo((object)"Disconnecting detected, stopping music."); if (audioSource != null) { audioSource.Stop(); } isPlaying = false; wasTriggered = false; wasInOrbit = true; return; } if (isPlaying && audioSource != null) { object startOfRound = GetStartOfRound(); if (startOfRound == null) { ((BaseUnityPlugin)this).Logger.LogInfo((object)"StartOfRound gone, stopping music."); audioSource.Stop(); isPlaying = false; wasTriggered = false; return; } } object startOfRound2 = GetStartOfRound(); if (startOfRound2 != null) { if (!GetBool(startOfRound2, "shipHasLanded")) { if (!wasInOrbit && wasTriggered) { wasTriggered = false; if (audioSource != null && isPlaying) { audioSource.Stop(); isPlaying = false; } ((BaseUnityPlugin)this).Logger.LogInfo((object)"Left moon, reset meltdown trigger for next round."); } wasInOrbit = true; } else { wasInOrbit = false; } } if (isPlaying && audioSource != null) { suppressCheckTimer += Time.deltaTime; if (suppressCheckTimer >= 0.5f) { suppressCheckTimer = 0f; SuppressOtherAudio(); } object startOfRound3 = GetStartOfRound(); if (startOfRound3 != null && GetBool(startOfRound3, "shipIsLeaving")) { ((MonoBehaviour)this).StartCoroutine(FadeOutAndStop(2f)); } } } private void SuppressOtherAudio() { AudioSource[] array = Object.FindObjectsOfType<AudioSource>(); if (array == null) { return; } AudioSource[] array2 = array; foreach (AudioSource val in array2) { if (val != null && val != audioSource && val.isPlaying) { string text = ((((Component)val).gameObject != null) ? ((Object)((Component)val).gameObject).name.ToLower() : ""); string text2 = ((val.clip != null && ((Object)val.clip).name != null) ? ((Object)val.clip).name.ToLower() : ""); if (text.Contains("meltdown") || text.Contains("facilitymeltdown") || text2.Contains("meltdown")) { val.volume = 0f; val.mute = true; } } } } private void OnDestroy() { wasTriggered = false; isPlaying = false; Harmony obj = harmony; if (obj != null) { obj.UnpatchSelf(); } } [IteratorStateMachine(typeof(<PlayMusic>d__18))] private IEnumerator PlayMusic() { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <PlayMusic>d__18(0) { <>4__this = this }; } [IteratorStateMachine(typeof(<FadeOutAndStop>d__19))] private IEnumerator FadeOutAndStop(float duration) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <FadeOutAndStop>d__19(0) { <>4__this = this, duration = duration }; } private static bool GetIsDisconnecting() { try { Type type = null; Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies(); foreach (Assembly assembly in assemblies) { type = assembly.GetType("GameNetworkManager"); if (type != null) { break; } } if (type == null) { return false; } PropertyInfo property = type.GetProperty("Instance", BindingFlags.Static | BindingFlags.Public); object obj = ((property != null) ? property.GetValue(null) : null); if (obj == null) { FieldInfo field = type.GetField("Instance", BindingFlags.Static | BindingFlags.Public); obj = ((field != null) ? field.GetValue(null) : null); } if (obj == null) { return false; } PropertyInfo property2 = type.GetProperty("isDisconnecting", BindingFlags.Instance | BindingFlags.Public); if (property2 != null) { return (bool)property2.GetValue(obj); } FieldInfo field2 = type.GetField("isDisconnecting", BindingFlags.Instance | BindingFlags.Public); if (field2 != null) { return (bool)field2.GetValue(obj); } return false; } catch { return false; } } private static object GetStartOfRound() { Type type = null; Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies(); foreach (Assembly assembly in assemblies) { type = assembly.GetType("StartOfRound"); if (type != null) { break; } } if (type == null) { return null; } PropertyInfo property = type.GetProperty("Instance", BindingFlags.Static | BindingFlags.Public); if (property != null) { return property.GetValue(null); } FieldInfo field = type.GetField("Instance", BindingFlags.Static | BindingFlags.Public); if (field != null) { return field.GetValue(null); } return null; } private static bool GetBool(object obj, string name) { if (obj == null) { return false; } Type type = obj.GetType(); PropertyInfo property = type.GetProperty(name, BindingFlags.Instance | BindingFlags.Public); if (property != null) { return (bool)property.GetValue(obj); } FieldInfo field = type.GetField(name, BindingFlags.Instance | BindingFlags.Public); if (field != null) { return (bool)field.GetValue(obj); } return false; } } public static class LungPropPatch { public static void Prefix(object __instance) { if (Plugin.instance != null && !Plugin.wasTriggered) { Type type = __instance.GetType(); FieldInfo field = type.GetField("isLungDocked", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (!(field == null) && (bool)field.GetValue(__instance)) { Plugin.instance.TriggerMeltdownMusic(); } } } }