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 BepInEx; using HarmonyLib; using Microsoft.CodeAnalysis; using UnityEngine; using UnityEngine.Networking; using YamlDotNet.Serialization; using YamlDotNet.Serialization.NamingConventions; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)] [assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")] [assembly: AssemblyCompany("GlitnirMusicZones")] [assembly: AssemblyConfiguration("Debug")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0")] [assembly: AssemblyProduct("GlitnirMusicZones")] [assembly: AssemblyTitle("GlitnirMusicZones")] [assembly: AssemblyVersion("1.0.0.0")] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace GlitnirMusicZones { internal static class DefaultConfig { public const string YAML = "# ╔══════════════════════════════════════════════════════════════════╗\r\n# ║ GLITNIR MUSIC ZONES — music_config.yaml ║\r\n# ╚══════════════════════════════════════════════════════════════════╝\r\n# Use URLs diretas de MP3 (sem expiração). Recomendado: GitHub Releases\r\n# ou cdn.pixabay.com. Evite links do Discord (expiram em horas).\r\n#\r\n# Após salvar o arquivo, a config recarrega automaticamente no jogo.\r\n\r\n# ─── MENU PRINCIPAL ────────────────────────────────────────────────\r\nmenu:\r\n enabled: true\r\n volume: 0.3\r\n url: \"https://cdn.pixabay.com/download/audio/2025/07/24/audio_9d4a9c72f8.mp3?filename=wesleysert-glitnir-valhhala-1-379314.mp3\"\r\n\r\n# ─── BIOMAS ────────────────────────────────────────────────────────\r\n# Biomas disponíveis: Meadows, BlackForest, Swamp, Mountain, Plains,\r\n# Mistlands, AshLands, DeepNorth, Ocean\r\nbiomes:\r\n enabled: true\r\n volume: 0.6\r\n tracks:\r\n Meadows:\r\n enabled: true\r\n url: \"\"\r\n BlackForest:\r\n enabled: true\r\n url: \"\"\r\n Swamp:\r\n enabled: true\r\n url: \"\"\r\n Mountain:\r\n enabled: true\r\n url: \"\"\r\n Plains:\r\n enabled: true\r\n url: \"\"\r\n Mistlands:\r\n enabled: true\r\n url: \"\"\r\n AshLands:\r\n enabled: true\r\n url: \"\"\r\n DeepNorth:\r\n enabled: true\r\n url: \"\"\r\n Ocean:\r\n enabled: true\r\n url: \"\"\r\n\r\n# ─── TERRITÓRIOS (Locations do ZoneSystem) ─────────────────────────\r\n# location: nome exato da Location (ex: StartTemple, Crypt2)\r\n# radius: raio em unidades (0 = usa o radius global abaixo)\r\n# dungeon_only: true = só toca dentro da dungeon (faixa Y)\r\n# dungeon_y_min/max: faixa Y da dungeon (-1 = usa o global)\r\nterritories:\r\n enabled: true\r\n volume: 0.65\r\n radius: 90.0\r\n dungeon_y_min: 4500.0\r\n dungeon_y_max: 5500.0\r\n tracks:\r\n - enabled: true\r\n location: StartTemple\r\n radius: 60.0\r\n dungeon_only: false\r\n dungeon_y_min: -1\r\n dungeon_y_max: -1\r\n url: \"\"\r\n\r\n - enabled: false\r\n location: Vendor_BlackForest\r\n radius: 0.0\r\n dungeon_only: false\r\n dungeon_y_min: -1\r\n dungeon_y_max: -1\r\n url: \"\"\r\n\r\n - enabled: true\r\n location: Crypt2\r\n radius: 90.0\r\n dungeon_only: true\r\n dungeon_y_min: 4500\r\n dungeon_y_max: 5500\r\n url: \"\"\r\n\r\n - enabled: true\r\n location: Crypt3\r\n radius: 90.0\r\n dungeon_only: true\r\n dungeon_y_min: 4500\r\n dungeon_y_max: 5500\r\n url: \"\"\r\n\r\n - enabled: true\r\n location: Crypt4\r\n radius: 90.0\r\n dungeon_only: true\r\n dungeon_y_min: 4500\r\n dungeon_y_max: 5500\r\n url: \"\"\r\n\r\n# ─── ZONAS POR COORDENADA ──────────────────────────────────────────\r\n# Use para vilas ou regiões sem Location no ZoneSystem.\r\n# x/z: coordenadas do centro no mapa do Valheim\r\nzones:\r\n enabled: true\r\n tracks:\r\n - enabled: false\r\n name: Exemplo Vila\r\n x: 0.0\r\n z: 0.0\r\n radius: 80.0\r\n volume: 0.65\r\n url: \"\"\r\n\r\n# ─── BOSSES ────────────────────────────────────────────────────────\r\n# Prefab name do boss sem '(Clone)'. Toca enquanto o boss estiver vivo no raio.\r\n# Bosses vanilla: Eikthyr, gd_king, Bonemass, Dragon, GoblinKing, SeekerQueen, Fader\r\nbosses:\r\n enabled: true\r\n volume: 0.7\r\n radius: 120.0\r\n tracks:\r\n Eikthyr:\r\n enabled: true\r\n url: \"\"\r\n gd_king:\r\n enabled: true\r\n url: \"\"\r\n Bonemass:\r\n enabled: true\r\n url: \"\"\r\n Dragon:\r\n enabled: true\r\n url: \"\"\r\n GoblinKing:\r\n enabled: true\r\n url: \"\"\r\n SeekerQueen:\r\n enabled: true\r\n url: \"\"\r\n Fader:\r\n enabled: true\r\n url: \"\"\r\n\r\n# ─── CRIATURAS ─────────────────────────────────────────────────────\r\n# Toca enquanto houver ao menos uma criatura viva no raio.\r\ncreatures:\r\n enabled: true\r\n volume: 0.55\r\n radius: 30.0\r\n tracks:\r\n Troll:\r\n enabled: false\r\n url: \"\"\r\n GoblinBrute:\r\n enabled: false\r\n url: \"\"\r\n BlobTar:\r\n enabled: false\r\n url: \"\"\r\n Seeker:\r\n enabled: false\r\n url: \"\"\r\n Leech:\r\n enabled: false\r\n url: \"\"\r\n"; } internal static class MusicManPatches { private static AudioSource _musicManSource = null; private static float _volCheckTimer = 0f; private static AudioSource MusicManSource { get { if ((Object)(object)_musicManSource == (Object)null && (Object)(object)MusicMan.instance != (Object)null) { _musicManSource = ((Component)MusicMan.instance).GetComponent(); } return _musicManSource; } } public static float RealMusicVolume { get; private set; } = PlayerPrefs.GetFloat("MusicVolume", 1f); public static void InvalidateSourceCache() { _musicManSource = null; } private static bool PrefixStartMusic() { if (!Plugin.VanillaMuted) { return true; } AudioSource musicManSource = MusicManSource; if (musicManSource != null) { musicManSource.Stop(); } return false; } private static bool PrefixQueue() { return !Plugin.VanillaMuted; } private static void PrefixUpdate() { _volCheckTimer += Time.deltaTime; if (!(_volCheckTimer < 0.2f)) { _volCheckTimer = 0f; float @float = PlayerPrefs.GetFloat("MusicVolume", 1f); if (@float >= 0f) { RealMusicVolume = @float; } } } private static void PostfixUpdate() { if (Plugin.VanillaMuted) { MusicMan.m_masterMusicVolume = 0f; AudioSource musicManSource = MusicManSource; if ((Object)(object)musicManSource != (Object)null && musicManSource.isPlaying) { musicManSource.Stop(); } } } public static void ApplyAll(Harmony harmony) { //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Expected O, but got Unknown //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Expected O, but got Unknown //IL_003f: Unknown result type (might be due to invalid IL or missing references) //IL_0045: Expected O, but got Unknown //IL_00ce: Unknown result type (might be due to invalid IL or missing references) //IL_00d5: Expected O, but got Unknown Type typeFromHandle = typeof(MusicManPatches); HarmonyMethod val = new HarmonyMethod(typeFromHandle.GetMethod("PrefixStartMusic", BindingFlags.Static | BindingFlags.NonPublic)); HarmonyMethod val2 = new HarmonyMethod(typeFromHandle.GetMethod("PrefixQueue", BindingFlags.Static | BindingFlags.NonPublic)); HarmonyMethod val3 = new HarmonyMethod(typeFromHandle.GetMethod("PostfixUpdate", BindingFlags.Static | BindingFlags.NonPublic)); MethodInfo[] methods = typeof(MusicMan).GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); foreach (MethodInfo methodInfo in methods) { if (methodInfo.Name == "StartMusic") { harmony.Patch((MethodBase)methodInfo, val, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); } else if (methodInfo.Name == "Queue") { harmony.Patch((MethodBase)methodInfo, val2, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); } } HarmonyMethod val4 = new HarmonyMethod(typeFromHandle.GetMethod("PrefixUpdate", BindingFlags.Static | BindingFlags.NonPublic)); MethodInfo method = typeof(MusicMan).GetMethod("Update", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (method != null) { harmony.Patch((MethodBase)method, val4, val3, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); } } } public class YamlConfig { public YamlMenu menu { get; set; } = new YamlMenu(); public YamlBiomes biomes { get; set; } = new YamlBiomes(); public YamlTerritories territories { get; set; } = new YamlTerritories(); public YamlZones zones { get; set; } = new YamlZones(); public YamlBosses bosses { get; set; } = new YamlBosses(); public YamlCreatures creatures { get; set; } = new YamlCreatures(); } public class YamlMenu { public bool enabled { get; set; } = true; public float volume { get; set; } = 0.3f; public string url { get; set; } = ""; } public class YamlBiomes { public bool enabled { get; set; } = true; public float volume { get; set; } = 0.6f; public Dictionary tracks { get; set; } = new Dictionary(); } public class YamlTerritories { public bool enabled { get; set; } = true; public float volume { get; set; } = 0.65f; public float radius { get; set; } = 90f; public float dungeon_y_min { get; set; } = 4500f; public float dungeon_y_max { get; set; } = 5500f; public List tracks { get; set; } = new List(); } public class YamlZones { public bool enabled { get; set; } = true; public List tracks { get; set; } = new List(); } public class YamlBosses { public bool enabled { get; set; } = true; public float volume { get; set; } = 0.7f; public float radius { get; set; } = 120f; public Dictionary tracks { get; set; } = new Dictionary(); } public class YamlCreatures { public bool enabled { get; set; } = true; public float volume { get; set; } = 0.55f; public float radius { get; set; } = 30f; public Dictionary tracks { get; set; } = new Dictionary(); } public class YamlTrack { public bool enabled { get; set; } = true; public string url { get; set; } = ""; } public class YamlTerritoryTrack { public bool enabled { get; set; } = true; public string location { get; set; } = ""; public float radius { get; set; } = 0f; public bool dungeon_only { get; set; } = false; public float dungeon_y_min { get; set; } = -1f; public float dungeon_y_max { get; set; } = -1f; public string url { get; set; } = ""; } public class YamlZoneTrack { public bool enabled { get; set; } = true; public string name { get; set; } = ""; public float x { get; set; } = 0f; public float z { get; set; } = 0f; public float radius { get; set; } = 60f; public float volume { get; set; } = 0.65f; public string url { get; set; } = ""; } [BepInPlugin("glitnir.musiczones", "Glitnir Music Zones", "1.0.0")] public class Plugin : BaseUnityPlugin { private enum MusicState { None, Menu, Biome, Territory, Boss, Creature } internal class TerritoryEntry { public string location; public float radius; public float dungeonYMin; public float dungeonYMax; public bool dungeonOnly; public bool enabled; public string url; public bool IsActive => enabled && !string.IsNullOrWhiteSpace(url) && !string.IsNullOrWhiteSpace(location); } internal class ZoneEntry { public string name; public float x; public float z; public float radius; public float volume; public bool enabled; public string url; public bool IsActive => enabled && !string.IsNullOrWhiteSpace(url); } internal class MusicEntry { public bool enabled; public string url; public bool IsActive => enabled && !string.IsNullOrWhiteSpace(url); public MusicEntry(bool enabled, string url) { this.enabled = enabled; this.url = url ?? ""; } } [CompilerGenerated] private sealed class d__68 : IEnumerator, IDisposable, IEnumerator { private int <>1__state; private object <>2__current; public bool andUnmute; public Plugin <>4__this; private float 5__1; private float 5__2; object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public d__68(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; 5__1 = audioSource.volume; 5__2 = 0f; break; case 1: <>1__state = -1; break; } if (5__2 < <>4__this.fadeDuration) { 5__2 += Time.deltaTime; audioSource.volume = Mathf.Lerp(5__1, 0f, 5__2 / <>4__this.fadeDuration); <>2__current = null; <>1__state = 1; return true; } audioSource.Stop(); <>4__this.ReleaseCurrentClip(); if (andUnmute) { <>4__this.UnmuteVanilla(); } 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 d__67 : IEnumerator, IDisposable, IEnumerator { private int <>1__state; private object <>2__current; public string url; public float cfgVolume; public Plugin <>4__this; private float 5__1; private float 5__2; private float 5__3; private float 5__4; private AudioClip 5__5; private float
5__6; object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public d__67(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { 5__5 = null; <>1__state = -2; } private bool MoveNext() { switch (<>1__state) { default: return false; case 0: <>1__state = -1; 5__1 = <>4__this.fadeDuration + 15f; 5__2 = 0f; 5__3 = audioSource.volume; 5__4 = 0f; goto IL_0156; case 1: <>1__state = -1; goto IL_0156; case 2: <>1__state = -1; goto IL_0297; case 3: { <>1__state = -1; break; } IL_0156: if (5__4 < <>4__this.fadeDuration || (<>4__this.preloadingUrls.Contains(url) && 5__2 < 5__1)) {
5__6 = Time.deltaTime; 5__4 +=
5__6; 5__2 +=
5__6; if (5__4 <= <>4__this.fadeDuration) { audioSource.volume = Mathf.Lerp(5__3, 0f, 5__4 / <>4__this.fadeDuration); } else { audioSource.volume = 0f; } if (<>4__this.preloadingUrls.Contains(url) || !(5__4 >= <>4__this.fadeDuration)) { <>2__current = null; <>1__state = 1; return true; } } audioSource.Stop(); <>4__this.ReleaseCurrentClip(); if (<>4__this.clipCache.TryGetValue(url, out 5__5) && (Object)(object)5__5 != (Object)null) { <>4__this.currentClipUrl = url; audioSource.clip = 5__5; audioSource.volume = 0f; audioSource.Play(); 5__4 = 0f; goto IL_0297; } <>2__current = ((MonoBehaviour)<>4__this).StartCoroutine(<>4__this.LoadAndFadeIn(url, cfgVolume)); <>1__state = 3; return true; IL_0297: if (5__4 < <>4__this.fadeDuration) { 5__4 += Time.deltaTime; audioSource.volume = Mathf.Lerp(0f, <>4__this.FinalVolume(cfgVolume), 5__4 / <>4__this.fadeDuration); <>2__current = null; <>1__state = 2; return true; } audioSource.volume = <>4__this.FinalVolume(cfgVolume); ((BaseUnityPlugin)<>4__this).Logger.LogInfo((object)$"[Glitnir] Tocando do cache (vol={audioSource.volume:F2})."); break; } 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 d__66 : IEnumerator, IDisposable, IEnumerator { private int <>1__state; private object <>2__current; public AudioClip nextClip; public string url; public float cfgVolume; public Plugin <>4__this; private float 5__1; private float 5__2; object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public d__66(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; 5__1 = audioSource.volume; 5__2 = 0f; goto IL_00a3; case 1: <>1__state = -1; goto IL_00a3; case 2: { <>1__state = -1; break; } IL_00a3: if (5__2 < <>4__this.fadeDuration) { 5__2 += Time.deltaTime; audioSource.volume = Mathf.Lerp(5__1, 0f, 5__2 / <>4__this.fadeDuration); <>2__current = null; <>1__state = 1; return true; } audioSource.Stop(); <>4__this.currentClipUrl = url; audioSource.clip = nextClip; audioSource.volume = 0f; audioSource.Play(); 5__2 = 0f; break; } if (5__2 < <>4__this.fadeDuration) { 5__2 += Time.deltaTime; audioSource.volume = Mathf.Lerp(0f, <>4__this.FinalVolume(cfgVolume), 5__2 / <>4__this.fadeDuration); <>2__current = null; <>1__state = 2; return true; } audioSource.volume = <>4__this.FinalVolume(cfgVolume); ((BaseUnityPlugin)<>4__this).Logger.LogInfo((object)$"[Glitnir] Tocando do cache (vol={audioSource.volume:F2})."); 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 d__69 : IEnumerator, IDisposable, IEnumerator { private int <>1__state; private object <>2__current; public string url; public float cfgVolume; public Plugin <>4__this; private AudioClip 5__1; private float 5__2; private UnityWebRequest 5__3; private AudioClip 5__4; private float 5__5; object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public d__69(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(); } } 5__1 = null; 5__3 = null; 5__4 = null; <>1__state = -2; } private bool MoveNext() { //IL_0213: Unknown result type (might be due to invalid IL or missing references) //IL_0219: Invalid comparison between Unknown and I4 //IL_01cc: 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; if (string.IsNullOrWhiteSpace(url)) { result = false; } else { if (<>4__this.clipCache.TryGetValue(url, out 5__1) && (Object)(object)5__1 != (Object)null) { <>4__this.currentClipUrl = url; audioSource.clip = 5__1; audioSource.volume = 0f; audioSource.Play(); 5__2 = 0f; goto IL_013c; } 5__3 = UnityWebRequestMultimedia.GetAudioClip(url, (AudioType)13); <>1__state = -3; ((DownloadHandlerAudioClip)5__3.downloadHandler).compressed = false; 5__3.timeout = 15; <>2__current = 5__3.SendWebRequest(); <>1__state = 2; result = true; } goto end_IL_0000; case 1: <>1__state = -1; goto IL_013c; case 2: <>1__state = -3; if ((int)5__3.result != 1) { ((BaseUnityPlugin)<>4__this).Logger.LogError((object)("[Glitnir] Erro ao carregar: " + 5__3.error + " — URL: " + url)); <>4__this.clipCache[url] = null; result = false; break; } 5__4 = DownloadHandlerAudioClip.GetContent(5__3); if ((Object)(object)5__4 == (Object)null || <>4__this.currentUrl != url) { if ((Object)(object)5__4 != (Object)null) { Object.Destroy((Object)(object)5__4); } result = false; break; } <>4__this.clipCache[url] = 5__4; <>4__this.preloadingUrls.Remove(url); <>4__this.ReleaseCurrentClip(); audioSource.clip = 5__4; audioSource.volume = 0f; audioSource.Play(); <>4__this.currentClipUrl = url; 5__5 = 0f; goto IL_03cc; case 3: { <>1__state = -3; goto IL_03cc; } IL_013c: if (5__2 < <>4__this.fadeDuration) { 5__2 += Time.deltaTime; audioSource.volume = Mathf.Lerp(0f, <>4__this.FinalVolume(cfgVolume), 5__2 / <>4__this.fadeDuration); <>2__current = null; <>1__state = 1; result = true; } else { audioSource.volume = <>4__this.FinalVolume(cfgVolume); ((BaseUnityPlugin)<>4__this).Logger.LogInfo((object)$"[Glitnir] Tocando (vol={audioSource.volume:F2})."); result = false; } goto end_IL_0000; IL_03cc: if (5__5 < <>4__this.fadeDuration) { 5__5 += Time.deltaTime; audioSource.volume = Mathf.Lerp(0f, <>4__this.FinalVolume(cfgVolume), 5__5 / <>4__this.fadeDuration); <>2__current = null; <>1__state = 3; result = true; } else { audioSource.volume = <>4__this.FinalVolume(cfgVolume); ((BaseUnityPlugin)<>4__this).Logger.LogInfo((object)$"[Glitnir] Tocando (vol={audioSource.volume:F2})."); 5__4 = null; <>m__Finally1(); 5__3 = null; result = false; } 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 (5__3 != null) { ((IDisposable)5__3).Dispose(); } } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } [CompilerGenerated] private sealed class d__64 : IEnumerator, IDisposable, IEnumerator { private int <>1__state; private object <>2__current; public string url; public Plugin <>4__this; private UnityWebRequest 5__1; private AudioClip 5__2; object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public d__64(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(); } } 5__1 = null; 5__2 = null; <>1__state = -2; } private bool MoveNext() { //IL_0087: Unknown result type (might be due to invalid IL or missing references) //IL_00ce: Unknown result type (might be due to invalid IL or missing references) //IL_00d4: Invalid comparison between Unknown and I4 bool result; try { switch (<>1__state) { default: result = false; break; case 0: <>1__state = -1; <>4__this.preloadingUrls.Add(url); ((BaseUnityPlugin)<>4__this).Logger.LogInfo((object)("[Glitnir] Pré-carregando: " + url)); 5__1 = UnityWebRequestMultimedia.GetAudioClip(url, (AudioType)13); <>1__state = -3; ((DownloadHandlerAudioClip)5__1.downloadHandler).compressed = false; 5__1.timeout = 20; <>2__current = 5__1.SendWebRequest(); <>1__state = 1; result = true; break; case 1: <>1__state = -3; if ((int)5__1.result != 1) { ((BaseUnityPlugin)<>4__this).Logger.LogWarning((object)("[Glitnir] Falha no pré-carregamento: " + 5__1.error + " — URL: " + url)); <>4__this.clipCache[url] = null; <>4__this.preloadingUrls.Remove(url); result = false; <>m__Finally1(); break; } 5__2 = DownloadHandlerAudioClip.GetContent(5__1); if ((Object)(object)5__2 != (Object)null) { <>4__this.clipCache[url] = 5__2; ((BaseUnityPlugin)<>4__this).Logger.LogInfo((object)$"[Glitnir] Cache: {((Object)5__2).name} ({<>4__this.clipCache.Count} clips em RAM)"); } <>4__this.preloadingUrls.Remove(url); 5__2 = null; <>m__Finally1(); 5__1 = null; result = false; break; } } 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 (5__1 != null) { ((IDisposable)5__1).Dispose(); } } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } [CompilerGenerated] private sealed class d__71 : IEnumerator, IDisposable, IEnumerator { private int <>1__state; private object <>2__current; public Plugin <>4__this; private AudioClip 5__1; private UnityWebRequest 5__2; private AudioClip 5__3; object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public d__71(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(); } } 5__1 = null; 5__2 = null; 5__3 = null; <>1__state = -2; } private bool MoveNext() { //IL_016a: Unknown result type (might be due to invalid IL or missing references) //IL_0170: Invalid comparison between Unknown and I4 //IL_0123: Unknown result type (might be due to invalid IL or missing references) bool result; try { switch (<>1__state) { default: result = false; break; case 0: <>1__state = -1; if (<>4__this.menuEntry == null || !<>4__this.menuEnabled || !<>4__this.menuEntry.IsActive) { result = false; } else if (<>4__this.clipCache.TryGetValue(<>4__this.menuEntry.url, out 5__1)) { if ((Object)(object)5__1 != (Object)null) { <>4__this.menuClip = 5__1; <>4__this.menuClipReady = true; ((BaseUnityPlugin)<>4__this).Logger.LogInfo((object)"[Glitnir] Menu: usando clip do cache."); } result = false; } else { ((BaseUnityPlugin)<>4__this).Logger.LogInfo((object)"[Glitnir] Pré-carregando música do menu..."); 5__2 = UnityWebRequestMultimedia.GetAudioClip(<>4__this.menuEntry.url, (AudioType)13); <>1__state = -3; ((DownloadHandlerAudioClip)5__2.downloadHandler).compressed = false; 5__2.timeout = 15; <>2__current = 5__2.SendWebRequest(); <>1__state = 1; result = true; } break; case 1: <>1__state = -3; if ((int)5__2.result != 1) { ((BaseUnityPlugin)<>4__this).Logger.LogError((object)("[Glitnir] Falha no menu: " + 5__2.error)); <>4__this.clipCache[<>4__this.menuEntry.url] = null; result = false; <>m__Finally1(); break; } 5__3 = DownloadHandlerAudioClip.GetContent(5__2); if ((Object)(object)5__3 != (Object)null) { <>4__this.clipCache[<>4__this.menuEntry.url] = 5__3; <>4__this.menuClip = 5__3; <>4__this.menuClipReady = true; } ((BaseUnityPlugin)<>4__this).Logger.LogInfo((object)("[Glitnir] Menu " + (<>4__this.menuClipReady ? "pronto." : "clip nulo!"))); 5__3 = null; <>m__Finally1(); 5__2 = null; result = false; break; } } 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 (5__2 != null) { ((IDisposable)5__2).Dispose(); } } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } private static GameObject musicObject; private static AudioSource audioSource; private string currentClipUrl = ""; private readonly Dictionary clipCache = new Dictionary(); private readonly HashSet preloadingUrls = new HashSet(); private Coroutine fadeCoroutine = null; private float fadeDuration = 1f; private FileSystemWatcher configWatcher; private bool reloadPending = false; private float _reloadCooldown = 0f; private Harmony harmony; private MusicEntry menuEntry; private float menuVolume = 0.3f; private bool menuEnabled = true; private bool biomesEnabled = true; private float biomeVolume = 0.6f; private Dictionary biomeMap = new Dictionary(); private bool terrEnabled = true; private float terrVolume = 0.65f; private float terrRadius = 90f; private float terrDungeonYMin = 4500f; private float terrDungeonYMax = 5500f; private List terrList = new List(); private bool zonesEnabled = true; private List zoneList = new List(); private bool bossEnabled = true; private float bossVolume = 0.7f; private float bossRadius = 120f; private Dictionary bossMap = new Dictionary(); private bool creatEnabled = true; private float creatVolume = 0.55f; private float creatRadius = 30f; private Dictionary creatMap = new Dictionary(); private MusicState currentState = MusicState.None; private string currentUrl = ""; private AudioClip menuClip = null; private bool menuClipReady = false; private bool worldLoaded = false; private float checkInterval = 2f; private float checkTimer = 0f; private Vector3 _lastCheckPos = Vector3.zero; private readonly Dictionary _locPosCache = new Dictionary(); private float _locCacheTimer = 0f; private const float PreloadAheadMultiplier = 1.5f; private readonly List _charBuffer = new List(); public static bool VanillaMuted { get; private set; } private string ConfigPath => Path.Combine(Paths.ConfigPath, "glitnir.musiczones", "music_config.yaml"); private float FinalVolume(float cfgVolume) { return cfgVolume * MusicManPatches.RealMusicVolume; } private float CurrentCfgVolume() { return currentState switch { MusicState.Boss => bossVolume, MusicState.Creature => creatVolume, MusicState.Territory => terrVolume, MusicState.Biome => biomeVolume, _ => menuVolume, }; } private void MuteVanilla() { if (!VanillaMuted) { VanillaMuted = true; MusicManPatches.InvalidateSourceCache(); ((BaseUnityPlugin)this).Logger.LogInfo((object)"[Glitnir] Vanilla silenciada."); } } private void UnmuteVanilla() { if (VanillaMuted) { VanillaMuted = false; ((BaseUnityPlugin)this).Logger.LogInfo((object)"[Glitnir] Vanilla restaurada."); } } private void Awake() { //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Expected O, but got Unknown ((BaseUnityPlugin)this).Logger.LogInfo((object)"[Glitnir Music Zones] v1.0.0 iniciando..."); harmony = new Harmony("glitnir.musiczones"); try { MusicManPatches.ApplyAll(harmony); ((BaseUnityPlugin)this).Logger.LogInfo((object)"[Glitnir] Patches Harmony aplicados com sucesso."); } catch (Exception ex) { ((BaseUnityPlugin)this).Logger.LogError((object)("[Glitnir] Falha ao aplicar patches: " + ex.Message)); } EnsureDefaultConfig(); LoadConfig(); CreateMusicPlayer(); StartConfigWatcher(); ((MonoBehaviour)this).StartCoroutine(PreloadMenuMusic()); } private void OnDestroy() { Harmony obj = harmony; if (obj != null) { obj.UnpatchSelf(); } configWatcher?.Dispose(); UnmuteVanilla(); ClearCache(); } private void Update() { if (_reloadCooldown > 0f) { _reloadCooldown -= Time.deltaTime; } if (reloadPending && _reloadCooldown <= 0f) { reloadPending = false; _reloadCooldown = 1f; ((BaseUnityPlugin)this).Logger.LogInfo((object)"[Glitnir] Config alterada — recarregando..."); LoadConfig(); currentUrl = ""; currentState = MusicState.None; } bool flag = (Object)(object)ZNet.instance != (Object)null; if (flag && !worldLoaded && (Object)(object)Player.m_localPlayer != (Object)null) { worldLoaded = true; ((BaseUnityPlugin)this).Logger.LogInfo((object)"[Glitnir] Mundo carregado — parando música do menu."); StopOurMusic(); menuClip = null; menuClipReady = false; } if (!flag && worldLoaded) { worldLoaded = false; UnmuteVanilla(); ClearCache(); _locPosCache.Clear(); ((BaseUnityPlugin)this).Logger.LogInfo((object)"[Glitnir] Voltou ao menu."); ((MonoBehaviour)this).StartCoroutine(PreloadMenuMusic()); } if (!flag) { if (!menuEnabled || menuEntry == null || !menuEntry.IsActive) { if (VanillaMuted) { UnmuteVanilla(); } return; } if (menuClipReady && currentState != MusicState.Menu) { PlayCachedClip(menuClip, FinalVolume(menuVolume), MusicState.Menu, menuEntry.url); } if (currentState == MusicState.Menu && audioSource.isPlaying) { audioSource.volume = FinalVolume(menuVolume); } } else if (worldLoaded) { if (audioSource.isPlaying) { audioSource.volume = FinalVolume(CurrentCfgVolume()); } checkTimer -= Time.deltaTime; if (!(checkTimer > 0f)) { checkTimer = checkInterval; UpdateInGameMusic(); } } } private void UpdateInGameMusic() { //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Unknown result type (might be due to invalid IL or missing references) //IL_004c: Unknown result type (might be due to invalid IL or missing references) //IL_0091: Unknown result type (might be due to invalid IL or missing references) //IL_02b8: Unknown result type (might be due to invalid IL or missing references) //IL_02fe: Unknown result type (might be due to invalid IL or missing references) //IL_0346: Unknown result type (might be due to invalid IL or missing references) //IL_034c: Unknown result type (might be due to invalid IL or missing references) //IL_0358: Unknown result type (might be due to invalid IL or missing references) //IL_035d: Unknown result type (might be due to invalid IL or missing references) //IL_0365: Unknown result type (might be due to invalid IL or missing references) //IL_010d: Unknown result type (might be due to invalid IL or missing references) //IL_0115: Unknown result type (might be due to invalid IL or missing references) //IL_0172: Unknown result type (might be due to invalid IL or missing references) //IL_017a: Unknown result type (might be due to invalid IL or missing references) Player localPlayer = Player.m_localPlayer; if ((Object)(object)localPlayer == (Object)null) { return; } Vector3 position = ((Component)localPlayer).transform.position; float num = Vector3.Distance(position, _lastCheckPos); checkInterval = ((num < 3f) ? 4f : 2f); _lastCheckPos = position; _locCacheTimer += checkInterval; if (_locCacheTimer > 30f) { _locPosCache.Clear(); _locCacheTimer = 0f; } TryPreloadNearby(position); if (bossEnabled || creatEnabled) { string text = null; string text2 = null; float num2 = Math.Max(bossRadius, creatRadius); _charBuffer.Clear(); foreach (Character allCharacter in Character.GetAllCharacters()) { if (!((Object)(object)allCharacter == (Object)null) && !allCharacter.IsDead() && Vector3.Distance(position, ((Component)allCharacter).transform.position) <= num2) { _charBuffer.Add(allCharacter); } } foreach (Character item in _charBuffer) { float num3 = Vector3.Distance(position, ((Component)item).transform.position); string key = ((Object)item).name.Replace("(Clone)", "").Trim(); if (bossEnabled && text == null && num3 <= bossRadius && bossMap.TryGetValue(key, out var value) && value.IsActive) { text = value.url; } if (creatEnabled && text2 == null && num3 <= creatRadius && creatMap.TryGetValue(key, out var value2) && value2.IsActive) { text2 = value2.url; } if (text != null && text2 != null) { break; } } if (text != null) { TryPreload(text); SwitchMusic(text, bossVolume, MusicState.Boss); return; } if (text2 != null) { TryPreload(text2); SwitchMusic(text2, creatVolume, MusicState.Creature); return; } } if (terrEnabled) { string territoryMusic = GetTerritoryMusic(position); if (!string.IsNullOrEmpty(territoryMusic)) { TryPreload(territoryMusic); SwitchMusic(territoryMusic, terrVolume, MusicState.Territory); return; } } if (zonesEnabled && GetZoneMatch(position, out var url, out var volume)) { TryPreload(url); SwitchMusic(url, volume, MusicState.Territory); return; } if (biomesEnabled) { Biome key2 = (Biome)((WorldGenerator.instance != null) ? ((int)WorldGenerator.instance.GetBiome(position.x, position.z, 0.02f, false)) : 0); if (biomeMap.TryGetValue(key2, out var value3) && value3.IsActive) { TryPreload(value3.url); SwitchMusic(value3.url, biomeVolume, MusicState.Biome); return; } } if (currentState != 0) { if (fadeCoroutine != null) { ((MonoBehaviour)this).StopCoroutine(fadeCoroutine); } fadeCoroutine = ((MonoBehaviour)this).StartCoroutine(FadeOutAndStop(andUnmute: true)); currentState = MusicState.None; currentUrl = ""; ((BaseUnityPlugin)this).Logger.LogInfo((object)"[Glitnir] Sem zona ativa — vanilla tocando."); } } private void TryPreloadNearby(Vector3 pos) { //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_004f: Unknown result type (might be due to invalid IL or missing references) //IL_00c6: Unknown result type (might be due to invalid IL or missing references) //IL_00c7: Unknown result type (might be due to invalid IL or missing references) //IL_00ce: Unknown result type (might be due to invalid IL or missing references) //IL_00d7: Unknown result type (might be due to invalid IL or missing references) //IL_00dd: Unknown result type (might be due to invalid IL or missing references) //IL_00e3: Unknown result type (might be due to invalid IL or missing references) //IL_00e8: Unknown result type (might be due to invalid IL or missing references) //IL_00ef: Unknown result type (might be due to invalid IL or missing references) //IL_00f8: Unknown result type (might be due to invalid IL or missing references) //IL_00fe: Unknown result type (might be due to invalid IL or missing references) //IL_0104: Unknown result type (might be due to invalid IL or missing references) //IL_0109: Unknown result type (might be due to invalid IL or missing references) //IL_0110: Unknown result type (might be due to invalid IL or missing references) //IL_0116: Unknown result type (might be due to invalid IL or missing references) //IL_011c: Unknown result type (might be due to invalid IL or missing references) //IL_0125: Unknown result type (might be due to invalid IL or missing references) //IL_012a: Unknown result type (might be due to invalid IL or missing references) //IL_0131: Unknown result type (might be due to invalid IL or missing references) //IL_0137: Unknown result type (might be due to invalid IL or missing references) //IL_013d: Unknown result type (might be due to invalid IL or missing references) //IL_0146: Unknown result type (might be due to invalid IL or missing references) //IL_014b: Unknown result type (might be due to invalid IL or missing references) //IL_0160: Unknown result type (might be due to invalid IL or missing references) //IL_0165: Unknown result type (might be due to invalid IL or missing references) //IL_016d: Unknown result type (might be due to invalid IL or missing references) //IL_0174: Unknown result type (might be due to invalid IL or missing references) //IL_0181: Unknown result type (might be due to invalid IL or missing references) //IL_0186: Unknown result type (might be due to invalid IL or missing references) //IL_018e: Unknown result type (might be due to invalid IL or missing references) //IL_0247: Unknown result type (might be due to invalid IL or missing references) //IL_0252: Unknown result type (might be due to invalid IL or missing references) //IL_0258: Unknown result type (might be due to invalid IL or missing references) //IL_025d: Unknown result type (might be due to invalid IL or missing references) //IL_0269: Unknown result type (might be due to invalid IL or missing references) //IL_0270: Unknown result type (might be due to invalid IL or missing references) foreach (ZoneEntry zone in zoneList) { if (zone.IsActive) { float num = Vector3.Distance(new Vector3(pos.x, 0f, pos.z), new Vector3(zone.x, 0f, zone.z)); if (num <= zone.radius * 1.5f) { TryPreload(zone.url); } } } if (biomesEnabled && WorldGenerator.instance != null) { float num2 = 64f; Vector3[] array = (Vector3[])(object)new Vector3[5] { pos, new Vector3(pos.x + num2, pos.y, pos.z), new Vector3(pos.x - num2, pos.y, pos.z), new Vector3(pos.x, pos.y, pos.z + num2), new Vector3(pos.x, pos.y, pos.z - num2) }; Vector3[] array2 = array; foreach (Vector3 val in array2) { Biome biome = WorldGenerator.instance.GetBiome(val.x, val.z, 0.02f, false); if (biomeMap.TryGetValue(biome, out var value) && value.IsActive) { TryPreload(value.url); } } } if (terrEnabled) { foreach (TerritoryEntry terr in terrList) { if (terr.IsActive && _locPosCache.TryGetValue(terr.location, out var value2)) { float num3 = ((terr.radius > 0f) ? terr.radius : terrRadius); float num4 = Vector3.Distance(new Vector3(pos.x, 0f, pos.z), new Vector3(value2.x, 0f, value2.z)); if (num4 <= num3 * 1.5f) { TryPreload(terr.url); } } } } if ((!bossEnabled && !creatEnabled) || _charBuffer.Count <= 0) { return; } foreach (Character item in _charBuffer) { if (!((Object)(object)item == (Object)null)) { string key = ((Object)item).name.Replace("(Clone)", "").Trim(); if (bossEnabled && bossMap.TryGetValue(key, out var value3) && value3.IsActive) { TryPreload(value3.url); } if (creatEnabled && creatMap.TryGetValue(key, out var value4) && value4.IsActive) { TryPreload(value4.url); } } } } private string GetTerritoryMusic(Vector3 origin) { //IL_0080: Unknown result type (might be due to invalid IL or missing references) //IL_008a: Unknown result type (might be due to invalid IL or missing references) //IL_00ea: Unknown result type (might be due to invalid IL or missing references) //IL_0100: Unknown result type (might be due to invalid IL or missing references) //IL_0102: Unknown result type (might be due to invalid IL or missing references) //IL_0107: Unknown result type (might be due to invalid IL or missing references) //IL_0115: Unknown result type (might be due to invalid IL or missing references) //IL_0149: Unknown result type (might be due to invalid IL or missing references) //IL_014f: Unknown result type (might be due to invalid IL or missing references) //IL_0166: Unknown result type (might be due to invalid IL or missing references) //IL_016c: Unknown result type (might be due to invalid IL or missing references) //IL_013f: Unknown result type (might be due to invalid IL or missing references) //IL_0140: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)ZoneSystem.instance == (Object)null) { return null; } LocationInstance val = default(LocationInstance); foreach (TerritoryEntry terr in terrList) { if (!terr.IsActive) { continue; } float num = ((terr.dungeonYMin >= 0f) ? terr.dungeonYMin : terrDungeonYMin); float num2 = ((terr.dungeonYMax >= 0f) ? terr.dungeonYMax : terrDungeonYMax); bool flag = origin.y >= num && origin.y <= num2; if (terr.dungeonOnly) { if (!flag) { continue; } return terr.url; } if (!_locPosCache.TryGetValue(terr.location, out var value)) { if (!ZoneSystem.instance.FindClosestLocation(terr.location, origin, ref val)) { continue; } value = val.m_position; _locPosCache[terr.location] = value; } float num3 = ((terr.radius > 0f) ? terr.radius : terrRadius); float num4 = (flag ? ((float)Math.Sqrt(Math.Pow(origin.x - value.x, 2.0) + Math.Pow(origin.z - value.z, 2.0))) : Vector3.Distance(origin, value)); if (!(num4 <= num3)) { continue; } return terr.url; } return null; } private bool GetZoneMatch(Vector3 origin, out string url, out float volume) { //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_004f: Unknown result type (might be due to invalid IL or missing references) foreach (ZoneEntry zone in zoneList) { if (zone.IsActive) { float num = Vector3.Distance(new Vector3(origin.x, 0f, origin.z), new Vector3(zone.x, 0f, zone.z)); if (num <= zone.radius) { url = zone.url; volume = zone.volume; return true; } } } url = null; volume = 0f; return false; } private void TryPreload(string url) { if (!string.IsNullOrWhiteSpace(url) && !clipCache.ContainsKey(url) && !preloadingUrls.Contains(url)) { ((MonoBehaviour)this).StartCoroutine(PreloadClip(url)); } } [IteratorStateMachine(typeof(d__64))] private IEnumerator PreloadClip(string url) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new d__64(0) { <>4__this = this, url = url }; } private void SwitchMusic(string url, float cfgVolume, MusicState state) { if (!(currentUrl == url)) { ((BaseUnityPlugin)this).Logger.LogInfo((object)$"[Glitnir] [{state}] → {url}"); currentState = state; currentUrl = url; MuteVanilla(); if (fadeCoroutine != null) { ((MonoBehaviour)this).StopCoroutine(fadeCoroutine); } if (clipCache.TryGetValue(url, out var value) && (Object)(object)value != (Object)null) { fadeCoroutine = ((MonoBehaviour)this).StartCoroutine(FadeSwitchCached(value, url, cfgVolume)); } else { fadeCoroutine = ((MonoBehaviour)this).StartCoroutine(FadeSwitch(url, cfgVolume)); } } } [IteratorStateMachine(typeof(d__66))] private IEnumerator FadeSwitchCached(AudioClip nextClip, string url, float cfgVolume) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new d__66(0) { <>4__this = this, nextClip = nextClip, url = url, cfgVolume = cfgVolume }; } [IteratorStateMachine(typeof(d__67))] private IEnumerator FadeSwitch(string url, float cfgVolume) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new d__67(0) { <>4__this = this, url = url, cfgVolume = cfgVolume }; } [IteratorStateMachine(typeof(d__68))] private IEnumerator FadeOutAndStop(bool andUnmute = false) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new d__68(0) { <>4__this = this, andUnmute = andUnmute }; } [IteratorStateMachine(typeof(d__69))] private IEnumerator LoadAndFadeIn(string url, float cfgVolume) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new d__69(0) { <>4__this = this, url = url, cfgVolume = cfgVolume }; } private void PlayCachedClip(AudioClip clip, float finalVolume, MusicState state, string url) { if (!(currentUrl == url)) { currentState = state; currentUrl = url; currentClipUrl = url; MuteVanilla(); audioSource.Stop(); audioSource.clip = clip; audioSource.volume = finalVolume; audioSource.Play(); } } [IteratorStateMachine(typeof(d__71))] private IEnumerator PreloadMenuMusic() { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new d__71(0) { <>4__this = this }; } private void StopOurMusic() { if (fadeCoroutine != null) { ((MonoBehaviour)this).StopCoroutine(fadeCoroutine); } audioSource.Stop(); ReleaseCurrentClip(); currentState = MusicState.None; currentUrl = ""; } private void ReleaseCurrentClip() { if (!string.IsNullOrEmpty(currentClipUrl)) { if (!clipCache.ContainsKey(currentClipUrl) && (Object)(object)audioSource.clip != (Object)null) { Object.Destroy((Object)(object)audioSource.clip); } audioSource.clip = null; currentClipUrl = ""; } } private void ClearCache() { foreach (AudioClip value in clipCache.Values) { if ((Object)(object)value != (Object)null) { Object.Destroy((Object)(object)value); } } clipCache.Clear(); preloadingUrls.Clear(); ((BaseUnityPlugin)this).Logger.LogInfo((object)"[Glitnir] Cache de clips liberado."); } private void CreateMusicPlayer() { //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_0041: Expected O, but got Unknown if (!((Object)(object)musicObject != (Object)null) || !((Object)(object)audioSource != (Object)null)) { if ((Object)(object)musicObject == (Object)null) { musicObject = new GameObject("Glitnir Music Player"); Object.DontDestroyOnLoad((Object)(object)musicObject); } audioSource = musicObject.GetComponent() ?? musicObject.AddComponent(); audioSource.loop = true; audioSource.spatialBlend = 0f; audioSource.volume = 1f; } } private void StartConfigWatcher() { try { string directoryName = Path.GetDirectoryName(ConfigPath); string fileName = Path.GetFileName(ConfigPath); if (Directory.Exists(directoryName)) { configWatcher = new FileSystemWatcher(directoryName, fileName) { NotifyFilter = NotifyFilters.LastWrite, EnableRaisingEvents = true }; configWatcher.Changed += delegate { reloadPending = true; }; ((BaseUnityPlugin)this).Logger.LogInfo((object)"[Glitnir] Watcher de config ativo."); } } catch (Exception ex) { ((BaseUnityPlugin)this).Logger.LogWarning((object)("[Glitnir] Watcher não iniciado: " + ex.Message)); } } private void LoadConfig() { //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Expected O, but got Unknown //IL_00fc: Unknown result type (might be due to invalid IL or missing references) if (!File.Exists(ConfigPath)) { ((BaseUnityPlugin)this).Logger.LogWarning((object)("[Glitnir] Config não encontrada: " + ConfigPath)); return; } try { string text = File.ReadAllText(ConfigPath); IDeserializer val = ((BuilderSkeleton)new DeserializerBuilder()).WithNamingConvention(UnderscoredNamingConvention.Instance).IgnoreUnmatchedProperties().Build(); YamlConfig yamlConfig = val.Deserialize(text); if (yamlConfig == null) { throw new Exception("YAML resultou em objeto nulo."); } bool enabled = yamlConfig.menu.enabled; float volume = yamlConfig.menu.volume; MusicEntry musicEntry = new MusicEntry(enabled: true, yamlConfig.menu.url); bool enabled2 = yamlConfig.biomes.enabled; float volume2 = yamlConfig.biomes.volume; Dictionary dictionary = new Dictionary(); foreach (KeyValuePair track in yamlConfig.biomes.tracks) { if (Enum.TryParse(track.Key, out Biome result)) { dictionary[result] = new MusicEntry(track.Value.enabled, track.Value.url); } } bool enabled3 = yamlConfig.territories.enabled; float volume3 = yamlConfig.territories.volume; float radius = yamlConfig.territories.radius; float dungeon_y_min = yamlConfig.territories.dungeon_y_min; float dungeon_y_max = yamlConfig.territories.dungeon_y_max; List list = new List(); foreach (YamlTerritoryTrack track2 in yamlConfig.territories.tracks) { list.Add(new TerritoryEntry { location = track2.location, radius = track2.radius, dungeonYMin = track2.dungeon_y_min, dungeonYMax = track2.dungeon_y_max, dungeonOnly = track2.dungeon_only, enabled = track2.enabled, url = track2.url }); } bool enabled4 = yamlConfig.zones.enabled; List list2 = new List(); foreach (YamlZoneTrack track3 in yamlConfig.zones.tracks) { list2.Add(new ZoneEntry { name = track3.name, x = track3.x, z = track3.z, radius = track3.radius, volume = track3.volume, enabled = track3.enabled, url = track3.url }); } bool enabled5 = yamlConfig.bosses.enabled; float volume4 = yamlConfig.bosses.volume; float radius2 = yamlConfig.bosses.radius; Dictionary dictionary2 = new Dictionary(); foreach (KeyValuePair track4 in yamlConfig.bosses.tracks) { dictionary2[track4.Key] = new MusicEntry(track4.Value.enabled, track4.Value.url); } bool enabled6 = yamlConfig.creatures.enabled; float volume5 = yamlConfig.creatures.volume; float radius3 = yamlConfig.creatures.radius; Dictionary dictionary3 = new Dictionary(); foreach (KeyValuePair track5 in yamlConfig.creatures.tracks) { dictionary3[track5.Key] = new MusicEntry(track5.Value.enabled, track5.Value.url); } ClearCache(); _locPosCache.Clear(); menuEnabled = enabled; menuVolume = volume; menuEntry = musicEntry; biomesEnabled = enabled2; biomeVolume = volume2; biomeMap = dictionary; terrEnabled = enabled3; terrVolume = volume3; terrRadius = radius; terrDungeonYMin = dungeon_y_min; terrDungeonYMax = dungeon_y_max; terrList = list; zonesEnabled = enabled4; zoneList = list2; bossEnabled = enabled5; bossVolume = volume4; bossRadius = radius2; bossMap = dictionary2; creatEnabled = enabled6; creatVolume = volume5; creatRadius = radius3; creatMap = dictionary3; ((BaseUnityPlugin)this).Logger.LogInfo((object)("[Glitnir] Config carregada: " + $"{biomeMap.Count} biomas, {terrList.Count} territórios, " + $"{zoneList.Count} zonas, {bossMap.Count} bosses, {creatMap.Count} criaturas.")); } catch (Exception ex) { ((BaseUnityPlugin)this).Logger.LogError((object)("[Glitnir] Erro ao ler config: " + ex.Message)); ((BaseUnityPlugin)this).Logger.LogError((object)("[Glitnir] Verifique o arquivo: " + ConfigPath)); } } private void EnsureDefaultConfig() { if (!File.Exists(ConfigPath)) { Directory.CreateDirectory(Path.GetDirectoryName(ConfigPath)); File.WriteAllText(ConfigPath, "# ╔══════════════════════════════════════════════════════════════════╗\r\n# ║ GLITNIR MUSIC ZONES — music_config.yaml ║\r\n# ╚══════════════════════════════════════════════════════════════════╝\r\n# Use URLs diretas de MP3 (sem expiração). Recomendado: GitHub Releases\r\n# ou cdn.pixabay.com. Evite links do Discord (expiram em horas).\r\n#\r\n# Após salvar o arquivo, a config recarrega automaticamente no jogo.\r\n\r\n# ─── MENU PRINCIPAL ────────────────────────────────────────────────\r\nmenu:\r\n enabled: true\r\n volume: 0.3\r\n url: \"https://cdn.pixabay.com/download/audio/2025/07/24/audio_9d4a9c72f8.mp3?filename=wesleysert-glitnir-valhhala-1-379314.mp3\"\r\n\r\n# ─── BIOMAS ────────────────────────────────────────────────────────\r\n# Biomas disponíveis: Meadows, BlackForest, Swamp, Mountain, Plains,\r\n# Mistlands, AshLands, DeepNorth, Ocean\r\nbiomes:\r\n enabled: true\r\n volume: 0.6\r\n tracks:\r\n Meadows:\r\n enabled: true\r\n url: \"\"\r\n BlackForest:\r\n enabled: true\r\n url: \"\"\r\n Swamp:\r\n enabled: true\r\n url: \"\"\r\n Mountain:\r\n enabled: true\r\n url: \"\"\r\n Plains:\r\n enabled: true\r\n url: \"\"\r\n Mistlands:\r\n enabled: true\r\n url: \"\"\r\n AshLands:\r\n enabled: true\r\n url: \"\"\r\n DeepNorth:\r\n enabled: true\r\n url: \"\"\r\n Ocean:\r\n enabled: true\r\n url: \"\"\r\n\r\n# ─── TERRITÓRIOS (Locations do ZoneSystem) ─────────────────────────\r\n# location: nome exato da Location (ex: StartTemple, Crypt2)\r\n# radius: raio em unidades (0 = usa o radius global abaixo)\r\n# dungeon_only: true = só toca dentro da dungeon (faixa Y)\r\n# dungeon_y_min/max: faixa Y da dungeon (-1 = usa o global)\r\nterritories:\r\n enabled: true\r\n volume: 0.65\r\n radius: 90.0\r\n dungeon_y_min: 4500.0\r\n dungeon_y_max: 5500.0\r\n tracks:\r\n - enabled: true\r\n location: StartTemple\r\n radius: 60.0\r\n dungeon_only: false\r\n dungeon_y_min: -1\r\n dungeon_y_max: -1\r\n url: \"\"\r\n\r\n - enabled: false\r\n location: Vendor_BlackForest\r\n radius: 0.0\r\n dungeon_only: false\r\n dungeon_y_min: -1\r\n dungeon_y_max: -1\r\n url: \"\"\r\n\r\n - enabled: true\r\n location: Crypt2\r\n radius: 90.0\r\n dungeon_only: true\r\n dungeon_y_min: 4500\r\n dungeon_y_max: 5500\r\n url: \"\"\r\n\r\n - enabled: true\r\n location: Crypt3\r\n radius: 90.0\r\n dungeon_only: true\r\n dungeon_y_min: 4500\r\n dungeon_y_max: 5500\r\n url: \"\"\r\n\r\n - enabled: true\r\n location: Crypt4\r\n radius: 90.0\r\n dungeon_only: true\r\n dungeon_y_min: 4500\r\n dungeon_y_max: 5500\r\n url: \"\"\r\n\r\n# ─── ZONAS POR COORDENADA ──────────────────────────────────────────\r\n# Use para vilas ou regiões sem Location no ZoneSystem.\r\n# x/z: coordenadas do centro no mapa do Valheim\r\nzones:\r\n enabled: true\r\n tracks:\r\n - enabled: false\r\n name: Exemplo Vila\r\n x: 0.0\r\n z: 0.0\r\n radius: 80.0\r\n volume: 0.65\r\n url: \"\"\r\n\r\n# ─── BOSSES ────────────────────────────────────────────────────────\r\n# Prefab name do boss sem '(Clone)'. Toca enquanto o boss estiver vivo no raio.\r\n# Bosses vanilla: Eikthyr, gd_king, Bonemass, Dragon, GoblinKing, SeekerQueen, Fader\r\nbosses:\r\n enabled: true\r\n volume: 0.7\r\n radius: 120.0\r\n tracks:\r\n Eikthyr:\r\n enabled: true\r\n url: \"\"\r\n gd_king:\r\n enabled: true\r\n url: \"\"\r\n Bonemass:\r\n enabled: true\r\n url: \"\"\r\n Dragon:\r\n enabled: true\r\n url: \"\"\r\n GoblinKing:\r\n enabled: true\r\n url: \"\"\r\n SeekerQueen:\r\n enabled: true\r\n url: \"\"\r\n Fader:\r\n enabled: true\r\n url: \"\"\r\n\r\n# ─── CRIATURAS ─────────────────────────────────────────────────────\r\n# Toca enquanto houver ao menos uma criatura viva no raio.\r\ncreatures:\r\n enabled: true\r\n volume: 0.55\r\n radius: 30.0\r\n tracks:\r\n Troll:\r\n enabled: false\r\n url: \"\"\r\n GoblinBrute:\r\n enabled: false\r\n url: \"\"\r\n BlobTar:\r\n enabled: false\r\n url: \"\"\r\n Seeker:\r\n enabled: false\r\n url: \"\"\r\n Leech:\r\n enabled: false\r\n url: \"\"\r\n"); ((BaseUnityPlugin)this).Logger.LogInfo((object)("[Glitnir] Config padrão criada em: " + ConfigPath)); } } } }