Decompiled source of AmbienceSoundConfig v2.4.0

AmbienceSoundConfig.dll

Decompiled 3 days ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Configuration;
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.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[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 AmbienceSoundConfig;

[BepInPlugin("com.draconicvelum.ambiencesoundconfig", "Ambience Sound Config", "2.4.0")]
public class AmbienceSoundConfig : BaseUnityPlugin
{
	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;

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

	private void Awake()
	{
		//IL_002f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0039: Expected O, but got Unknown
		//IL_006c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0076: Expected O, but got Unknown
		//IL_00a9: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b3: Expected O, but got Unknown
		//IL_00e6: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f0: Expected O, but got Unknown
		//IL_0123: Unknown result type (might be due to invalid IL or missing references)
		//IL_012d: Expected O, but got Unknown
		MasterVolume = ((BaseUnityPlugin)this).Config.Bind<float>("Ambience", "Master Volume", 0.25f, new ConfigDescription("Controls overall ambience loudness multiplier.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1f), 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, 1f), 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, 1f), 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, 1f), 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, 1f), Array.Empty<object>()));
		harmony.PatchAll(typeof(AudioMan_AmbienceVolume_Patch));
		harmony.PatchAll(typeof(SettingsInject));
		((BaseUnityPlugin)this).Config.ConfigReloaded += OnReloaded;
		((BaseUnityPlugin)this).Logger.LogInfo((object)"Ambience Sound Config (v2.4.0) loaded. UI inject via SettingsInject (single init, no tab re-inject).");
	}

	private void OnReloaded(object sender, EventArgs e)
	{
		ApplyAllVolumes();
		SettingsInject.SyncUI();
	}

	public static void ApplyAllVolumes()
	{
		AudioMan_AmbienceVolume_Patch.ApplyWindVolumeWrapper();
		AudioMan_AmbienceVolume_Patch.ApplyOceanVolumeWrapper();
		AudioMan_AmbienceVolume_Patch.ApplyAmbientLoopVolumeWrapper();
		AudioMan_AmbienceVolume_Patch.ApplyShieldHumVolumeWrapper();
	}
}
[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();
	}
}
[HarmonyPatch(typeof(AudioSettings))]
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 TextMeshProUGUI _vMaster;

	internal static TextMeshProUGUI _vWind;

	internal static TextMeshProUGUI _vOcean;

	internal static TextMeshProUGUI _vAmbientLoop;

	internal static TextMeshProUGUI _vShieldHum;

	[HarmonyPostfix]
	[HarmonyPatch("LoadSettings")]
	private static void Postfix_LoadSettings(AudioSettings __instance)
	{
		//IL_0112: Unknown result type (might be due to invalid IL or missing references)
		//IL_0119: Expected O, but got Unknown
		//IL_0171: Unknown result type (might be due to invalid IL or missing references)
		//IL_0188: 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_01ac: Unknown result type (might be due to invalid IL or missing references)
		//IL_01b9: Unknown result type (might be due to invalid IL or missing references)
		//IL_01d0: Unknown result type (might be due to invalid IL or missing references)
		//IL_01e7: Unknown result type (might be due to invalid IL or missing references)
		//IL_0201: Unknown result type (might be due to invalid IL or missing references)
		//IL_020b: Expected O, but got Unknown
		//IL_0218: Unknown result type (might be due to invalid IL or missing references)
		//IL_022f: Unknown result type (might be due to invalid IL or missing references)
		try
		{
			if (_built && (Object)(object)_gridContainer != (Object)null)
			{
				SyncUI();
				return;
			}
			Transform obj = ((Component)__instance).transform.Find("MusicVolume");
			object obj2 = ((obj != null) ? ((Component)obj).gameObject : null);
			if (obj2 == null)
			{
				GameObject obj3 = FindDeepChild(((Component)__instance).transform, "MusicVolume");
				obj2 = ((obj3 != null) ? obj3.gameObject : null);
			}
			GameObject val = (GameObject)obj2;
			if ((Object)(object)val == (Object)null)
			{
				Debug.LogWarning((object)"[AmbienceSoundConfig] Could not locate MusicVolume as base template.");
				return;
			}
			Toggle value = Traverse.Create((object)__instance).Field("m_continousMusic").GetValue<Toggle>();
			Transform val2 = ((value != null) ? ((Component)value).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)value != (Object)null) ? ((Component)value).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();
		});
	}

	internal static void CreateOrBind(Transform parent, GameObject baseSlider, string labelText, ref Slider sliderRef, ref TextMeshProUGUI valueTextRef, ConfigEntry<float> config, Action<float> onChanged)
	{
		//IL_0061: Unknown result type (might be due to invalid IL or missing references)
		//IL_007e: Unknown result type (might be due to invalid IL or missing references)
		//IL_008b: Unknown result type (might be due to invalid IL or missing references)
		string text = "Ambience_" + labelText.Replace(" ", "");
		Transform val2 = parent.Find(text);
		GameObject val3;
		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;
			TextMeshProUGUI[] 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;
		TextMeshProUGUI[] componentsInChildren2 = val3.GetComponentsInChildren<TextMeshProUGUI>(true);
		foreach (TextMeshProUGUI val6 in componentsInChildren2)
		{
			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 = 1f;
		((UnityEventBase)componentInChildren2.onValueChanged).RemoveAllListeners();
		((UnityEvent<float>)(object)componentInChildren2.onValueChanged).AddListener((UnityAction<float>)delegate(float val)
		{
			config.Value = val;
			((ConfigEntryBase)config).ConfigFile.Save();
			if ((Object)(object)valueText != (Object)null)
			{
				((TMP_Text)valueText).text = $"{Mathf.RoundToInt(val * 100f)}%";
			}
			onChanged?.Invoke(val);
		});
		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.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.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.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.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.SetValueWithoutNotify(AmbienceSoundConfig.ShieldHumVolume.Value);
				if ((Object)(object)_vShieldHum != (Object)null)
				{
					((TMP_Text)_vShieldHum).text = $"{Mathf.RoundToInt(_sShieldHum.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);
		return Object.op_Implicit((Object)(object)val) ? ((Component)val).gameObject : null;
	}

	private static Transform FindDeepChildTransform(Transform parent, string name)
	{
		//IL_0011: Unknown result type (might be due to invalid IL or missing references)
		//IL_0017: 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;
	}
}