Decompiled source of MinecraftBackgroundMusic v0.4.5

BepInEx/plugins/com.mthwj.minecraftmusic.dll

Decompiled 2 weeks 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 HarmonyLib;
using Microsoft.CodeAnalysis;
using UnityEngine;
using UnityEngine.Networking;
using Zorro.Core;

[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 <LoadAndFadeAudio>d__5 : IEnumerator<object>, IEnumerator, IDisposable
			{
				private int <>1__state;

				private object <>2__current;

				public MonoBehaviour context;

				public string path;

				public string region;

				private AudioSource <source>5__1;

				private float <targetVolume>5__2;

				private bool <needsFadeOut>5__3;

				private float <timer>5__4;

				private float <startVolume>5__5;

				private UnityWebRequest <uwr>5__6;

				private AudioClip <clip>5__7;

				private float <fadeInTimer>5__8;

				object IEnumerator<object>.Current
				{
					[DebuggerHidden]
					get
					{
						return <>2__current;
					}
				}

				object IEnumerator.Current
				{
					[DebuggerHidden]
					get
					{
						return <>2__current;
					}
				}

				[DebuggerHidden]
				public <LoadAndFadeAudio>d__5(int <>1__state)
				{
					this.<>1__state = <>1__state;
				}

				[DebuggerHidden]
				void IDisposable.Dispose()
				{
					int num = <>1__state;
					if (num == -3 || (uint)(num - 2) <= 1u)
					{
						try
						{
						}
						finally
						{
							<>m__Finally1();
						}
					}
					<source>5__1 = null;
					<uwr>5__6 = null;
					<clip>5__7 = null;
					<>1__state = -2;
				}

				private bool MoveNext()
				{
					//IL_020c: Unknown result type (might be due to invalid IL or missing references)
					//IL_0212: Invalid comparison between Unknown and I4
					bool result;
					try
					{
						ManualLogSource? logger6;
						switch (<>1__state)
						{
						default:
							result = false;
							goto end_IL_0000;
						case 0:
						{
							<>1__state = -1;
							<source>5__1 = ((Component)context).GetComponent<AmbienceAudio>().mainMusic;
							<targetVolume>5__2 = Mathf.Max(<source>5__1.volume, 0.5f);
							<needsFadeOut>5__3 = isMusicPlaying && (currentRegion != region || !HasRegionSpecificMusic(region, out string _));
							if (<needsFadeOut>5__3)
							{
								ManualLogSource? logger8 = Logger;
								if (logger8 != null)
								{
									logger8.LogDebug((object)("Fading out current track for " + region));
								}
								<timer>5__4 = 0f;
								<startVolume>5__5 = <source>5__1.volume;
								goto IL_014a;
							}
							goto IL_0198;
						}
						case 1:
							<>1__state = -1;
							goto IL_014a;
						case 2:
						{
							<>1__state = -3;
							if ((int)<uwr>5__6.result != 1)
							{
								ManualLogSource? logger = Logger;
								if (logger != null)
								{
									logger.LogError((object)("Failed to load MP3 " + path + ": " + <uwr>5__6.error + ". Skipping file."));
								}
								result = false;
								break;
							}
							<clip>5__7 = DownloadHandlerAudioClip.GetContent(<uwr>5__6);
							if ((Object)(object)<clip>5__7 == (Object)null)
							{
								ManualLogSource? logger2 = Logger;
								if (logger2 != null)
								{
									logger2.LogError((object)("Failed to create AudioClip from " + path + ": Null clip. File may contain non-audio streams (e.g., embedded images). Skipping file."));
								}
								result = false;
								break;
							}
							ManualLogSource? logger3 = Logger;
							if (logger3 != null)
							{
								logger3.LogInfo((object)$"MP3 loaded, length: {<clip>5__7.length} seconds");
							}
							<source>5__1.clip = <clip>5__7;
							<source>5__1.volume = 0f;
							<source>5__1.Play();
							ManualLogSource? logger4 = Logger;
							if (logger4 != null)
							{
								logger4.LogDebug((object)("Fading in new track: " + Path.GetFileName(path)));
							}
							<fadeInTimer>5__8 = 0f;
							goto IL_03a7;
						}
						case 3:
							{
								<>1__state = -3;
								goto IL_03a7;
							}
							IL_03a7:
							if (<fadeInTimer>5__8 < 1f)
							{
								<fadeInTimer>5__8 += Time.deltaTime;
								<source>5__1.volume = Mathf.Lerp(0f, <targetVolume>5__2, <fadeInTimer>5__8 / 1f);
								<>2__current = null;
								<>1__state = 3;
								result = true;
							}
							else
							{
								<source>5__1.volume = <targetVolume>5__2;
								isMusicPlaying = true;
								ManualLogSource? logger5 = Logger;
								if (logger5 != null)
								{
									logger5.LogInfo((object)("Playing MP3 via mainMusic: " + Path.GetFileName(path)));
								}
								<clip>5__7 = null;
								<>m__Finally1();
								<uwr>5__6 = null;
								result = false;
							}
							goto end_IL_0000;
							IL_0198:
							logger6 = Logger;
							if (logger6 != null)
							{
								logger6.LogInfo((object)("Starting to load MP3 from: " + path));
							}
							<uwr>5__6 = UnityWebRequestMultimedia.GetAudioClip("file:///" + path, (AudioType)13);
							<>1__state = -3;
							<>2__current = <uwr>5__6.SendWebRequest();
							<>1__state = 2;
							result = true;
							goto end_IL_0000;
							IL_014a:
							if (!(<timer>5__4 < 1f))
							{
								<source>5__1.Stop();
								<source>5__1.clip = null;
								ManualLogSource? logger7 = Logger;
								if (logger7 != null)
								{
									logger7.LogDebug((object)("Stopped previous track for " + region));
								}
								goto IL_0198;
							}
							<timer>5__4 += Time.deltaTime;
							<source>5__1.volume = Mathf.Lerp(<startVolume>5__5, 0f, <timer>5__4 / 1f);
							<>2__current = null;
							<>1__state = 1;
							result = true;
							goto end_IL_0000;
						}
						<>m__Finally1();
						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 (<uwr>5__6 != null)
					{
						((IDisposable)<uwr>5__6).Dispose();
					}
				}

				[DebuggerHidden]
				void IEnumerator.Reset()
				{
					throw new NotSupportedException();
				}
			}

			[CompilerGenerated]
			private sealed class <LoadAndFadeAudio>d__6 : IEnumerator<object>, IEnumerator, IDisposable
			{
				private int <>1__state;

				private object <>2__current;

				public MonoBehaviour context;

				public AudioClip clip;

				public string region;

				private AudioSource <source>5__1;

				private float <targetVolume>5__2;

				private bool <needsFadeOut>5__3;

				private float <fadeInTimer>5__4;

				private float <timer>5__5;

				private float <startVolume>5__6;

				object IEnumerator<object>.Current
				{
					[DebuggerHidden]
					get
					{
						return <>2__current;
					}
				}

				object IEnumerator.Current
				{
					[DebuggerHidden]
					get
					{
						return <>2__current;
					}
				}

				[DebuggerHidden]
				public <LoadAndFadeAudio>d__6(int <>1__state)
				{
					this.<>1__state = <>1__state;
				}

				[DebuggerHidden]
				void IDisposable.Dispose()
				{
					<source>5__1 = null;
					<>1__state = -2;
				}

				private bool MoveNext()
				{
					ManualLogSource? logger2;
					ManualLogSource? logger3;
					ManualLogSource? logger4;
					switch (<>1__state)
					{
					default:
						return false;
					case 0:
					{
						<>1__state = -1;
						<source>5__1 = ((Component)context).GetComponent<AmbienceAudio>().mainMusic;
						<targetVolume>5__2 = Mathf.Max(<source>5__1.volume, 0.5f);
						<needsFadeOut>5__3 = isMusicPlaying && (currentRegion != region || !HasRegionSpecificMusic(region, out string _));
						if (<needsFadeOut>5__3)
						{
							ManualLogSource? logger = Logger;
							if (logger != null)
							{
								logger.LogDebug((object)("Fading out current track for " + region));
							}
							<timer>5__5 = 0f;
							<startVolume>5__6 = <source>5__1.volume;
							goto IL_0137;
						}
						goto IL_0183;
					}
					case 1:
						<>1__state = -1;
						goto IL_0137;
					case 2:
						{
							<>1__state = -1;
							break;
						}
						IL_0137:
						if (<timer>5__5 < 1f)
						{
							<timer>5__5 += Time.deltaTime;
							<source>5__1.volume = Mathf.Lerp(<startVolume>5__6, 0f, <timer>5__5 / 1f);
							<>2__current = null;
							<>1__state = 1;
							return true;
						}
						<source>5__1.Stop();
						<source>5__1.clip = null;
						logger2 = Logger;
						if (logger2 != null)
						{
							logger2.LogDebug((object)("Stopped previous track for " + region));
						}
						goto IL_0183;
						IL_0183:
						logger3 = Logger;
						if (logger3 != null)
						{
							logger3.LogInfo((object)("Playing MP3 via mainMusic: " + ((Object)clip).name));
						}
						<source>5__1.clip = clip;
						<source>5__1.volume = 0f;
						<source>5__1.Play();
						logger4 = Logger;
						if (logger4 != null)
						{
							logger4.LogDebug((object)("Fading in new track: " + ((Object)clip).name));
						}
						<fadeInTimer>5__4 = 0f;
						break;
					}
					if (<fadeInTimer>5__4 < 1f)
					{
						<fadeInTimer>5__4 += Time.deltaTime;
						<source>5__1.volume = Mathf.Lerp(0f, <targetVolume>5__2, <fadeInTimer>5__4 / 1f);
						<>2__current = null;
						<>1__state = 2;
						return true;
					}
					<source>5__1.volume = <targetVolume>5__2;
					isMusicPlaying = true;
					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();
				}
			}

			private static bool Prefix(AmbienceAudio __instance)
			{
				//IL_01a0: Unknown result type (might be due to invalid IL or missing references)
				//IL_01b2: 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 ((Object)(object)__instance.stingerSource != (Object)null && (Object)(object)__instance.stingerSource.clip != (Object)null)
				{
					string text = ((Object)__instance.stingerSource.clip).name.ToLower();
					ManualLogSource? logger2 = Logger;
					if (logger2 != null)
					{
						logger2.LogDebug((object)("StingerSource clip detected: " + text));
					}
					if (!allowStingerMusic.Value && (text.Contains("sunrise") || text.Contains("sunset") || text.Contains("night") || text.Contains("climb")))
					{
						if (__instance.stingerSource.isPlaying)
						{
							__instance.stingerSource.Stop();
							ManualLogSource? logger3 = Logger;
							if (logger3 != null)
							{
								logger3.LogDebug((object)("Stopped stingerSource playing '" + text + "' to prevent musical stinger playback"));
							}
						}
						__instance.stingerSource.clip = null;
					}
				}
				if (val.sinceDead > 0.5f && ((Object)(object)Character.localCharacter == (Object)null || !Character.localCharacter.warping) && !val.passedOut && !val.dead && !val.fullyPassedOut && !__instance.inTomb)
				{
					float z = ((Component)__instance).transform.position.z;
					float y = ((Component)__instance).transform.position.y;
					isMusicPlaying = __instance.mainMusic.isPlaying && (Object)(object)__instance.mainMusic.clip != (Object)null;
					ManualLogSource? logger4 = Logger;
					if (logger4 != null)
					{
						logger4.LogDebug((object)$"Position: z={z}, y={y}, isMusicPlaying={isMusicPlaying}, mainMusicVolume={__instance.mainMusic.volume}");
					}
					if (z > __instance.beachStingerZ && !__instance.playedBeach)
					{
						ManualLogSource? logger5 = Logger;
						if (logger5 != null)
						{
							logger5.LogInfo((object)"Entered beach region, overriding with Minecraft music");
						}
						TryPlayMusicForRegion((MonoBehaviour)(object)__instance, "Beach");
						__instance.playedBeach = true;
						return false;
					}
					if (z > __instance.tropicsStingerZ && !__instance.playedTropics)
					{
						ManualLogSource? logger6 = Logger;
						if (logger6 != null)
						{
							logger6.LogInfo((object)"Entered tropics region, overriding with Minecraft music");
						}
						TryPlayMusicForRegion((MonoBehaviour)(object)__instance, "Tropics");
						__instance.playedTropics = true;
						return false;
					}
					if (z > __instance.alpineStingerZ && !__instance.playedAlpineOrMesa)
					{
						string text2 = (Singleton<MapHandler>.Instance.BiomeIsPresent((BiomeType)2) ? "Alpine" : (Singleton<MapHandler>.Instance.BiomeIsPresent((BiomeType)6) ? "Mesa" : "Default"));
						ManualLogSource? logger7 = Logger;
						if (logger7 != null)
						{
							logger7.LogInfo((object)("Entered " + text2 + " region, overriding with Minecraft music"));
						}
						TryPlayMusicForRegion((MonoBehaviour)(object)__instance, text2);
						__instance.playedAlpineOrMesa = true;
						return false;
					}
					if (z > __instance.calderaStingerZ && !__instance.playedCaldera)
					{
						ManualLogSource? logger8 = Logger;
						if (logger8 != null)
						{
							logger8.LogInfo((object)"Entered caldera region, overriding with Minecraft music");
						}
						TryPlayMusicForRegion((MonoBehaviour)(object)__instance, "Caldera");
						__instance.playedCaldera = true;
						return false;
					}
					if (y > __instance.kilnStingerY && !__instance.playedKiln)
					{
						ManualLogSource? logger9 = Logger;
						if (logger9 != null)
						{
							logger9.LogInfo((object)"Entered kiln region, overriding with Minecraft music");
						}
						TryPlayMusicForRegion((MonoBehaviour)(object)__instance, "Kiln");
						__instance.playedKiln = true;
						return false;
					}
					if (z > __instance.peaksTingerZ && !__instance.playedPeak)
					{
						ManualLogSource? logger10 = Logger;
						if (logger10 != null)
						{
							logger10.LogInfo((object)"Entered peak region, overriding with Minecraft music");
						}
						TryPlayMusicForRegion((MonoBehaviour)(object)__instance, "Peak");
						__instance.playedPeak = true;
						return false;
					}
					if (z > 700f && __instance.inTomb && !__instance.playedTomb && !useDefaultTombMusic.Value)
					{
						ManualLogSource? logger11 = Logger;
						if (logger11 != null)
						{
							logger11.LogInfo((object)"Entered tomb region, overriding with Minecraft music");
						}
						TryPlayMusicForRegion((MonoBehaviour)(object)__instance, "Tomb");
						__instance.playedTomb = true;
						return false;
					}
					if (!isMusicPlaying && (Object)(object)__instance.mainMusic.clip != (Object)null)
					{
						string currentRegion = GetCurrentRegion(__instance);
						ManualLogSource? logger12 = Logger;
						if (logger12 != null)
						{
							logger12.LogInfo((object)("Current track ended, playing new random MP3 for " + currentRegion));
						}
						TryPlayMusicForRegion((MonoBehaviour)(object)__instance, currentRegion);
						return false;
					}
				}
				else
				{
					ManualLogSource? logger13 = Logger;
					if (logger13 != null)
					{
						logger13.LogInfo((object)"Character conditions not met, fading out music");
					}
					__instance.mainMusic.volume = Mathf.Lerp(__instance.mainMusic.volume, 0f, Time.deltaTime / 1f);
				}
				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 (__instance.inTomb && z > 700f)
				{
					return "Tomb";
				}
				if (y > __instance.kilnStingerY)
				{
					return "Kiln";
				}
				if (z > __instance.peaksTingerZ)
				{
					return "Peak";
				}
				if (z > __instance.calderaStingerZ)
				{
					return "Caldera";
				}
				if (z > __instance.alpineStingerZ)
				{
					if (Singleton<MapHandler>.Instance.BiomeIsPresent((BiomeType)2))
					{
						return "Alpine";
					}
					if (Singleton<MapHandler>.Instance.BiomeIsPresent((BiomeType)6))
					{
						return "Mesa";
					}
				}
				if (z > __instance.tropicsStingerZ)
				{
					return "Tropics";
				}
				if (z > __instance.beachStingerZ)
				{
					return "Beach";
				}
				return "Default";
			}

			private static bool HasRegionSpecificMusic(string region, out string folderPath)
			{
				if (1 == 0)
				{
				}
				string text = region switch
				{
					"Beach" => beachFolderConfig.Value.Trim(), 
					"Tropics" => tropicsFolderConfig.Value.Trim(), 
					"Alpine" => alpineFolderConfig.Value.Trim(), 
					"Mesa" => mesaFolderConfig.Value.Trim(), 
					"Caldera" => calderaFolderConfig.Value.Trim(), 
					"Kiln" => kilnFolderConfig.Value.Trim(), 
					"Peak" => peakFolderConfig.Value.Trim(), 
					"Tomb" => tombFolderConfig.Value.Trim(), 
					_ => defaultFolderConfig.Value.Trim(), 
				};
				if (1 == 0)
				{
				}
				string text2 = text;
				folderPath = (Path.IsPathRooted(text2) ? text2 : Path.Combine(musicFolder, text2));
				if (preloadAudioClips.Value)
				{
					return (regionClips.ContainsKey(region) && regionClips[region].Count > 0) || (region != "Default" && regionClips.ContainsKey("Default") && regionClips["Default"].Count > 0);
				}
				return Directory.Exists(folderPath) && Directory.GetFiles(folderPath, "*.mp3").Length != 0;
			}

			private static void TryPlayMusicForRegion(MonoBehaviour context, string region)
			{
				if (region == "Tomb" && useDefaultTombMusic.Value)
				{
					ManualLogSource? logger = Logger;
					if (logger != null)
					{
						logger.LogDebug((object)"Using default tomb music, skipping custom playback");
					}
				}
				else
				{
					HasRegionSpecificMusic(region, out string folderPath);
					PlayRandomMp3(context, region, folderPath);
				}
			}

			private static void PlayRandomMp3(MonoBehaviour context, string region, string folderPath)
			{
				string text = region;
				string text2 = folderPath;
				if (preloadAudioClips.Value)
				{
					if (!regionClips.ContainsKey(region) || regionClips[region].Count == 0)
					{
						text = "Default";
						text2 = Path.Combine(musicFolder, defaultFolderConfig.Value.Trim());
						if (!regionClips.ContainsKey(text) || regionClips[text].Count == 0)
						{
							ManualLogSource? logger = Logger;
							if (logger != null)
							{
								logger.LogError((object)("No MP3s available for " + region + " or Default at " + text2 + "!"));
							}
							return;
						}
					}
					Random random = new Random();
					List<AudioClip> list = regionClips[text];
					AudioClip val = list[random.Next(list.Count)];
					ManualLogSource? logger2 = Logger;
					if (logger2 != null)
					{
						logger2.LogInfo((object)("Playing MP3 for " + text + ": " + ((Object)val).name));
					}
					context.StartCoroutine(LoadAndFadeAudio(context, val, text));
				}
				else
				{
					if (!Directory.Exists(folderPath) || Directory.GetFiles(folderPath, "*.mp3").Length == 0)
					{
						text = "Default";
						text2 = Path.Combine(musicFolder, defaultFolderConfig.Value.Trim());
						if (!Directory.Exists(text2) || Directory.GetFiles(text2, "*.mp3").Length == 0)
						{
							ManualLogSource? logger3 = Logger;
							if (logger3 != null)
							{
								logger3.LogError((object)("No MP3s available for " + region + " or Default at " + text2 + "!"));
							}
							return;
						}
					}
					string[] files = Directory.GetFiles(text2, "*.mp3");
					Random random2 = new Random();
					string path = files[random2.Next(files.Length)];
					ManualLogSource? logger4 = Logger;
					if (logger4 != null)
					{
						logger4.LogInfo((object)("Loading MP3 for " + text + ": " + Path.GetFileName(path)));
					}
					context.StartCoroutine(LoadAndFadeAudio(context, path, text));
				}
				currentRegion = text;
			}

			[IteratorStateMachine(typeof(<LoadAndFadeAudio>d__5))]
			private static IEnumerator LoadAndFadeAudio(MonoBehaviour context, string path, string region)
			{
				//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
				return new <LoadAndFadeAudio>d__5(0)
				{
					context = context,
					path = path,
					region = region
				};
			}

			[IteratorStateMachine(typeof(<LoadAndFadeAudio>d__6))]
			private static IEnumerator LoadAndFadeAudio(MonoBehaviour context, AudioClip clip, string region)
			{
				//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
				return new <LoadAndFadeAudio>d__6(0)
				{
					context = context,
					clip = clip,
					region = region
				};
			}
		}

		[CompilerGenerated]
		private sealed class <LoadAllAudioClips>d__20 : IEnumerator<object>, IEnumerator, IDisposable
		{
			private int <>1__state;

			private object <>2__current;

			public Plugin <>4__this;

			private Dictionary<string, ConfigEntry<string>> <regions>5__1;

			private int <totalClips>5__2;

			private Dictionary<string, ConfigEntry<string>>.Enumerator <>s__3;

			private KeyValuePair<string, ConfigEntry<string>> <region>5__4;

			private string <regionName>5__5;

			private string <folderName>5__6;

			private string <folderPath>5__7;

			private string[] <mp3Files>5__8;

			private string[] <>s__9;

			private int <>s__10;

			private string <file>5__11;

			private UnityWebRequest <uwr>5__12;

			private AudioClip <clip>5__13;

			private Exception <ex>5__14;

			object IEnumerator<object>.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			object IEnumerator.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			[DebuggerHidden]
			public <LoadAllAudioClips>d__20(int <>1__state)
			{
				this.<>1__state = <>1__state;
			}

			[DebuggerHidden]
			void IDisposable.Dispose()
			{
				int num = <>1__state;
				if ((uint)(num - -4) <= 1u || num == 1)
				{
					try
					{
						if (num == -4 || num == 1)
						{
							try
							{
							}
							finally
							{
								<>m__Finally2();
							}
						}
					}
					finally
					{
						<>m__Finally1();
					}
				}
				<regions>5__1 = null;
				<>s__3 = default(Dictionary<string, ConfigEntry<string>>.Enumerator);
				<region>5__4 = default(KeyValuePair<string, ConfigEntry<string>>);
				<regionName>5__5 = null;
				<folderName>5__6 = null;
				<folderPath>5__7 = null;
				<mp3Files>5__8 = null;
				<>s__9 = null;
				<file>5__11 = null;
				<uwr>5__12 = null;
				<clip>5__13 = null;
				<ex>5__14 = null;
				<>1__state = -2;
			}

			private bool MoveNext()
			{
				//IL_0301: Unknown result type (might be due to invalid IL or missing references)
				//IL_0307: Invalid comparison between Unknown and I4
				//IL_03c6: Unknown result type (might be due to invalid IL or missing references)
				//IL_03cc: Invalid comparison between Unknown and I4
				//IL_03f4: Unknown result type (might be due to invalid IL or missing references)
				try
				{
					int num = <>1__state;
					if (num != 0)
					{
						if (num != 1)
						{
							return false;
						}
						<>1__state = -4;
						if ((int)<uwr>5__12.result != 1)
						{
							ManualLogSource? logger = Logger;
							if (logger != null)
							{
								logger.LogError((object)("Failed to load MP3 " + <file>5__11 + ": " + <uwr>5__12.error + ". Skipping file."));
							}
						}
						else
						{
							<clip>5__13 = DownloadHandlerAudioClip.GetContent(<uwr>5__12);
							if ((Object)(object)<clip>5__13 == (Object)null)
							{
								ManualLogSource? logger2 = Logger;
								if (logger2 != null)
								{
									logger2.LogError((object)("Failed to create AudioClip from " + <file>5__11 + ": Null clip. File may contain non-audio streams (e.g., embedded images). Skipping file."));
								}
							}
							else
							{
								try
								{
									<clip>5__13.LoadAudioData();
									if ((int)<clip>5__13.loadState == 2)
									{
										((Object)<clip>5__13).name = Path.GetFileNameWithoutExtension(<file>5__11);
										regionClips[<regionName>5__5].Add(<clip>5__13);
										<totalClips>5__2++;
										ManualLogSource? logger3 = Logger;
										if (logger3 != null)
										{
											logger3.LogInfo((object)$"Loaded MP3 for {<regionName>5__5}: {((Object)<clip>5__13).name}, Length: {<clip>5__13.length} seconds");
										}
										goto IL_04ea;
									}
									ManualLogSource? logger4 = Logger;
									if (logger4 != null)
									{
										logger4.LogError((object)$"Failed to preload audio data for {<file>5__11}: Load state {<clip>5__13.loadState}. Skipping file.");
									}
								}
								catch (Exception ex)
								{
									<ex>5__14 = ex;
									ManualLogSource? logger5 = Logger;
									if (logger5 != null)
									{
										logger5.LogError((object)("Exception while loading audio data for " + <file>5__11 + ": " + <ex>5__14.Message + ". Skipping file."));
									}
								}
							}
						}
						<>m__Finally2();
						goto IL_0513;
					}
					<>1__state = -1;
					if (isLoading)
					{
						ManualLogSource? logger6 = Logger;
						if (logger6 != null)
						{
							logger6.LogInfo((object)"Already loading audio clips, skipping.");
						}
						return false;
					}
					isLoading = true;
					ManualLogSource? logger7 = Logger;
					if (logger7 != null)
					{
						logger7.LogInfo((object)"Starting to preload audio clips...");
					}
					<regions>5__1 = new Dictionary<string, ConfigEntry<string>>
					{
						{ "Beach", beachFolderConfig },
						{ "Tropics", tropicsFolderConfig },
						{ "Alpine", alpineFolderConfig },
						{ "Mesa", mesaFolderConfig },
						{ "Caldera", calderaFolderConfig },
						{ "Kiln", kilnFolderConfig },
						{ "Peak", peakFolderConfig },
						{ "Tomb", tombFolderConfig },
						{ "Default", defaultFolderConfig }
					};
					<totalClips>5__2 = 0;
					<>s__3 = <regions>5__1.GetEnumerator();
					<>1__state = -3;
					goto IL_0564;
					IL_0513:
					<>s__10++;
					goto IL_0521;
					IL_0521:
					if (<>s__10 < <>s__9.Length)
					{
						<file>5__11 = <>s__9[<>s__10];
						ManualLogSource? logger8 = Logger;
						if (logger8 != null)
						{
							logger8.LogInfo((object)("Loading MP3 for " + <regionName>5__5 + ": " + Path.GetFileName(<file>5__11)));
						}
						<uwr>5__12 = UnityWebRequestMultimedia.GetAudioClip("file:///" + <file>5__11, (AudioType)13);
						<>1__state = -4;
						<>2__current = <uwr>5__12.SendWebRequest();
						<>1__state = 1;
						return true;
					}
					<>s__9 = null;
					<regionName>5__5 = null;
					<folderName>5__6 = null;
					<folderPath>5__7 = null;
					<mp3Files>5__8 = null;
					<region>5__4 = default(KeyValuePair<string, ConfigEntry<string>>);
					goto IL_0564;
					IL_0564:
					while (true)
					{
						if (<>s__3.MoveNext())
						{
							<region>5__4 = <>s__3.Current;
							<regionName>5__5 = <region>5__4.Key;
							<folderName>5__6 = <region>5__4.Value.Value.Trim();
							<folderPath>5__7 = (Path.IsPathRooted(<folderName>5__6) ? <folderName>5__6 : Path.Combine(musicFolder, <folderName>5__6));
							if (!Directory.Exists(<folderPath>5__7))
							{
								ManualLogSource? logger9 = Logger;
								if (logger9 != null)
								{
									logger9.LogWarning((object)("Folder not found for " + <regionName>5__5 + ": " + <folderPath>5__7));
								}
								continue;
							}
							<mp3Files>5__8 = Directory.GetFiles(<folderPath>5__7, "*.mp3");
							if (<mp3Files>5__8.Length != 0)
							{
								break;
							}
							ManualLogSource? logger10 = Logger;
							if (logger10 != null)
							{
								logger10.LogWarning((object)("No MP3 files found in " + <regionName>5__5 + " folder: " + <folderPath>5__7));
							}
							continue;
						}
						<>m__Finally1();
						<>s__3 = default(Dictionary<string, ConfigEntry<string>>.Enumerator);
						ManualLogSource? logger11 = Logger;
						if (logger11 != null)
						{
							logger11.LogInfo((object)$"Preloading complete. Total clips loaded: {<totalClips>5__2}");
						}
						isLoading = false;
						return false;
					}
					regionClips[<regionName>5__5] = new List<AudioClip>();
					<>s__9 = <mp3Files>5__8;
					<>s__10 = 0;
					goto IL_0521;
					IL_04ea:
					<clip>5__13 = null;
					<>m__Finally2();
					<uwr>5__12 = null;
					<file>5__11 = null;
					goto IL_0513;
				}
				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;
				((IDisposable)<>s__3).Dispose();
			}

			private void <>m__Finally2()
			{
				<>1__state = -3;
				if (<uwr>5__12 != null)
				{
					((IDisposable)<uwr>5__12).Dispose();
				}
			}

			[DebuggerHidden]
			void IEnumerator.Reset()
			{
				throw new NotSupportedException();
			}
		}

		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> mesaFolderConfig = null;

		private static ConfigEntry<string> calderaFolderConfig = null;

		private static ConfigEntry<string> kilnFolderConfig = null;

		private static ConfigEntry<string> peakFolderConfig = null;

		private static ConfigEntry<string> tombFolderConfig = null;

		private static ConfigEntry<string> defaultFolderConfig = null;

		private static ConfigEntry<bool> useDefaultTombMusic = null;

		private static ConfigEntry<bool> allowStingerMusic = null;

		private static ConfigEntry<bool> preloadAudioClips = null;

		private static string currentRegion = "Default";

		private static readonly Dictionary<string, List<AudioClip>> regionClips = new Dictionary<string, List<AudioClip>>();

		private static bool isLoading = false;

		private const float FADE_DURATION = 1f;

		public const string Id = "com.mthwj.minecraftmusic";

		public static string Name => "MinecraftMusicPlugin";

		public static string Version => "0.1.0";

		private void Awake()
		{
			//IL_0203: Unknown result type (might be due to invalid IL or missing references)
			//IL_0209: 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).");
			mesaFolderConfig = ((BaseUnityPlugin)this).Config.Bind<string>("MusicFolders", "MesaFolder", "Mesa", "Folder for Mesa 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).");
			tombFolderConfig = ((BaseUnityPlugin)this).Config.Bind<string>("MusicFolders", "TombFolder", "Tomb", "Folder for Tomb 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).");
			useDefaultTombMusic = ((BaseUnityPlugin)this).Config.Bind<bool>("MusicOptions", "UseDefaultTombMusic", false, "If true, uses vanilla tomb music instead of custom MP3s for the Tomb region.");
			allowStingerMusic = ((BaseUnityPlugin)this).Config.Bind<bool>("MusicOptions", "AllowStingerMusic", false, "If true, allows default stinger music related to sunrise, sunset, night, and climb events (e.g., 'Music Stinger Tropics Sunset', 'Music Stinger Night 1', 'climbStingerTropics') to play alongside custom music. If false, blocks these musical stingers to ensure only custom music plays, while preserving gameplay-critical audio cues like fog rising or bee swarm sounds.");
			preloadAudioClips = ((BaseUnityPlugin)this).Config.Bind<bool>("MusicOptions", "PreloadAudioClips", false, "If true, preloads all MP3s during game startup to avoid lag spikes during gameplay, but may cause a delay (e.g., 10 seconds) at the main menu. If false, loads MP3s on-demand during gameplay, which may cause minor lag when tracks change.");
			Harmony val = new Harmony("com.mthwj.minecraftmusic.patch");
			val.PatchAll();
			ManualLogSource? logger2 = Logger;
			if (logger2 != null)
			{
				logger2.LogInfo((object)"Harmony patches applied successfully");
			}
			if (preloadAudioClips.Value)
			{
				((MonoBehaviour)this).StartCoroutine(LoadAllAudioClips());
				return;
			}
			ManualLogSource? logger3 = Logger;
			if (logger3 != null)
			{
				logger3.LogInfo((object)"PreloadAudioClips is disabled, using on-demand loading.");
			}
		}

		[IteratorStateMachine(typeof(<LoadAllAudioClips>d__20))]
		private IEnumerator LoadAllAudioClips()
		{
			//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
			return new <LoadAllAudioClips>d__20(0)
			{
				<>4__this = this
			};
		}
	}
}
namespace System.Runtime.CompilerServices
{
	[AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)]
	internal sealed class IgnoresAccessChecksToAttribute : Attribute
	{
		public IgnoresAccessChecksToAttribute(string assemblyName)
		{
		}
	}
}