The BepInEx console will not appear when launching like it does for other games on Thunderstore. This is normal (and helps prevent crashes during startup). You can turn it back on in your BepInEx.cfg file.
Decompiled source of MinecraftBackgroundMusic v0.2.4
BepInEx/plugins/backgroundMusic.dll
Decompiled 7 hours 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 HarmonyLib; using Microsoft.CodeAnalysis; 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: IgnoresAccessChecksTo("Assembly-CSharp")] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: AssemblyCompany("com.mthwj.minecraftmusic")] [assembly: AssemblyConfiguration("Debug")] [assembly: AssemblyFileVersion("0.1.0.0")] [assembly: AssemblyInformationalVersion("0.1.0")] [assembly: AssemblyProduct("com.mthwj.minecraftmusic")] [assembly: AssemblyTitle("MinecraftMusicPlugin")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("0.1.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.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)] internal sealed class NullableAttribute : Attribute { public readonly byte[] NullableFlags; public NullableAttribute(byte P_0) { NullableFlags = new byte[1] { P_0 }; } public NullableAttribute(byte[] P_0) { NullableFlags = P_0; } } [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] internal sealed class NullableContextAttribute : Attribute { public readonly byte Flag; public NullableContextAttribute(byte P_0) { Flag = P_0; } } [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 BepInEx { [AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = false)] [Conditional("CodeGeneration")] internal sealed class BepInAutoPluginAttribute : Attribute { public BepInAutoPluginAttribute(string? id = null, string? name = null, string? version = null) { } } } namespace BepInEx.Preloader.Core.Patching { [AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = false)] [Conditional("CodeGeneration")] internal sealed class PatcherAutoPluginAttribute : Attribute { public PatcherAutoPluginAttribute(string? id = null, string? name = null, string? version = null) { } } } namespace MinecraftMusicPlugin { [BepInPlugin("com.mthwj.minecraftmusic", "MinecraftMusicPlugin", "0.1.0")] public class Plugin : BaseUnityPlugin { [HarmonyPatch(typeof(AmbienceAudio), "FixedUpdate")] private static class AmbienceAudio_FixedUpdate_Patch { [CompilerGenerated] private sealed class <LoadAndPlayAudio>d__3 : IEnumerator<object>, IEnumerator, IDisposable { private int <>1__state; private object <>2__current; public MonoBehaviour context; public string path; private UnityWebRequest <uwr>5__1; private AudioClip <clip>5__2; private AudioSource <source>5__3; object IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <LoadAndPlayAudio>d__3(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(); } } <uwr>5__1 = null; <clip>5__2 = null; <source>5__3 = null; <>1__state = -2; } private bool MoveNext() { //IL_0099: Unknown result type (might be due to invalid IL or missing references) //IL_009f: Invalid comparison between Unknown and I4 try { switch (<>1__state) { default: return false; case 0: { <>1__state = -1; ManualLogSource? logger6 = Logger; if (logger6 != null) { logger6.LogInfo((object)("Starting to load MP3 from: " + path)); } <uwr>5__1 = UnityWebRequestMultimedia.GetAudioClip("file:///" + path, (AudioType)13); <>1__state = -3; <>2__current = <uwr>5__1.SendWebRequest(); <>1__state = 1; return true; } case 1: <>1__state = -3; if ((int)<uwr>5__1.result == 1) { <clip>5__2 = DownloadHandlerAudioClip.GetContent(<uwr>5__1); if ((Object)(object)<clip>5__2 != (Object)null) { ManualLogSource? logger = Logger; if (logger != null) { logger.LogInfo((object)$"MP3 loaded, length: {<clip>5__2.length} seconds"); } <source>5__3 = ((Component)context).GetComponent<AmbienceAudio>().mainMusic; if (<source>5__3.isPlaying) { <source>5__3.Stop(); <source>5__3.clip = null; ManualLogSource? logger2 = Logger; if (logger2 != null) { logger2.LogDebug((object)("Stopped previous playback for " + Path.GetFileName(path))); } } <source>5__3.clip = <clip>5__2; <source>5__3.volume = Mathf.Max(<source>5__3.volume, 0.5f); <source>5__3.Play(); ManualLogSource? logger3 = Logger; if (logger3 != null) { logger3.LogInfo((object)("Playing MP3 via mainMusic: " + Path.GetFileName(path))); } isMusicPlaying = true; <source>5__3 = null; } else { ManualLogSource? logger4 = Logger; if (logger4 != null) { logger4.LogError((object)("Failed to create AudioClip from " + path + ": Null clip")); } } <clip>5__2 = null; } else { ManualLogSource? logger5 = Logger; if (logger5 != null) { logger5.LogError((object)("Failed to load MP3: " + <uwr>5__1.error)); } } <>m__Finally1(); <uwr>5__1 = null; return false; } } catch { //try-fault ((IDisposable)this).Dispose(); throw; } } 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 (<uwr>5__1 != null) { ((IDisposable)<uwr>5__1).Dispose(); } } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } private static bool Prefix(AmbienceAudio __instance) { //IL_0080: 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) Transform transform = ((Component)__instance).transform; object obj; if (transform == null) { obj = null; } else { Transform root = transform.root; obj = ((root != null) ? ((Component)root).GetComponent<CharacterData>() : null); } CharacterData val = (CharacterData)obj; if ((Object)(object)val == (Object)null) { ManualLogSource? logger = Logger; if (logger != null) { logger.LogWarning((object)"CharacterData component not found on root transform"); } return true; } if (val.sinceDead > 0.5f && !val.passedOut && !val.dead && !val.fullyPassedOut) { float z = ((Component)__instance).transform.position.z; float y = ((Component)__instance).transform.position.y; isMusicPlaying = __instance.mainMusic.isPlaying; if (z > __instance.beachStingerZ && !__instance.playedBeach) { ManualLogSource? logger2 = Logger; if (logger2 != null) { logger2.LogInfo((object)"Entered beach region, overriding with Minecraft music"); } PlayRandomMp3((MonoBehaviour)(object)__instance, "Beach"); __instance.playedBeach = true; return false; } if (z > __instance.tropicsStingerZ && !__instance.playedTropics) { ManualLogSource? logger3 = Logger; if (logger3 != null) { logger3.LogInfo((object)"Entered tropics region, overriding with Minecraft music"); } PlayRandomMp3((MonoBehaviour)(object)__instance, "Tropics"); __instance.playedTropics = true; return false; } if (z > __instance.alpineStingerZ && !__instance.playedAlpine) { ManualLogSource? logger4 = Logger; if (logger4 != null) { logger4.LogInfo((object)"Entered alpine region, overriding with Minecraft music"); } PlayRandomMp3((MonoBehaviour)(object)__instance, "Alpine"); __instance.playedAlpine = true; return false; } if (z > __instance.calderaStingerZ && !__instance.playedCaldera) { ManualLogSource? logger5 = Logger; if (logger5 != null) { logger5.LogInfo((object)"Entered caldera region, overriding with Minecraft music"); } PlayRandomMp3((MonoBehaviour)(object)__instance, "Caldera"); __instance.playedCaldera = true; return false; } if (y > __instance.kilnStingerY && !__instance.playedKiln) { ManualLogSource? logger6 = Logger; if (logger6 != null) { logger6.LogInfo((object)"Entered kiln region, overriding with Minecraft music"); } PlayRandomMp3((MonoBehaviour)(object)__instance, "Kiln"); __instance.playedKiln = true; return false; } if (z > __instance.peaksTingerZ && !__instance.playedPeak) { ManualLogSource? logger7 = Logger; if (logger7 != null) { logger7.LogInfo((object)"Entered peak region, overriding with Minecraft music"); } PlayRandomMp3((MonoBehaviour)(object)__instance, "Peak"); __instance.playedPeak = true; return false; } if (!isMusicPlaying && (Object)(object)__instance.mainMusic.clip != (Object)null) { string currentRegion = GetCurrentRegion(__instance); ManualLogSource? logger8 = Logger; if (logger8 != null) { logger8.LogInfo((object)("Current track ended, playing new random MP3 for " + currentRegion)); } PlayRandomMp3((MonoBehaviour)(object)__instance, currentRegion); return false; } } else { ManualLogSource? logger9 = Logger; if (logger9 != null) { logger9.LogInfo((object)"Character conditions not met, fading out music"); } __instance.mainMusic.volume = Mathf.Lerp(__instance.mainMusic.volume, 0f, 0.05f); } return true; } private static string GetCurrentRegion(AmbienceAudio __instance) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Unknown result type (might be due to invalid IL or missing references) float z = ((Component)__instance).transform.position.z; float y = ((Component)__instance).transform.position.y; if (y > __instance.kilnStingerY) { return "Kiln"; } if (z > __instance.peaksTingerZ) { return "Peak"; } if (z > __instance.calderaStingerZ) { return "Caldera"; } if (z > __instance.alpineStingerZ) { return "Alpine"; } if (z > __instance.tropicsStingerZ) { return "Tropics"; } if (z > __instance.beachStingerZ) { return "Beach"; } return "Default"; } private static void PlayRandomMp3(MonoBehaviour context, string region) { if (1 == 0) { } string text = region switch { "Beach" => beachFolderConfig.Value.Trim(), "Tropics" => tropicsFolderConfig.Value.Trim(), "Alpine" => alpineFolderConfig.Value.Trim(), "Caldera" => calderaFolderConfig.Value.Trim(), "Kiln" => kilnFolderConfig.Value.Trim(), "Peak" => peakFolderConfig.Value.Trim(), _ => defaultFolderConfig.Value.Trim(), }; if (1 == 0) { } string text2 = text; string text3 = (Path.IsPathRooted(text2) ? text2 : Path.Combine(musicFolder, text2)); if (!Directory.Exists(text3) || Directory.GetFiles(text3, "*.mp3").Length == 0) { ManualLogSource? logger = Logger; if (logger != null) { logger.LogWarning((object)("Music folder for " + region + " not found or empty at " + text3 + ", falling back to Default")); } text3 = Path.Combine(musicFolder, defaultFolderConfig.Value.Trim()); } if (!Directory.Exists(text3)) { ManualLogSource? logger2 = Logger; if (logger2 != null) { logger2.LogError((object)("No MP3s available for " + region + " or Default at " + text3 + "!")); } return; } string[] files = Directory.GetFiles(text3, "*.mp3"); if (files.Length == 0) { ManualLogSource? logger3 = Logger; if (logger3 != null) { logger3.LogError((object)("No MP3 files found in " + text3 + " for " + region + "!")); } } else { Random random = new Random(); string path = files[random.Next(files.Length)]; ManualLogSource? logger4 = Logger; if (logger4 != null) { logger4.LogInfo((object)("Loading MP3 for " + region + ": " + Path.GetFileName(path))); } context.StartCoroutine(LoadAndPlayAudio(context, path)); } } [IteratorStateMachine(typeof(<LoadAndPlayAudio>d__3))] private static IEnumerator LoadAndPlayAudio(MonoBehaviour context, string path) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <LoadAndPlayAudio>d__3(0) { context = context, path = path }; } } internal static ManualLogSource? Logger; private static string musicFolder = string.Empty; private static bool isMusicPlaying = false; private static ConfigEntry<string> beachFolderConfig = null; private static ConfigEntry<string> tropicsFolderConfig = null; private static ConfigEntry<string> alpineFolderConfig = null; private static ConfigEntry<string> calderaFolderConfig = null; private static ConfigEntry<string> kilnFolderConfig = null; private static ConfigEntry<string> peakFolderConfig = null; private static ConfigEntry<string> defaultFolderConfig = null; public const string Id = "com.mthwj.minecraftmusic"; public static string Name => "MinecraftMusicPlugin"; public static string Version => "0.1.0"; private void Awake() { //IL_015b: Unknown result type (might be due to invalid IL or missing references) //IL_0161: Expected O, but got Unknown Logger = ((BaseUnityPlugin)this).Logger; musicFolder = Path.Combine(Path.GetDirectoryName(((BaseUnityPlugin)this).Info.Location) ?? throw new InvalidOperationException("Plugin location not found"), "CustomBackgroundMusic"); ManualLogSource? logger = Logger; if (logger != null) { logger.LogInfo((object)("Plugin com.mthwj.minecraftmusic is loaded! Music folder: " + musicFolder)); } beachFolderConfig = ((BaseUnityPlugin)this).Config.Bind<string>("MusicFolders", "BeachFolder", "Beach", "Folder for Beach region music (relative to CustomBackgroundMusic or absolute path)."); tropicsFolderConfig = ((BaseUnityPlugin)this).Config.Bind<string>("MusicFolders", "TropicsFolder", "Tropics", "Folder for Tropics region music (relative to CustomBackgroundMusic or absolute path)."); alpineFolderConfig = ((BaseUnityPlugin)this).Config.Bind<string>("MusicFolders", "AlpineFolder", "Alpine", "Folder for Alpine region music (relative to CustomBackgroundMusic or absolute path)."); calderaFolderConfig = ((BaseUnityPlugin)this).Config.Bind<string>("MusicFolders", "CalderaFolder", "Caldera", "Folder for Caldera region music (relative to CustomBackgroundMusic or absolute path)."); kilnFolderConfig = ((BaseUnityPlugin)this).Config.Bind<string>("MusicFolders", "KilnFolder", "Kiln", "Folder for Kiln region music (relative to CustomBackgroundMusic or absolute path)."); peakFolderConfig = ((BaseUnityPlugin)this).Config.Bind<string>("MusicFolders", "PeakFolder", "Peak", "Folder for Peak region music (relative to CustomBackgroundMusic or absolute path)."); defaultFolderConfig = ((BaseUnityPlugin)this).Config.Bind<string>("MusicFolders", "DefaultFolder", "Default", "Fallback folder if region-specific folder is missing or empty (relative to CustomBackgroundMusic or absolute path)."); Harmony val = new Harmony("com.mthwj.minecraftmusic.patch"); val.PatchAll(); ManualLogSource? logger2 = Logger; if (logger2 != null) { logger2.LogInfo((object)"Harmony patches applied successfully"); } } } } namespace System.Runtime.CompilerServices { [AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)] internal sealed class IgnoresAccessChecksToAttribute : Attribute { public IgnoresAccessChecksToAttribute(string assemblyName) { } } }