Decompiled source of Ambient Muter v1.0.7

BepInEx\plugins\AmbientMuter\AmbientMuter.dll

Decompiled a week ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Reflection.Emit;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Configuration;
using FMOD.Studio;
using FMODUnity;
using FistVR;
using HarmonyLib;
using UnityEngine;
using UnityEngine.SceneManagement;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETFramework,Version=v4.6", FrameworkDisplayName = ".NET Framework 4.6")]
[assembly: AssemblyCompany("AmbientMuter")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("AmbientMuter")]
[assembly: AssemblyTitle("AmbientMuter")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.0.0")]
[module: UnverifiableCode]
namespace AmbientMuter;

[BepInPlugin("h3vr.invent60.ambientmuter", "AmbientMuter", "1.0.7")]
public class AmbientMuterPlugin : BaseUnityPlugin
{
	private ConfigEntry<bool> _cfgMuteMusic;

	private ConfigEntry<bool> _cfgMuteAmbient;

	private ConfigEntry<float> _cfgSweepDelay;

	private ConfigEntry<bool> _cfgKeepFootsteps;

	private ConfigEntry<bool> _cfgKeepInteractive;

	private ConfigEntry<bool> _cfgMutePlayerHurt;

	private Bus _musicBus;

	private bool _busObtained;

	private Harmony _harmony;

	private bool _calibrated;

	private int _calibrationAttempts;

	private void Awake()
	{
		//IL_001d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0027: Expected O, but got Unknown
		BindConfig();
		SceneManager.sceneLoaded += OnSceneLoaded;
		_harmony = new Harmony("h3vr.invent60.ambientmuter");
		_harmony.PatchAll(typeof(CursedLLPitchFix));
		try
		{
			_harmony.PatchAll(typeof(MagBoopTimerFix));
			((BaseUnityPlugin)this).Logger.LogInfo((object)"[AmbientMuter] MagBoop slow-mo timer fix applied.");
		}
		catch
		{
		}
		((MonoBehaviour)this).StartCoroutine(DetectCursedLL());
		((BaseUnityPlugin)this).Logger.LogInfo((object)"[AmbientMuter] Loaded.");
	}

	private void BindConfig()
	{
		_cfgMuteMusic = ((BaseUnityPlugin)this).Config.Bind<bool>("Music", "Mute map music", true, "Zeros the FMOD music bus every frame, silencing background music in all maps (TNH, outdoor assault maps, etc.). Overrides any other mod that sets music volume.");
		_cfgMuteAmbient = ((BaseUnityPlugin)this).Config.Bind<bool>("Ambient", "Mute ambient sounds", true, "Mutes map ambient AudioSources (wind loops, propaganda speakers, environment drones). Applied once per scene load after the sweep delay.");
		_cfgSweepDelay = ((BaseUnityPlugin)this).Config.Bind<float>("Ambient", "Sweep delay seconds", 4f, "Seconds to wait after scene load before sweeping ambient sources. Increase if some ambient sounds are not being caught. (0 to 30)");
		_cfgKeepInteractive = ((BaseUnityPlugin)this).Config.Bind<bool>("Ambient", "Keep interactive object sounds", true, "Buttons, levers, switches, and other interactive map objects keep their sounds. Disable to also silence these.");
		_cfgKeepFootsteps = ((BaseUnityPlugin)this).Config.Bind<bool>("Player", "Keep footstep mod sounds", true, "Footstep mods (PlayerFootsteps, AlyxFootsteps, EFT Frame, BF4 Footsteps) are not silenced. Disable to mute footstep sounds too.");
		_cfgMutePlayerHurt = ((BaseUnityPlugin)this).Config.Bind<bool>("Player", "Mute player hurt sounds", false, "Mutes pain and impact sounds when the player takes damage.");
	}

	private IEnumerator DetectCursedLL()
	{
		yield return null;
		try
		{
			PropertyInfo property = typeof(AudioSource).GetProperty("pitch");
			if ((object)property == null)
			{
				yield break;
			}
			MethodInfo setMethod = property.GetSetMethod();
			if ((object)setMethod == null)
			{
				yield break;
			}
			Patches patchInfo = Harmony.GetPatchInfo((MethodBase)setMethod);
			if (patchInfo == null)
			{
				yield break;
			}
			int num = 0;
			foreach (Patch prefix in patchInfo.Prefixes)
			{
				if (!string.Equals(prefix.owner, "h3vr.invent60.ambientmuter", StringComparison.OrdinalIgnoreCase))
				{
					((BaseUnityPlugin)this).Logger.LogInfo((object)("[AmbientMuter] pitch-setter prefix: " + prefix.owner));
					num++;
				}
			}
			foreach (Patch postfix in patchInfo.Postfixes)
			{
				if (!string.Equals(postfix.owner, "h3vr.invent60.ambientmuter", StringComparison.OrdinalIgnoreCase))
				{
					((BaseUnityPlugin)this).Logger.LogInfo((object)("[AmbientMuter] pitch-setter postfix: " + postfix.owner));
					num++;
				}
			}
			foreach (Patch transpiler in patchInfo.Transpilers)
			{
				if (!string.Equals(transpiler.owner, "h3vr.invent60.ambientmuter", StringComparison.OrdinalIgnoreCase))
				{
					((BaseUnityPlugin)this).Logger.LogInfo((object)("[AmbientMuter] pitch-setter transpiler: " + transpiler.owner));
					num++;
				}
			}
			if (num > 0)
			{
				CursedLLPitchFix.PatcherDetected = true;
				((BaseUnityPlugin)this).Logger.LogInfo((object)("[AmbientMuter] pitch-setter patcher(s) found (" + num + "). Calibration deferred to first slow-mo."));
			}
			else
			{
				((BaseUnityPlugin)this).Logger.LogInfo((object)"[AmbientMuter] CursedLL pitch fix: not needed");
			}
		}
		catch
		{
		}
	}

	private void TryGetBus()
	{
		//IL_0006: Unknown result type (might be due to invalid IL or missing references)
		//IL_000b: Unknown result type (might be due to invalid IL or missing references)
		try
		{
			_musicBus = RuntimeManager.GetBus("bus:/Music");
			_busObtained = true;
		}
		catch
		{
		}
	}

	private void Update()
	{
		//IL_0082: Unknown result type (might be due to invalid IL or missing references)
		CursedLLPitchFix.CachedTimeScale = Time.timeScale;
		if (CursedLLPitchFix.PatcherDetected && !_calibrated && _calibrationAttempts < 5 && Time.timeScale < 0.99f && Time.timeScale > 0.001f)
		{
			_calibrationAttempts++;
			MeasurePitchCompound();
			_calibrated = CursedLLPitchFix.Initialized;
		}
		if (!_cfgMuteMusic.Value)
		{
			return;
		}
		if (!_busObtained)
		{
			TryGetBus();
			return;
		}
		try
		{
			((Bus)(ref _musicBus)).setVolume(0f);
		}
		catch
		{
			_busObtained = false;
		}
	}

	private void MeasurePitchCompound()
	{
		//IL_0020: Unknown result type (might be due to invalid IL or missing references)
		//IL_0026: Expected O, but got Unknown
		try
		{
			float cachedTimeScale = CursedLLPitchFix.CachedTimeScale;
			if (cachedTimeScale <= 0.001f || cachedTimeScale >= 0.999f)
			{
				return;
			}
			GameObject val = new GameObject("__AMCalib");
			AudioSource obj = val.AddComponent<AudioSource>();
			obj.volume = 0f;
			obj.mute = true;
			obj.pitch = 1f;
			float pitch = obj.pitch;
			Object.Destroy((Object)(object)val);
			if (pitch <= 0f)
			{
				return;
			}
			float num = Mathf.Log(cachedTimeScale);
			float num2 = Mathf.Log(pitch);
			if (!(Mathf.Abs(num) < 0.0001f))
			{
				int num3 = Mathf.RoundToInt(num2 / num);
				if (num3 > 0)
				{
					CursedLLPitchFix.CompoundLevels = num3;
					CursedLLPitchFix.ExtraCompounders = Mathf.Max(0, num3 - 1);
					CursedLLPitchFix.CursedActive = true;
					CursedLLPitchFix.Initialized = true;
					((BaseUnityPlugin)this).Logger.LogInfo((object)$"[AmbientMuter] CursedLL calibrated: {num3} compound level(s), {CursedLLPitchFix.ExtraCompounders} extra (ts={cachedTimeScale:F3})");
				}
			}
		}
		catch (Exception ex)
		{
			((BaseUnityPlugin)this).Logger.LogWarning((object)("[AmbientMuter] CursedLL calibration error: " + ex.Message));
		}
	}

	private void OnSceneLoaded(Scene scene, LoadSceneMode mode)
	{
		_busObtained = false;
		if (_cfgMuteAmbient.Value)
		{
			((MonoBehaviour)this).StartCoroutine(MuteAmbientDelayed());
		}
	}

	private IEnumerator MuteAmbientDelayed()
	{
		yield return (object)new WaitForSeconds(_cfgSweepDelay.Value);
		MuteAmbientSources();
	}

	private void MuteAmbientSources()
	{
		//IL_0063: Unknown result type (might be due to invalid IL or missing references)
		//IL_0068: Unknown result type (might be due to invalid IL or missing references)
		bool value = _cfgKeepFootsteps.Value;
		bool value2 = _cfgKeepInteractive.Value;
		bool value3 = _cfgMutePlayerHurt.Value;
		int num = 0;
		int num2 = 0;
		AudioSource[] array = Object.FindObjectsOfType<AudioSource>();
		foreach (AudioSource val in array)
		{
			if ((Object)(object)((Component)val).GetComponent<FVRPooledAudioSource>() != (Object)null)
			{
				num2++;
				continue;
			}
			if (value)
			{
				Scene scene = ((Component)val).gameObject.scene;
				if (((Scene)(ref scene)).name == "DontDestroyOnLoad")
				{
					num2++;
					continue;
				}
			}
			if (value2 && (Object)(object)((Component)val).GetComponentInParent<FVRInteractiveObject>() != (Object)null)
			{
				num2++;
				continue;
			}
			if (!value2 && (Object)(object)((Component)val).GetComponentInParent<FVRPhysicalObject>() != (Object)null)
			{
				num2++;
				continue;
			}
			if ((Object)(object)((Component)val).GetComponentInParent<Sosig>() != (Object)null)
			{
				num2++;
				continue;
			}
			if ((Object)(object)((Component)val).GetComponentInParent<FVRMovementManager>() != (Object)null && !value3)
			{
				num2++;
				continue;
			}
			if (value && (Object)(object)((Component)val).GetComponentInParent<BaseUnityPlugin>() != (Object)null)
			{
				num2++;
				continue;
			}
			val.mute = true;
			num++;
		}
		((BaseUnityPlugin)this).Logger.LogInfo((object)$"[AmbientMuter] Scene sweep done. Muted: {num}, Kept: {num2}");
	}
}
[HarmonyPatch]
public static class MagBoopTimerFix
{
	private static MethodBase TargetMethod()
	{
		return AccessTools.Method("MagBoop.MagTriggerScript:Update", (Type[])null, (Type[])null);
	}

	[HarmonyTranspiler]
	private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions)
	{
		MethodInfo getMethod = typeof(Time).GetProperty("fixedUnscaledDeltaTime").GetGetMethod();
		List<CodeInstruction> list = instructions.ToList();
		for (int i = 0; i < list.Count; i++)
		{
			if (list[i].opcode == OpCodes.Call && list[i].operand is MethodInfo methodInfo && methodInfo.DeclaringType == typeof(Time) && methodInfo.Name == "get_fixedDeltaTime")
			{
				list[i].operand = getMethod;
			}
		}
		return list;
	}
}
public static class CursedLLPitchFix
{
	public static bool PatcherDetected = false;

	public static bool Initialized = false;

	public static bool CursedActive = false;

	public static int CompoundLevels = 0;

	public static int ExtraCompounders = 0;

	public static float CachedTimeScale = 1f;

	[HarmonyPatch(/*Could not decode attribute arguments.*/)]
	[HarmonyPostfix]
	public static void CompensatePitchRead(ref float __result)
	{
		if (Initialized && CursedActive && !(CachedTimeScale >= 0.9999f) && !(CachedTimeScale <= 0.001f))
		{
			__result /= CachedTimeScale;
		}
	}

	[HarmonyPatch(/*Could not decode attribute arguments.*/)]
	[HarmonyPrefix]
	public static void PreCompensatePitchSet(ref float value)
	{
		if (Initialized && CursedActive && !(CachedTimeScale >= 0.9999f) && !(CachedTimeScale <= 0.001f) && ExtraCompounders > 0)
		{
			for (int i = 0; i < ExtraCompounders; i++)
			{
				value /= CachedTimeScale;
			}
		}
	}
}