Decompiled source of AmbienceSoundConfig v2.7.8

AmbienceSoundConfig.dll

Decompiled 2 weeks ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using System.Text;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.ConfigurationManager;
using HarmonyLib;
using TMPro;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.UI;
using Valheim.SettingsGui;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyTitle("AmbienceSoundConfig")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("Valheim_Ambience_Mute")]
[assembly: AssemblyCopyright("Copyright ©  2025")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("f01ac134-75c0-45a2-be66-fe63019a4264")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[assembly: AssemblyVersion("1.0.0.0")]
namespace BepInEx.ConfigurationManager
{
	public sealed class ConfigurationManagerAttributes
	{
		public Action<ConfigEntryBase> CustomDrawer;

		public bool? HideDefaultButton;
	}
}
namespace AmbienceSoundConfig
{
	[BepInPlugin("com.draconicvelum.ambiencesoundconfig", "Ambience Sound Config", "2.7.8")]
	public class AmbienceSoundConfig : BaseUnityPlugin
	{
		private sealed class CustomSectionSnapshot
		{
			private readonly string _extraSfxSplit;

			private readonly string _extraClipsSplit;

			private CustomSectionSnapshot(string extraSfxSplit, string extraClipsSplit)
			{
				_extraSfxSplit = extraSfxSplit;
				_extraClipsSplit = extraClipsSplit;
			}

			internal static CustomSectionSnapshot Capture(string path)
			{
				if (string.IsNullOrEmpty(path) || !File.Exists(path))
				{
					return new CustomSectionSnapshot(null, null);
				}
				string text = File.ReadAllText(path);
				return new CustomSectionSnapshot(ReadRawSection(text, "Extra SFX Split"), ReadRawSection(text, "Extra Clips Split"));
			}

			internal void Restore(string path)
			{
				if (!string.IsNullOrEmpty(path) && File.Exists(path))
				{
					string text = File.ReadAllText(path);
					if (!string.IsNullOrWhiteSpace(_extraSfxSplit))
					{
						text = RemoveSection(text, "Extra SFX Split");
					}
					if (!string.IsNullOrWhiteSpace(_extraClipsSplit))
					{
						text = RemoveSection(text, "Extra Clips Split");
					}
					StringBuilder stringBuilder = new StringBuilder(text.TrimEnd(Array.Empty<char>()));
					if (!string.IsNullOrWhiteSpace(_extraSfxSplit))
					{
						stringBuilder.AppendLine();
						stringBuilder.AppendLine();
						stringBuilder.Append(_extraSfxSplit.TrimEnd(Array.Empty<char>()));
					}
					if (!string.IsNullOrWhiteSpace(_extraClipsSplit))
					{
						stringBuilder.AppendLine();
						stringBuilder.AppendLine();
						stringBuilder.Append(_extraClipsSplit.TrimEnd(Array.Empty<char>()));
					}
					File.WriteAllText(path, stringBuilder.ToString() + Environment.NewLine);
				}
			}
		}

		public const string PluginVersion = "2.7.8";

		public const string ExtraSfxSplitSection = "Extra SFX Split";

		public const string ExtraClipSplitSection = "Extra Clips Split";

		public static ConfigEntry<string> ConfigVersion;

		public static ConfigEntry<bool> ReloadConfigButton;

		public static ConfigEntry<float> VolumeSliderMax;

		public static ConfigEntry<float> MasterVolume;

		public static ConfigEntry<float> WindVolume;

		public static ConfigEntry<float> OceanVolume;

		public static ConfigEntry<float> AmbientLoopVolume;

		public static ConfigEntry<float> ShieldHumVolume;

		public static ConfigEntry<string> ExtraSfxList;

		public static ConfigEntry<float> ExtraSfxVolume;

		public static ConfigEntry<string> ExtraClipList;

		public static ConfigEntry<float> ExtraClipVolume;

		public static ConfigEntry<bool> EnableSoundLogging;

		public static ConfigEntry<bool> LogOnlyUnique;

		public static string PluginConfigFilePath;

		private static readonly Harmony harmony = new Harmony("com.draconicvelum.ambiencesoundconfig");

		private void Awake()
		{
			//IL_0092: Unknown result type (might be due to invalid IL or missing references)
			//IL_009c: Expected O, but got Unknown
			//IL_00cf: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d9: Expected O, but got Unknown
			//IL_010c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0116: Expected O, but got Unknown
			//IL_0149: Unknown result type (might be due to invalid IL or missing references)
			//IL_0153: Expected O, but got Unknown
			//IL_0186: Unknown result type (might be due to invalid IL or missing references)
			//IL_0190: Expected O, but got Unknown
			//IL_01c3: Unknown result type (might be due to invalid IL or missing references)
			//IL_01cd: Expected O, but got Unknown
			//IL_0200: Unknown result type (might be due to invalid IL or missing references)
			//IL_020a: Expected O, but got Unknown
			//IL_0261: Unknown result type (might be due to invalid IL or missing references)
			//IL_026b: Expected O, but got Unknown
			//IL_02c2: Unknown result type (might be due to invalid IL or missing references)
			//IL_02cc: Expected O, but got Unknown
			PluginConfigFilePath = ((BaseUnityPlugin)this).Config.ConfigFilePath;
			CustomSectionSnapshot startupCustomSections = CustomSectionSnapshot.Capture(PluginConfigFilePath);
			bool configNeedsUpdate = IsOlderConfigVersion(ReadConfigVersion(), "2.7.8");
			ConfigVersion = ((BaseUnityPlugin)this).Config.Bind<string>("General", "Config Version", "2.7.8", "Internal config version. The mod updates older config files to the latest format while keeping your values.");
			ReloadConfigButton = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "Reload Config", false, new ConfigDescription("Button for compatible config manager mods. Reloads this config file and reapplies split SFX/clip volumes.", (AcceptableValueBase)null, new object[1]
			{
				new ConfigurationManagerAttributes
				{
					CustomDrawer = DrawReloadConfigButton,
					HideDefaultButton = true
				}
			}));
			VolumeSliderMax = ((BaseUnityPlugin)this).Config.Bind<float>("General", "Volume Slider Max", 1f, new ConfigDescription("Config-only maximum value used by this mod's volume sliders and volume config entries. Default is 1.0; valid range is 0.0 to 5.0.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 5f), Array.Empty<object>()));
			MasterVolume = ((BaseUnityPlugin)this).Config.Bind<float>("Ambience", "Master Volume", 0.25f, new ConfigDescription("Controls overall ambience loudness multiplier.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 5f), Array.Empty<object>()));
			WindVolume = ((BaseUnityPlugin)this).Config.Bind<float>("Ambience", "Wind Volume", 1f, new ConfigDescription("Volume for wind ambience (multiplied by Master Volume).", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 5f), Array.Empty<object>()));
			OceanVolume = ((BaseUnityPlugin)this).Config.Bind<float>("Ambience", "Ocean Volume", 1f, new ConfigDescription("Volume for ocean ambience (multiplied by Master Volume).", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 5f), Array.Empty<object>()));
			AmbientLoopVolume = ((BaseUnityPlugin)this).Config.Bind<float>("Ambience", "Ambient Loop Volume", 1f, new ConfigDescription("Volume for background ambient loop (multiplied by Master Volume).", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 5f), Array.Empty<object>()));
			ShieldHumVolume = ((BaseUnityPlugin)this).Config.Bind<float>("Ambience", "Shield Hum Volume", 1f, new ConfigDescription("Volume for shield dome hum (multiplied by Master Volume).", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 5f), Array.Empty<object>()));
			ExtraSfxList = ((BaseUnityPlugin)this).Config.Bind<string>("Extra SFX", "Extra SFX Prefabs", "", "Legacy comma separated list of ZSFX prefab names affected by Extra SFX Volume. For per-sound volumes, add entries under [Extra SFX Split].");
			ExtraSfxVolume = ((BaseUnityPlugin)this).Config.Bind<float>("Extra SFX", "Extra SFX Volume", 1f, new ConfigDescription("Legacy shared volume multiplier for sound effects listed in Extra SFX Prefabs.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 5f), Array.Empty<object>()));
			ExtraClipList = ((BaseUnityPlugin)this).Config.Bind<string>("Extra Clips", "Extra Clip Names", "", "Legacy comma separated list of AudioClip names affected by Extra Clip Volume. For per-clip volumes, add entries under [Extra Clips Split].");
			ExtraClipVolume = ((BaseUnityPlugin)this).Config.Bind<float>("Extra Clips", "Extra Clip Volume", 1f, new ConfigDescription("Legacy shared volume multiplier for clip names listed in Extra Clip Names.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 5f), Array.Empty<object>()));
			EnableSoundLogging = ((BaseUnityPlugin)this).Config.Bind<bool>("Logging", "Enable Sound Logging", false, "Logs all played SFX and AudioClips to console and a file next to this config.");
			LogOnlyUnique = ((BaseUnityPlugin)this).Config.Bind<bool>("Logging", "Log Only Unique", true, "If enabled, each sound name is logged only once per session.");
			VolumeSliderMax.SettingChanged += delegate
			{
				ClampAllVolumeConfigs();
				AudioSourceFilter.Refresh();
				AudioSourceFilter.ApplyToRunningSources();
				ApplyAllVolumes();
				SettingsInject.SyncUI();
				SaveConfigPreservingCustomSections(((BaseUnityPlugin)this).Config);
			};
			MasterVolume.SettingChanged += delegate
			{
				ClampVolumeConfig(MasterVolume);
			};
			WindVolume.SettingChanged += delegate
			{
				ClampVolumeConfig(WindVolume);
			};
			OceanVolume.SettingChanged += delegate
			{
				ClampVolumeConfig(OceanVolume);
			};
			AmbientLoopVolume.SettingChanged += delegate
			{
				ClampVolumeConfig(AmbientLoopVolume);
			};
			ShieldHumVolume.SettingChanged += delegate
			{
				ClampVolumeConfig(ShieldHumVolume);
			};
			ExtraSfxList.SettingChanged += delegate
			{
				AudioSourceFilter.Refresh();
			};
			ExtraSfxVolume.SettingChanged += delegate
			{
				ClampVolumeConfig(ExtraSfxVolume);
				AudioSourceFilter.Refresh();
				AudioSource[] array = Object.FindObjectsOfType<AudioSource>();
				for (int i = 0; i < array.Length; i++)
				{
					AudioSourceFilter.Apply(array[i]);
				}
			};
			ExtraClipList.SettingChanged += delegate
			{
				AudioSourceFilter.Refresh();
				AudioSourceFilter.ApplyToRunningSources();
			};
			ExtraClipVolume.SettingChanged += delegate
			{
				ClampVolumeConfig(ExtraClipVolume);
				AudioSourceFilter.Refresh();
				AudioSourceFilter.ApplyToRunningSources();
			};
			ClampAllVolumeConfigs();
			UpdateConfigFileIfNeeded(configNeedsUpdate, startupCustomSections);
			EnsureCustomVolumeSections();
			AudioSourceFilter.Refresh();
			SoundPlayLogger.Init(((BaseUnityPlugin)this).Config);
			harmony.PatchAll(typeof(AudioSource_DoAll_Patch));
			harmony.PatchAll(typeof(AudioSource_PlayOneShotScale_Patch));
			harmony.PatchAll(typeof(ZSFX_VolumeScale_Patch));
			harmony.PatchAll(typeof(AudioMan_AmbienceVolume_Patch));
			harmony.PatchAll(typeof(SettingsInject));
			((BaseUnityPlugin)this).Config.ConfigReloaded += OnReloaded;
			((BaseUnityPlugin)this).Logger.LogInfo((object)"Ambience Sound Config (v2.7.8) loaded.");
		}

		private void OnReloaded(object sender, EventArgs e)
		{
			ClampAllVolumeConfigs();
			EnsureCustomVolumeSections();
			AudioSourceFilter.Refresh();
			AudioSourceFilter.ApplyToRunningSources();
			ApplyAllVolumes();
			SettingsInject.SyncUI();
		}

		public static void ReloadConfigFromManager()
		{
			try
			{
				ReloadConfigPreservingCustomSections(((ConfigEntryBase)ConfigVersion).ConfigFile);
				AudioSourceFilter.Refresh();
				AudioSourceFilter.ApplyToRunningSources();
				ApplyAllVolumes();
				SettingsInject.SyncUI();
				Debug.Log((object)"[AmbienceSoundConfig] Config reloaded from config manager button.");
			}
			catch (Exception ex)
			{
				Debug.LogWarning((object)("[AmbienceSoundConfig] Config manager reload failed: " + ex.Message));
			}
		}

		private static void DrawReloadConfigButton(ConfigEntryBase entry)
		{
			if (GUILayout.Button("Reload Config", Array.Empty<GUILayoutOption>()))
			{
				ReloadConfigFromManager();
			}
		}

		public static void ApplyAllVolumes()
		{
			AudioMan_AmbienceVolume_Patch.ApplyWindVolumeWrapper();
			AudioMan_AmbienceVolume_Patch.ApplyOceanVolumeWrapper();
			AudioMan_AmbienceVolume_Patch.ApplyAmbientLoopVolumeWrapper();
			AudioMan_AmbienceVolume_Patch.ApplyShieldHumVolumeWrapper();
		}

		public static float GetVolumeSliderMax()
		{
			return Mathf.Clamp(VolumeSliderMax.Value, 0f, 5f);
		}

		public static float ClampConfiguredVolume(float value)
		{
			return Mathf.Clamp(value, 0f, GetVolumeSliderMax());
		}

		private static void ClampVolumeConfig(ConfigEntry<float> entry)
		{
			float num = ClampConfiguredVolume(entry.Value);
			if (!Mathf.Approximately(entry.Value, num))
			{
				entry.Value = num;
			}
		}

		private static void ClampAllVolumeConfigs()
		{
			ClampVolumeConfig(MasterVolume);
			ClampVolumeConfig(WindVolume);
			ClampVolumeConfig(OceanVolume);
			ClampVolumeConfig(AmbientLoopVolume);
			ClampVolumeConfig(ShieldHumVolume);
			ClampVolumeConfig(ExtraSfxVolume);
			ClampVolumeConfig(ExtraClipVolume);
		}

		private static string ReadConfigVersion()
		{
			if (string.IsNullOrEmpty(PluginConfigFilePath) || !File.Exists(PluginConfigFilePath))
			{
				return null;
			}
			try
			{
				string[] array = File.ReadAllLines(PluginConfigFilePath);
				for (int i = 0; i < array.Length; i++)
				{
					string text = array[i].Trim();
					if (text.StartsWith("Config Version =", StringComparison.OrdinalIgnoreCase))
					{
						int num = text.IndexOf('=');
						if (num >= 0)
						{
							return text.Substring(num + 1).Trim();
						}
					}
				}
			}
			catch (Exception ex)
			{
				Debug.LogWarning((object)("[AmbienceSoundConfig] Could not read config version: " + ex.Message));
			}
			return null;
		}

		private static bool IsOlderConfigVersion(string currentVersion, string targetVersion)
		{
			if (string.IsNullOrEmpty(currentVersion))
			{
				return File.Exists(PluginConfigFilePath);
			}
			if (!Version.TryParse(currentVersion, out Version result))
			{
				return true;
			}
			if (!Version.TryParse(targetVersion, out Version result2))
			{
				return false;
			}
			return result < result2;
		}

		private void UpdateConfigFileIfNeeded(bool configNeedsUpdate, CustomSectionSnapshot startupCustomSections)
		{
			if (!configNeedsUpdate)
			{
				return;
			}
			try
			{
				ConfigVersion.Value = "2.7.8";
				SaveConfigPreservingCustomSections(((BaseUnityPlugin)this).Config, startupCustomSections);
				((BaseUnityPlugin)this).Logger.LogInfo((object)"Updated config file to v2.7.8 while keeping existing values.");
			}
			catch (Exception ex)
			{
				((BaseUnityPlugin)this).Logger.LogWarning((object)("Could not update config file: " + ex.Message));
			}
		}

		internal static void EnsureCustomVolumeSections()
		{
			if (string.IsNullOrEmpty(PluginConfigFilePath))
			{
				return;
			}
			try
			{
				if (File.Exists(PluginConfigFilePath))
				{
					string text = RemoveLegacyEntryLines(File.ReadAllText(PluginConfigFilePath));
					bool flag = text != File.ReadAllText(PluginConfigFilePath);
					StringBuilder stringBuilder = new StringBuilder(text.TrimEnd(Array.Empty<char>()));
					if (!HasSection(text, "Extra SFX Split"))
					{
						AppendExtraSfxSplitSection(stringBuilder);
						flag = true;
					}
					if (!HasSection(text, "Extra Clips Split"))
					{
						AppendExtraClipsSplitSection(stringBuilder);
						flag = true;
					}
					if (flag)
					{
						File.WriteAllText(PluginConfigFilePath, stringBuilder.ToString() + Environment.NewLine);
					}
				}
			}
			catch (Exception ex)
			{
				Debug.LogWarning((object)("[AmbienceSoundConfig] Could not seed custom volume config sections: " + ex.Message));
			}
		}

		internal static void SaveConfigPreservingCustomSections(ConfigFile config)
		{
			SaveConfigPreservingCustomSections(config, CustomSectionSnapshot.Capture(PluginConfigFilePath));
		}

		private static void SaveConfigPreservingCustomSections(ConfigFile config, CustomSectionSnapshot snapshot)
		{
			config.Save();
			snapshot.Restore(PluginConfigFilePath);
			EnsureCustomVolumeSections();
		}

		private static void ReloadConfigPreservingCustomSections(ConfigFile config)
		{
			CustomSectionSnapshot customSectionSnapshot = CustomSectionSnapshot.Capture(PluginConfigFilePath);
			config.Reload();
			customSectionSnapshot.Restore(PluginConfigFilePath);
			EnsureCustomVolumeSections();
		}

		private static void AppendExtraSfxSplitSection(StringBuilder builder)
		{
			builder.AppendLine();
			builder.AppendLine();
			builder.AppendLine("[Extra SFX Split]");
			builder.AppendLine("## Config-only per-sound SFX volumes. Add one ZSFX prefab per line.");
			builder.AppendLine("## Format: prefab_name = volume");
			builder.AppendLine("## Example: sfx_boar_idle = 0.25");
		}

		private static void AppendExtraClipsSplitSection(StringBuilder builder)
		{
			builder.AppendLine();
			builder.AppendLine();
			builder.AppendLine("[Extra Clips Split]");
			builder.AppendLine("## Config-only per-clip volumes. Add one AudioClip name per line.");
			builder.AppendLine("## Format: clip_name = volume");
			builder.AppendLine("## Example: MeadowAmbience = 0.25");
		}

		private static string RemoveLegacyEntryLines(string text)
		{
			StringBuilder stringBuilder = new StringBuilder();
			using (StringReader stringReader = new StringReader(text))
			{
				string text2;
				while ((text2 = stringReader.ReadLine()) != null)
				{
					string text3 = text2.TrimStart(Array.Empty<char>());
					if (!text3.StartsWith("Extra SFX Entries =", StringComparison.OrdinalIgnoreCase) && !text3.StartsWith("Extra Clip Entries =", StringComparison.OrdinalIgnoreCase))
					{
						stringBuilder.AppendLine(text2);
					}
				}
			}
			return stringBuilder.ToString().TrimEnd(Array.Empty<char>()) + Environment.NewLine;
		}

		private static string ReadRawSection(string text, string sectionName)
		{
			StringBuilder stringBuilder = new StringBuilder();
			bool flag = false;
			using (StringReader stringReader = new StringReader(text))
			{
				string text2;
				while ((text2 = stringReader.ReadLine()) != null)
				{
					string text3 = text2.Trim();
					if (text3.StartsWith("[") && text3.EndsWith("]"))
					{
						if (flag)
						{
							break;
						}
						flag = text3.Substring(1, text3.Length - 2).Trim().Equals(sectionName, StringComparison.OrdinalIgnoreCase);
					}
					if (flag)
					{
						stringBuilder.AppendLine(text2);
					}
				}
			}
			if (stringBuilder.Length <= 0)
			{
				return null;
			}
			return stringBuilder.ToString().TrimEnd(Array.Empty<char>()) + Environment.NewLine;
		}

		private static string RemoveSection(string text, string sectionName)
		{
			StringBuilder stringBuilder = new StringBuilder();
			bool flag = false;
			using (StringReader stringReader = new StringReader(text))
			{
				string text2;
				while ((text2 = stringReader.ReadLine()) != null)
				{
					string text3 = text2.Trim();
					if (text3.StartsWith("[") && text3.EndsWith("]"))
					{
						flag = text3.Substring(1, text3.Length - 2).Trim().Equals(sectionName, StringComparison.OrdinalIgnoreCase);
					}
					if (!flag)
					{
						stringBuilder.AppendLine(text2);
					}
				}
			}
			return stringBuilder.ToString();
		}

		private static bool HasSection(string text, string sectionName)
		{
			using (StringReader stringReader = new StringReader(text))
			{
				string text2;
				while ((text2 = stringReader.ReadLine()) != null)
				{
					text2 = text2.Trim();
					if (text2.StartsWith("[") && text2.EndsWith("]") && text2.Substring(1, text2.Length - 2).Trim().Equals(sectionName, StringComparison.OrdinalIgnoreCase))
					{
						return true;
					}
				}
			}
			return false;
		}
	}
	[HarmonyPatch(typeof(AudioMan))]
	public static class AudioMan_AmbienceVolume_Patch
	{
		private static readonly BindingFlags Flags = BindingFlags.Instance | BindingFlags.NonPublic;

		private static readonly Dictionary<string, FieldInfo> CachedFields = new Dictionary<string, FieldInfo>();

		private static AudioSource GetPrivateSource(string fieldName)
		{
			if ((Object)(object)AudioMan.instance == (Object)null)
			{
				return null;
			}
			if (!CachedFields.TryGetValue(fieldName, out var value))
			{
				value = typeof(AudioMan).GetField(fieldName, Flags);
				if (value != null)
				{
					CachedFields[fieldName] = value;
				}
			}
			object? obj = value?.GetValue(AudioMan.instance);
			return (AudioSource)((obj is AudioSource) ? obj : null);
		}

		public static void ApplyWindVolumeWrapper()
		{
			AudioSource privateSource = GetPrivateSource("m_windLoopSource");
			if ((Object)(object)privateSource != (Object)null)
			{
				privateSource.volume = AmbienceSoundConfig.WindVolume.Value * AmbienceSoundConfig.MasterVolume.Value;
			}
		}

		public static void ApplyOceanVolumeWrapper()
		{
			AudioSource privateSource = GetPrivateSource("m_oceanAmbientSource");
			if ((Object)(object)privateSource != (Object)null)
			{
				privateSource.volume = AmbienceSoundConfig.OceanVolume.Value * AmbienceSoundConfig.MasterVolume.Value;
			}
		}

		public static void ApplyAmbientLoopVolumeWrapper()
		{
			AudioSource privateSource = GetPrivateSource("m_ambientLoopSource");
			if ((Object)(object)privateSource != (Object)null)
			{
				privateSource.volume = AmbienceSoundConfig.AmbientLoopVolume.Value * AmbienceSoundConfig.MasterVolume.Value;
			}
		}

		public static void ApplyShieldHumVolumeWrapper()
		{
			AudioSource privateSource = GetPrivateSource("m_shieldHumSource");
			if ((Object)(object)privateSource != (Object)null)
			{
				privateSource.volume = AmbienceSoundConfig.ShieldHumVolume.Value * AmbienceSoundConfig.MasterVolume.Value;
			}
		}

		[HarmonyPostfix]
		[HarmonyPatch("UpdateWindAmbience")]
		public static void ApplyWindVolume(ref AudioSource ___m_windLoopSource)
		{
			ApplyWindVolumeWrapper();
		}

		[HarmonyPostfix]
		[HarmonyPatch("UpdateOceanAmbiance")]
		public static void ApplyOceanVolume(ref AudioSource ___m_oceanAmbientSource)
		{
			ApplyOceanVolumeWrapper();
		}

		[HarmonyPostfix]
		[HarmonyPatch("UpdateAmbientLoop")]
		public static void ApplyAmbientLoopVolume(ref AudioSource ___m_ambientLoopSource)
		{
			ApplyAmbientLoopVolumeWrapper();
		}

		[HarmonyPostfix]
		[HarmonyPatch("UpdateShieldHum")]
		public static void ApplyShieldHumVolume(ref AudioSource ___m_shieldHumSource)
		{
			ApplyShieldHumVolumeWrapper();
		}
	}
	internal static class AudioSourceFilter
	{
		private static readonly Dictionary<string, float> _nameTargets = new Dictionary<string, float>(StringComparer.OrdinalIgnoreCase);

		private static readonly Dictionary<string, float> _clipTargets = new Dictionary<string, float>(StringComparer.OrdinalIgnoreCase);

		private static readonly Dictionary<AudioSource, float> _baseVolume = new Dictionary<AudioSource, float>();

		internal static bool HasClipTargets => _clipTargets.Count > 0;

		internal static void Refresh()
		{
			_nameTargets.Clear();
			_clipTargets.Clear();
			ParseSharedList(AmbienceSoundConfig.ExtraSfxList.Value, AmbienceSoundConfig.ExtraSfxVolume.Value, _nameTargets);
			ParseConfigVolumeSection("Extra SFX Split", _nameTargets);
			ParseSharedList(AmbienceSoundConfig.ExtraClipList.Value, AmbienceSoundConfig.ExtraClipVolume.Value, _clipTargets);
			ParseConfigVolumeSection("Extra Clips Split", _clipTargets);
		}

		internal static void Apply(AudioSource src)
		{
			if (!((Object)(object)src == (Object)null) && _nameTargets.Count != 0 && TryGetSfxMultiplier(((Object)((Component)src).gameObject).name, out var multiplier))
			{
				ApplyVolume(src, multiplier);
			}
		}

		internal static void Apply(AudioSource src, ref float volume)
		{
			if (!((Object)(object)src == (Object)null) && _nameTargets.Count != 0 && TryGetSfxMultiplier(((Object)((Component)src).gameObject).name, out var multiplier))
			{
				volume = Scale(volume, multiplier);
			}
		}

		internal static bool ShouldMuteClip(AudioClip clip)
		{
			float multiplier;
			return TryGetClipMultiplier(clip, out multiplier);
		}

		internal static bool TryGetClipMultiplier(AudioClip clip, out float multiplier)
		{
			multiplier = 1f;
			if ((Object)(object)clip != (Object)null)
			{
				return TryMatch(_clipTargets, ((Object)clip).name, out multiplier);
			}
			return false;
		}

		internal static void ApplyToRunningSources()
		{
			List<AudioSource> list = new List<AudioSource>();
			foreach (KeyValuePair<AudioSource, float> item in _baseVolume)
			{
				if ((Object)(object)item.Key == (Object)null)
				{
					list.Add(item.Key);
				}
			}
			foreach (AudioSource item2 in list)
			{
				_baseVolume.Remove(item2);
			}
			AudioSource[] array = Object.FindObjectsOfType<AudioSource>();
			foreach (AudioSource val in array)
			{
				if ((Object)(object)val == (Object)null || (Object)(object)val.clip == (Object)null)
				{
					continue;
				}
				float multiplier = 1f;
				if (!HasClipTargets || !TryGetClipMultiplier(val.clip, out multiplier))
				{
					if (_baseVolume.ContainsKey(val))
					{
						_baseVolume.Remove(val);
					}
					val.mute = false;
					continue;
				}
				if (!_baseVolume.ContainsKey(val))
				{
					_baseVolume[val] = val.volume;
				}
				float num = _baseVolume[val];
				if (multiplier <= 0f)
				{
					val.mute = true;
					continue;
				}
				val.mute = false;
				val.volume = Mathf.Clamp01(num * multiplier);
			}
		}

		private static bool TryGetSfxMultiplier(string goName, out float multiplier)
		{
			return TryMatch(_nameTargets, goName, out multiplier);
		}

		private static void ApplyVolume(AudioSource src, float mult)
		{
			if (mult <= 0f)
			{
				src.mute = true;
				return;
			}
			src.mute = false;
			src.volume = Mathf.Clamp01(src.volume * mult);
		}

		private static float Scale(float v, float mult)
		{
			if (mult <= 0f)
			{
				return 0f;
			}
			return v * mult;
		}

		private static bool TryMatch(Dictionary<string, float> targets, string sourceName, out float multiplier)
		{
			multiplier = 1f;
			if (targets.Count == 0)
			{
				return false;
			}
			string text = Normalize(sourceName);
			if (targets.TryGetValue(text, out multiplier))
			{
				return true;
			}
			foreach (KeyValuePair<string, float> target in targets)
			{
				if (text.StartsWith(target.Key, StringComparison.OrdinalIgnoreCase) || text.IndexOf(target.Key, StringComparison.OrdinalIgnoreCase) >= 0)
				{
					multiplier = target.Value;
					return true;
				}
			}
			return false;
		}

		private static void ParseSharedList(string raw, float sharedVolume, Dictionary<string, float> target)
		{
			if (string.IsNullOrEmpty(raw))
			{
				return;
			}
			string[] array = raw.Split(',', '\n', '\r');
			for (int i = 0; i < array.Length; i++)
			{
				string text = Normalize(array[i]);
				if (!string.IsNullOrEmpty(text))
				{
					target[text] = AmbienceSoundConfig.ClampConfiguredVolume(sharedVolume);
				}
			}
		}

		private static void ParseConfigVolumeSection(string sectionName, Dictionary<string, float> target)
		{
			string pluginConfigFilePath = AmbienceSoundConfig.PluginConfigFilePath;
			if (string.IsNullOrEmpty(pluginConfigFilePath) || !File.Exists(pluginConfigFilePath))
			{
				return;
			}
			bool flag = false;
			string[] array = File.ReadAllLines(pluginConfigFilePath);
			for (int i = 0; i < array.Length; i++)
			{
				string text = array[i].Trim();
				if (!string.IsNullOrEmpty(text) && !text.StartsWith("#"))
				{
					if (text.StartsWith("[") && text.EndsWith("]"))
					{
						flag = text.Substring(1, text.Length - 2).Trim().Equals(sectionName, StringComparison.OrdinalIgnoreCase);
					}
					else if (flag)
					{
						ParseVolumeLine(text, target);
					}
				}
			}
		}

		private static void ParseVolumeLine(string line, Dictionary<string, float> target)
		{
			string text = line.Trim();
			if (string.IsNullOrEmpty(text) || text.StartsWith("#"))
			{
				return;
			}
			string name = text;
			string text2 = null;
			int num = text.IndexOf('=');
			if (num < 0)
			{
				num = text.IndexOf(':');
			}
			if (num >= 0)
			{
				name = text.Substring(0, num);
				text2 = text.Substring(num + 1);
			}
			name = Normalize(name);
			if (!string.IsNullOrEmpty(name))
			{
				float value = 1f;
				if (!string.IsNullOrEmpty(text2) && float.TryParse(text2.Trim(), NumberStyles.Float, CultureInfo.InvariantCulture, out var result))
				{
					value = result;
				}
				target[name] = AmbienceSoundConfig.ClampConfiguredVolume(value);
			}
		}

		private static string Normalize(string name)
		{
			if (string.IsNullOrEmpty(name))
			{
				return string.Empty;
			}
			int num = name.IndexOf("(Clone)", StringComparison.OrdinalIgnoreCase);
			if (num >= 0)
			{
				name = name.Substring(0, num);
			}
			return name.Trim();
		}
	}
	[HarmonyPatch(typeof(AudioSource))]
	internal static class AudioSource_DoAll_Patch
	{
		[HarmonyPostfix]
		[HarmonyPatch("Play", new Type[] { })]
		private static void Postfix_Play(AudioSource __instance)
		{
			SoundPlayLogger.Log("SFX", ((Object)((Component)__instance).gameObject).name, ((Component)__instance).gameObject);
			AudioSourceFilter.Apply(__instance);
		}

		[HarmonyPostfix]
		[HarmonyPatch("Play", new Type[] { typeof(ulong) })]
		private static void Postfix_PlayDelayed(AudioSource __instance)
		{
			AudioSourceFilter.Apply(__instance);
		}

		[HarmonyPostfix]
		[HarmonyPatch("PlayOneShot", new Type[] { typeof(AudioClip) })]
		private static void Postfix_PlayOneShot(AudioSource __instance)
		{
			AudioSourceFilter.Apply(__instance);
		}

		[HarmonyPrefix]
		[HarmonyPatch("set_volume")]
		private static void Prefix_SetVolume(AudioSource __instance, ref float value)
		{
			AudioSourceFilter.Apply(__instance, ref value);
		}
	}
	[HarmonyPatch(typeof(AudioSource))]
	internal static class AudioSource_PlayOneShotScale_Patch
	{
		[HarmonyPrefix]
		[HarmonyPatch("PlayOneShot", new Type[]
		{
			typeof(AudioClip),
			typeof(float)
		})]
		private static void Prefix(AudioSource __instance, AudioClip clip, ref float volumeScale)
		{
			SoundPlayLogger.Log("CLIP", (clip != null) ? ((Object)clip).name : null, Object.op_Implicit((Object)(object)__instance) ? ((Component)__instance).gameObject : null);
			if (!((Object)(object)clip == (Object)null) && AudioSourceFilter.HasClipTargets && AudioSourceFilter.TryGetClipMultiplier(clip, out var multiplier))
			{
				volumeScale = ((multiplier <= 0f) ? 0f : (volumeScale * multiplier));
			}
		}

		[HarmonyPrefix]
		[HarmonyPatch("PlayOneShot", new Type[] { typeof(AudioClip) })]
		private static void Prefix_NoScale(AudioSource __instance, AudioClip clip)
		{
			SoundPlayLogger.Log("CLIP", (clip != null) ? ((Object)clip).name : null, Object.op_Implicit((Object)(object)__instance) ? ((Component)__instance).gameObject : null);
		}
	}
	[HarmonyPatch]
	public static class SettingsInject
	{
		private static Transform _gridContainer;

		private static bool _built;

		private const string ContainerName = "AmbienceGridContainer";

		internal static Slider _sMaster;

		internal static Slider _sWind;

		internal static Slider _sOcean;

		internal static Slider _sAmbientLoop;

		internal static Slider _sShieldHum;

		internal static Slider _sExtraSfx;

		internal static Slider _sExtraClip;

		internal static TextMeshProUGUI _vMaster;

		internal static TextMeshProUGUI _vWind;

		internal static TextMeshProUGUI _vOcean;

		internal static TextMeshProUGUI _vAmbientLoop;

		internal static TextMeshProUGUI _vShieldHum;

		internal static TextMeshProUGUI _vExtraSfx;

		internal static TextMeshProUGUI _vExtraClip;

		private static MethodBase TargetMethod()
		{
			Type type = typeof(AudioSettings);
			MethodBase methodBase = Find("Initialize") ?? Find("Awake") ?? Find("Start");
			if (methodBase != null)
			{
				Debug.Log((object)("[AmbienceSoundConfig] UI inject patching → " + methodBase.Name));
				return methodBase;
			}
			methodBase = Find("LoadSettings");
			if (methodBase != null)
			{
				Debug.Log((object)"[AmbienceSoundConfig] UI inject patching → LoadSettings (legacy fallback for Valheim 0.221.4)");
				return methodBase;
			}
			throw new Exception("[AmbienceSoundConfig] No compatible AudioSettings method found to patch.");
			MethodBase Find(string name)
			{
				return type.GetMethod(name, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
			}
		}

		[HarmonyPostfix]
		private static void Postfix_LoadSettings(AudioSettings __instance)
		{
			//IL_00e1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e6: Unknown result type (might be due to invalid IL or missing references)
			//IL_0118: 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_0136: 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_016b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0176: Unknown result type (might be due to invalid IL or missing references)
			//IL_018b: Unknown result type (might be due to invalid IL or missing references)
			//IL_019f: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b4: Unknown result type (might be due to invalid IL or missing references)
			//IL_01be: Expected O, but got Unknown
			//IL_01c9: Unknown result type (might be due to invalid IL or missing references)
			//IL_01de: Unknown result type (might be due to invalid IL or missing references)
			//IL_01fc: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				if (_built && (Object)(object)_gridContainer != (Object)null)
				{
					SyncUI();
					return;
				}
				Slider value = Traverse.Create((object)__instance).Field("m_musicVolumeSlider").GetValue<Slider>();
				GameObject val = ((value != null) ? ((Component)value).gameObject : null);
				if ((Object)(object)val == (Object)null)
				{
					Debug.LogWarning((object)"[AmbienceSoundConfig] Could not get m_musicVolumeSlider.");
					return;
				}
				Toggle value2 = Traverse.Create((object)__instance).Field("m_continousMusic").GetValue<Toggle>();
				Transform val2 = ((value2 != null) ? ((Component)value2).transform.parent : null) ?? val.transform.parent;
				Transform val3 = val2.Find("AmbienceGridContainer");
				if ((Object)(object)val3 != (Object)null)
				{
					Object.DestroyImmediate((Object)(object)((Component)val3).gameObject);
				}
				GameObject val4 = new GameObject("AmbienceGridContainer", new Type[3]
				{
					typeof(RectTransform),
					typeof(GridLayoutGroup),
					typeof(ContentSizeFitter)
				});
				val4.transform.SetParent(val2, false);
				int siblingIndex = (((Object)(object)value2 != (Object)null) ? ((Component)value2).transform.GetSiblingIndex() : val.transform.GetSiblingIndex()) + 1;
				val4.transform.SetSiblingIndex(siblingIndex);
				RectTransform component = val4.GetComponent<RectTransform>();
				component.anchorMin = new Vector2(0f, 1f);
				component.anchorMax = new Vector2(1f, 1f);
				component.pivot = new Vector2(0.5f, 1f);
				component.offsetMin = Vector2.zero;
				component.offsetMax = Vector2.zero;
				component.anchoredPosition = new Vector2(0f, 0f);
				component.sizeDelta = new Vector2(0f, 0f);
				GridLayoutGroup component2 = val4.GetComponent<GridLayoutGroup>();
				((LayoutGroup)component2).padding = new RectOffset(0, 0, 0, 0);
				component2.cellSize = new Vector2(300f, 20f);
				component2.spacing = new Vector2(0f, 8f);
				component2.constraint = (Constraint)1;
				component2.constraintCount = 1;
				((LayoutGroup)component2).childAlignment = (TextAnchor)0;
				ContentSizeFitter component3 = val4.GetComponent<ContentSizeFitter>();
				component3.verticalFit = (FitMode)2;
				component3.horizontalFit = (FitMode)0;
				_gridContainer = val4.transform;
				BindOrCreateSliders(_gridContainer, val);
				SyncUI();
				_built = true;
				LayoutRebuilder.ForceRebuildLayoutImmediate(((Component)val2).GetComponent<RectTransform>());
				Debug.Log((object)"[AmbienceSoundConfig] AmbienceGridContainer built and anchored to top (no drift).");
			}
			catch (Exception ex)
			{
				Debug.LogError((object)("[AmbienceSoundConfig] LoadSettings patch failed: " + ex));
			}
		}

		private static void BindOrCreateSliders(Transform container, GameObject baseSlider)
		{
			CreateOrBind(container, baseSlider, "Ambience Master Volume", ref _sMaster, ref _vMaster, AmbienceSoundConfig.MasterVolume, delegate
			{
				AmbienceSoundConfig.ApplyAllVolumes();
			});
			CreateOrBind(container, baseSlider, "Wind Volume", ref _sWind, ref _vWind, AmbienceSoundConfig.WindVolume, delegate
			{
				AudioMan_AmbienceVolume_Patch.ApplyWindVolumeWrapper();
			});
			CreateOrBind(container, baseSlider, "Ocean Volume", ref _sOcean, ref _vOcean, AmbienceSoundConfig.OceanVolume, delegate
			{
				AudioMan_AmbienceVolume_Patch.ApplyOceanVolumeWrapper();
			});
			CreateOrBind(container, baseSlider, "Ambient Loop Volume", ref _sAmbientLoop, ref _vAmbientLoop, AmbienceSoundConfig.AmbientLoopVolume, delegate
			{
				AudioMan_AmbienceVolume_Patch.ApplyAmbientLoopVolumeWrapper();
			});
			CreateOrBind(container, baseSlider, "Shield Hum Volume", ref _sShieldHum, ref _vShieldHum, AmbienceSoundConfig.ShieldHumVolume, delegate
			{
				AudioMan_AmbienceVolume_Patch.ApplyShieldHumVolumeWrapper();
			});
			CreateOrBind(container, baseSlider, "Extra SFX Volume", ref _sExtraSfx, ref _vExtraSfx, AmbienceSoundConfig.ExtraSfxVolume, delegate
			{
				AudioSourceFilter.Refresh();
				AudioSource[] array = Object.FindObjectsOfType<AudioSource>();
				for (int i = 0; i < array.Length; i++)
				{
					AudioSourceFilter.Apply(array[i]);
				}
			});
			CreateOrBind(container, baseSlider, "Extra Clip Volume", ref _sExtraClip, ref _vExtraClip, AmbienceSoundConfig.ExtraClipVolume, delegate
			{
				AudioSourceFilter.Refresh();
				AudioSourceFilter.ApplyToRunningSources();
			});
		}

		internal static void CreateOrBind(Transform parent, GameObject baseSlider, string labelText, ref Slider sliderRef, ref TextMeshProUGUI valueTextRef, ConfigEntry<float> config, Action<float> onChanged)
		{
			//IL_005a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0072: Unknown result type (might be due to invalid IL or missing references)
			//IL_007c: Unknown result type (might be due to invalid IL or missing references)
			string text = "Ambience_" + labelText.Replace(" ", "");
			Transform val2 = parent.Find(text);
			GameObject val3;
			TextMeshProUGUI[] componentsInChildren;
			if ((Object)(object)val2 == (Object)null)
			{
				val3 = Object.Instantiate<GameObject>(baseSlider, parent);
				((Object)val3).name = text;
				val3.transform.localScale = Vector3.one;
				val3.SetActive(true);
				RectTransform component = val3.GetComponent<RectTransform>();
				((Transform)component).localPosition = Vector3.zero;
				((Transform)component).localRotation = Quaternion.identity;
				componentsInChildren = val3.GetComponentsInChildren<TextMeshProUGUI>(true);
				foreach (TextMeshProUGUI val4 in componentsInChildren)
				{
					if (!((Object)(object)((TMP_Text)val4).font == (Object)null))
					{
						continue;
					}
					TextMeshProUGUI componentInChildren = baseSlider.GetComponentInChildren<TextMeshProUGUI>(true);
					if ((Object)(object)componentInChildren != (Object)null && (Object)(object)((TMP_Text)componentInChildren).font != (Object)null)
					{
						((TMP_Text)val4).font = ((TMP_Text)componentInChildren).font;
						((TMP_Text)val4).fontSharedMaterial = ((TMP_Text)componentInChildren).fontSharedMaterial;
						continue;
					}
					TMP_FontAsset[] array = Resources.FindObjectsOfTypeAll<TMP_FontAsset>();
					if (array.Length != 0)
					{
						((TMP_Text)val4).font = array[0];
					}
				}
			}
			else
			{
				val3 = ((Component)val2).gameObject;
			}
			Slider componentInChildren2 = val3.GetComponentInChildren<Slider>(true);
			if ((Object)(object)componentInChildren2 == (Object)null)
			{
				Debug.LogError((object)("[AmbienceSoundConfig] Slider missing for " + labelText));
				return;
			}
			TextMeshProUGUI val5 = null;
			TextMeshProUGUI valueText = null;
			componentsInChildren = val3.GetComponentsInChildren<TextMeshProUGUI>(true);
			foreach (TextMeshProUGUI val6 in componentsInChildren)
			{
				string text2 = ((Object)val6).name.ToLowerInvariant();
				if (text2.Contains("value"))
				{
					valueText = val6;
				}
				else if (text2.Contains("text") || text2.Contains("label"))
				{
					val5 = val6;
				}
			}
			if ((Object)(object)val5 != (Object)null)
			{
				((TMP_Text)val5).text = labelText;
				((TMP_Text)val5).enableAutoSizing = true;
				((TMP_Text)val5).fontSizeMin = 10f;
				((TMP_Text)val5).fontSizeMax = 14f;
				((Graphic)val5).raycastTarget = false;
			}
			if ((Object)(object)valueText != (Object)null)
			{
				((Graphic)valueText).raycastTarget = false;
				((TMP_Text)valueText).text = $"{Mathf.RoundToInt(config.Value * 100f)}%";
			}
			componentInChildren2.minValue = 0f;
			componentInChildren2.maxValue = AmbienceSoundConfig.GetVolumeSliderMax();
			((UnityEventBase)componentInChildren2.onValueChanged).RemoveAllListeners();
			((UnityEvent<float>)(object)componentInChildren2.onValueChanged).AddListener((UnityAction<float>)delegate(float val)
			{
				float num = AmbienceSoundConfig.ClampConfiguredVolume(val);
				config.Value = num;
				AmbienceSoundConfig.SaveConfigPreservingCustomSections(((ConfigEntryBase)config).ConfigFile);
				if ((Object)(object)valueText != (Object)null)
				{
					((TMP_Text)valueText).text = $"{Mathf.RoundToInt(num * 100f)}%";
				}
				onChanged?.Invoke(num);
			});
			sliderRef = componentInChildren2;
			valueTextRef = valueText;
			componentInChildren2.value = config.Value;
		}

		public static void SyncUI()
		{
			try
			{
				if ((Object)(object)_gridContainer == (Object)null || (Object)(object)((Component)_gridContainer).gameObject == (Object)null)
				{
					return;
				}
				if ((Object)(object)_sMaster != (Object)null)
				{
					_sMaster.maxValue = AmbienceSoundConfig.GetVolumeSliderMax();
					_sMaster.SetValueWithoutNotify(AmbienceSoundConfig.MasterVolume.Value);
					if ((Object)(object)_vMaster != (Object)null)
					{
						((TMP_Text)_vMaster).text = $"{Mathf.RoundToInt(_sMaster.value * 100f)}%";
					}
				}
				if ((Object)(object)_sWind != (Object)null)
				{
					_sWind.maxValue = AmbienceSoundConfig.GetVolumeSliderMax();
					_sWind.SetValueWithoutNotify(AmbienceSoundConfig.WindVolume.Value);
					if ((Object)(object)_vWind != (Object)null)
					{
						((TMP_Text)_vWind).text = $"{Mathf.RoundToInt(_sWind.value * 100f)}%";
					}
				}
				if ((Object)(object)_sOcean != (Object)null)
				{
					_sOcean.maxValue = AmbienceSoundConfig.GetVolumeSliderMax();
					_sOcean.SetValueWithoutNotify(AmbienceSoundConfig.OceanVolume.Value);
					if ((Object)(object)_vOcean != (Object)null)
					{
						((TMP_Text)_vOcean).text = $"{Mathf.RoundToInt(_sOcean.value * 100f)}%";
					}
				}
				if ((Object)(object)_sAmbientLoop != (Object)null)
				{
					_sAmbientLoop.maxValue = AmbienceSoundConfig.GetVolumeSliderMax();
					_sAmbientLoop.SetValueWithoutNotify(AmbienceSoundConfig.AmbientLoopVolume.Value);
					if ((Object)(object)_vAmbientLoop != (Object)null)
					{
						((TMP_Text)_vAmbientLoop).text = $"{Mathf.RoundToInt(_sAmbientLoop.value * 100f)}%";
					}
				}
				if ((Object)(object)_sShieldHum != (Object)null)
				{
					_sShieldHum.maxValue = AmbienceSoundConfig.GetVolumeSliderMax();
					_sShieldHum.SetValueWithoutNotify(AmbienceSoundConfig.ShieldHumVolume.Value);
					if ((Object)(object)_vShieldHum != (Object)null)
					{
						((TMP_Text)_vShieldHum).text = $"{Mathf.RoundToInt(_sShieldHum.value * 100f)}%";
					}
				}
				if ((Object)(object)_sExtraSfx != (Object)null)
				{
					_sExtraSfx.maxValue = AmbienceSoundConfig.GetVolumeSliderMax();
					_sExtraSfx.SetValueWithoutNotify(AmbienceSoundConfig.ExtraSfxVolume.Value);
					if ((Object)(object)_vExtraSfx != (Object)null)
					{
						((TMP_Text)_vExtraSfx).text = $"{Mathf.RoundToInt(_sExtraSfx.value * 100f)}%";
					}
				}
				if ((Object)(object)_sExtraClip != (Object)null)
				{
					_sExtraClip.maxValue = AmbienceSoundConfig.GetVolumeSliderMax();
					_sExtraClip.SetValueWithoutNotify(AmbienceSoundConfig.ExtraClipVolume.Value);
					if ((Object)(object)_vExtraClip != (Object)null)
					{
						((TMP_Text)_vExtraClip).text = $"{Mathf.RoundToInt(_sExtraClip.value * 100f)}%";
					}
				}
			}
			catch (Exception ex)
			{
				Debug.LogError((object)("[AmbienceSoundConfig] SyncUI failed: " + ex));
			}
		}

		private static GameObject FindDeepChild(Transform parent, string name)
		{
			Transform val = FindDeepChildTransform(parent, name);
			if (!Object.op_Implicit((Object)(object)val))
			{
				return null;
			}
			return ((Component)val).gameObject;
		}

		private static Transform FindDeepChildTransform(Transform parent, string name)
		{
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0015: Expected O, but got Unknown
			foreach (Transform item in parent)
			{
				Transform val = item;
				if (((Object)val).name == name)
				{
					return val;
				}
				Transform val2 = FindDeepChildTransform(val, name);
				if ((Object)(object)val2 != (Object)null)
				{
					return val2;
				}
			}
			return null;
		}
	}
	internal static class SoundPlayLogger
	{
		private static readonly HashSet<string> _seen = new HashSet<string>(StringComparer.OrdinalIgnoreCase);

		private static string _logPath;

		internal static void Init(ConfigFile config)
		{
			try
			{
				_logPath = Path.Combine(Path.GetDirectoryName(config.ConfigFilePath), "AmbienceSoundConfig_SoundLog.txt");
			}
			catch
			{
				_logPath = Path.Combine(Paths.ConfigPath, "AmbienceSoundConfig_SoundLog.txt");
			}
		}

		internal static void Log(string type, string name, GameObject go = null)
		{
			if (!AmbienceSoundConfig.EnableSoundLogging.Value || string.IsNullOrEmpty(name) || (AmbienceSoundConfig.LogOnlyUnique.Value && !_seen.Add(type + "|" + name)))
			{
				return;
			}
			string text = DateTime.Now.ToString("HH:mm:ss.fff");
			string text2 = (((Object)(object)go != (Object)null) ? ("[" + text + "] " + type + ": " + name + " @ " + ((Object)go).name) : ("[" + text + "] " + type + ": " + name));
			Debug.Log((object)("[ASC-LOG] " + text2));
			try
			{
				File.AppendAllText(_logPath, text2 + Environment.NewLine);
			}
			catch
			{
			}
		}
	}
	[HarmonyPatch(typeof(ZSFX))]
	internal static class ZSFX_VolumeScale_Patch
	{
		[HarmonyPostfix]
		[HarmonyPatch("CustomUpdate")]
		private static void Postfix(ZSFX __instance)
		{
			if (!AudioSourceFilter.HasClipTargets)
			{
				return;
			}
			AudioSource component = ((Component)__instance).GetComponent<AudioSource>();
			if (!((Object)(object)component == (Object)null) && !((Object)(object)component.clip == (Object)null))
			{
				if (component.isPlaying)
				{
					SoundPlayLogger.Log("ZSFX", ((Object)component.clip).name, ((Component)__instance).gameObject);
				}
				float num = 1f;
				if (AudioSourceFilter.TryGetClipMultiplier(component.clip, out var multiplier))
				{
					num = multiplier;
				}
				__instance.SetVolumeModifier((num <= 0f) ? 0f : num);
			}
		}
	}
}