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;
}
}