Decompiled source of MuteMusic v1.0.3

BepInEx/plugins/MuteMusic/MuteMusic.dll

Decompiled 5 days ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using UnityEngine;
using UnityEngine.SceneManagement;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("MuteMusic")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.3.0")]
[assembly: AssemblyInformationalVersion("1.0.3")]
[assembly: AssemblyProduct("Mute Music")]
[assembly: AssemblyTitle("MuteMusic")]
[assembly: AssemblyVersion("1.0.3.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableAttribute : Attribute
	{
		public readonly byte[] NullableFlags;

		public NullableAttribute(byte P_0)
		{
			NullableFlags = new byte[1] { P_0 };
		}

		public NullableAttribute(byte[] P_0)
		{
			NullableFlags = P_0;
		}
	}
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableContextAttribute : Attribute
	{
		public readonly byte Flag;

		public NullableContextAttribute(byte P_0)
		{
			Flag = P_0;
		}
	}
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace MuteMusic
{
	public static class AudioNames
	{
		private static readonly string[] Protected = new string[12]
		{
			"speaker", "shipintro", "introspeech", "shiplanding", "shiparrive", "shipdepart", "shipmotor", "ship3d", "shipdoor", "turbulence",
			"thruster", "shipalarm"
		};

		private static readonly string[] GameplayKeep = new string[5] { "boombox", "radio", "walkie", "heartbeat", "jester" };

		private static readonly string[] Soundtrack = new string[8] { "music", "theme", "daytime", "evening", "soundtrack", "icecream", "timeofday", "menuaudio" };

		public static bool IsProtected(string? name)
		{
			return ContainsAny(name, Protected);
		}

		public static bool IsGameplayKeep(string? name)
		{
			return ContainsAny(name, GameplayKeep);
		}

		public static bool IsSoundtrack(string? name)
		{
			if (string.IsNullOrEmpty(name) || IsProtected(name) || IsGameplayKeep(name))
			{
				return false;
			}
			return ContainsAny(name, Soundtrack);
		}

		public static bool IsDropshipMelody(string? objectName, string? sourceName, string? clipName)
		{
			if (IsProtected(objectName) || IsProtected(sourceName) || IsProtected(clipName) || IsGameplayKeep(objectName) || IsGameplayKeep(sourceName) || IsGameplayKeep(clipName))
			{
				return false;
			}
			if (ContainsAny(clipName, "icecream") || ContainsAny(objectName, "icecream"))
			{
				return true;
			}
			if (!IsBareMusicName(objectName))
			{
				return IsBareMusicName(sourceName);
			}
			return true;
		}

		public static bool IsBareMusicName(string? name)
		{
			if (string.IsNullOrEmpty(name))
			{
				return false;
			}
			string text = name.Trim();
			if (text.Equals("music", StringComparison.OrdinalIgnoreCase))
			{
				return true;
			}
			if (text.StartsWith("music (", StringComparison.OrdinalIgnoreCase))
			{
				return text.EndsWith(")", StringComparison.Ordinal);
			}
			return false;
		}

		public static bool ContainsAny(string? text, params string[] needles)
		{
			if (string.IsNullOrEmpty(text) || needles == null || needles.Length == 0)
			{
				return false;
			}
			foreach (string value in needles)
			{
				if (!string.IsNullOrEmpty(value) && text.IndexOf(value, StringComparison.OrdinalIgnoreCase) >= 0)
				{
					return true;
				}
			}
			return false;
		}
	}
	public static class VolumeMath
	{
		public const float Silent = 0.001f;

		public static float Clamp01(float value)
		{
			if (float.IsNaN(value) || float.IsInfinity(value))
			{
				return 0f;
			}
			if (value < 0f)
			{
				return 0f;
			}
			if (value > 1f)
			{
				return 1f;
			}
			return value;
		}

		public static bool IsSilent(float value)
		{
			return Clamp01(value) <= 0.001f;
		}
	}
	internal static class HarmonyPatches
	{
		internal static void Apply(Harmony harmony)
		{
			string[] array = new string[5] { "MenuManager", "SoundManager", "StartOfRound", "TimeOfDay", "ItemDropship" };
			foreach (string text in array)
			{
				Type type = AccessTools.TypeByName(text);
				if (type == null || type.Assembly.GetName().Name != "Assembly-CSharp")
				{
					continue;
				}
				foreach (MethodInfo declaredMethod in AccessTools.GetDeclaredMethods(type))
				{
					try
					{
						PatchMethod(harmony, text, declaredMethod);
					}
					catch (Exception ex)
					{
						ManualLogSource log = Plugin.Log;
						if (log != null)
						{
							log.LogWarning((object)("Skip patch " + text + "." + declaredMethod.Name + ": " + ex.Message));
						}
					}
				}
			}
		}

		private static void PatchMethod(Harmony harmony, string typeName, MethodInfo method)
		{
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0057: Expected O, but got Unknown
			//IL_00a6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b4: Expected O, but got Unknown
			//IL_00df: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ec: Expected O, but got Unknown
			//IL_0117: Unknown result type (might be due to invalid IL or missing references)
			//IL_0124: Expected O, but got Unknown
			//IL_014f: Unknown result type (might be due to invalid IL or missing references)
			//IL_015c: Expected O, but got Unknown
			//IL_01d7: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e4: Expected O, but got Unknown
			bool flag;
			switch (method.Name)
			{
			case "Awake":
			case "Start":
			case "OnEnable":
				flag = true;
				break;
			default:
				flag = false;
				break;
			}
			if (flag)
			{
				harmony.Patch((MethodBase)method, (HarmonyMethod)null, new HarmonyMethod(typeof(HarmonyPatches), "AfterReady", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			}
			else
			{
				switch (method.Name)
				{
				case "PlayRandomOutsideMusic":
				case "PlayTimeMusicDelayed":
				case "StartMusic":
					flag = true;
					break;
				default:
					flag = false;
					break;
				}
				if (flag)
				{
					harmony.Patch((MethodBase)method, new HarmonyMethod(typeof(HarmonyPatches), "SkipIfMusicMuted", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
				}
				else if (method.Name == "firstDayAnimation")
				{
					harmony.Patch((MethodBase)method, (HarmonyMethod)null, new HarmonyMethod(typeof(HarmonyPatches), "WrapShipIntro", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
				}
				else if (method.Name == "PlayFirstDayShipAnimation")
				{
					harmony.Patch((MethodBase)method, (HarmonyMethod)null, new HarmonyMethod(typeof(HarmonyPatches), "AfterIntroStart", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
				}
				else if (method.Name == "openingDoorsSequence")
				{
					harmony.Patch((MethodBase)method, (HarmonyMethod)null, new HarmonyMethod(typeof(HarmonyPatches), "WrapRoundMusic", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
				}
				else
				{
					flag = typeName == "ItemDropship";
					if (flag)
					{
						bool flag2;
						switch (method.Name)
						{
						case "Update":
						case "LandShipClientRpc":
						case "DeliverVehicleClientRpc":
						case "ShipLandedAnimationEvent":
						case "ShipLandedInAnimation":
							flag2 = true;
							break;
						default:
							flag2 = false;
							break;
						}
						flag = flag2;
					}
					if (!flag)
					{
						return;
					}
					harmony.Patch((MethodBase)method, (HarmonyMethod)null, new HarmonyMethod(typeof(HarmonyPatches), "AfterDropship", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
				}
			}
			ManualLogSource log = Plugin.Log;
			if (log != null)
			{
				log.LogInfo((object)("Patched " + typeName + "." + method.Name));
			}
		}

		private static void AfterReady(object __instance)
		{
			try
			{
				MusicController.Register(__instance);
				Plugin.EnsureTicker();
				MusicController.Scan();
				MusicController.ApplyTracked();
				if (__instance.GetType().Name == "ItemDropship")
				{
					MusicController.SilenceDropship(__instance);
				}
			}
			catch (Exception ex)
			{
				ManualLogSource log = Plugin.Log;
				if (log != null)
				{
					log.LogWarning((object)("AfterReady " + __instance?.GetType().Name + ": " + ex.Message));
				}
			}
		}

		private static bool SkipIfMusicMuted()
		{
			return !VolumeMath.IsSilent(ModConfig.EffectiveVolume);
		}

		private static void AfterDropship(object __instance)
		{
			try
			{
				MusicController.SilenceDropship(__instance);
			}
			catch (Exception ex)
			{
				ManualLogSource log = Plugin.Log;
				if (log != null)
				{
					log.LogWarning((object)("AfterDropship: " + ex.Message));
				}
			}
		}

		private static void AfterIntroStart(object __instance)
		{
			try
			{
				MusicController.Register(__instance);
				MusicController.SilenceIntro(includeSpeaker: true);
			}
			catch (Exception ex)
			{
				ManualLogSource log = Plugin.Log;
				if (log != null)
				{
					log.LogWarning((object)("AfterIntroStart: " + ex.Message));
				}
			}
		}

		private static void WrapShipIntro(object __instance, ref IEnumerator __result)
		{
			try
			{
				MusicController.Register(__instance);
				if (__result != null)
				{
					__result = MusicController.SilenceWhile(__result, includeSpeaker: true);
				}
			}
			catch (Exception ex)
			{
				ManualLogSource log = Plugin.Log;
				if (log != null)
				{
					log.LogWarning((object)("WrapShipIntro: " + ex.Message));
				}
			}
		}

		private static void WrapRoundMusic(object __instance, ref IEnumerator __result)
		{
			try
			{
				MusicController.Register(__instance);
				if (__result != null)
				{
					__result = MusicController.SilenceWhile(__result, includeSpeaker: false);
				}
			}
			catch (Exception ex)
			{
				ManualLogSource log = Plugin.Log;
				if (log != null)
				{
					log.LogWarning((object)("WrapRoundMusic: " + ex.Message));
				}
			}
		}
	}
	internal static class ModConfig
	{
		internal static ConfigEntry<float> MusicVolume;

		internal static float EffectiveVolume
		{
			get
			{
				try
				{
					return (MusicVolume == null) ? 0f : VolumeMath.Clamp01(MusicVolume.Value);
				}
				catch
				{
					return 0f;
				}
			}
		}

		internal static void Bind(ConfigFile config)
		{
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_0033: Expected O, but got Unknown
			MusicVolume = config.Bind<float>("General", "MusicVolume", 0f, new ConfigDescription("Soundtrack muted when 0, vanilla when 1. Independent from master volume.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1f), Array.Empty<object>()));
		}
	}
	internal static class MusicController
	{
		private static readonly Dictionary<int, float> OriginalVolumes = new Dictionary<int, float>();

		private static readonly HashSet<int> TrackedIds = new HashSet<int>();

		private static readonly List<AudioSource> Tracked = new List<AudioSource>();

		private static readonly Dictionary<string, Type?> TypeCache = new Dictionary<string, Type>();

		private static readonly string[] MusicFields = new string[11]
		{
			"MenuAudio", "musicSource", "TimeOfDayMusic", "musicAudio", "elevatorJingleMusic", "companyVisitMusic", "endStatsMusic", "rewardsMusic", "advertMusic", "firstTimeAudio",
			"coldOpen2Audio"
		};

		private static readonly BindingFlags AnyMember = BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic;

		private static Component? MenuManager;

		private static Component? _soundManager;

		private static Component? _startOfRound;

		private static Component? _timeOfDay;

		private static float _nextScan;

		private static string _lastScene = "";

		private static readonly Dictionary<int, List<AudioSource>> DropshipSources = new Dictionary<int, List<AudioSource>>();

		internal static void Register(object instance)
		{
			Component val = (Component)((instance is Component) ? instance : null);
			if (val != null && Object.op_Implicit((Object)(object)val))
			{
				switch (((object)val).GetType().Name)
				{
				case "MenuManager":
					MenuManager = val;
					break;
				case "SoundManager":
					_soundManager = val;
					break;
				case "StartOfRound":
					_startOfRound = val;
					break;
				case "TimeOfDay":
					_timeOfDay = val;
					break;
				}
			}
		}

		internal static void OnSceneChanged()
		{
			MenuManager = null;
			_soundManager = null;
			_startOfRound = null;
			_timeOfDay = null;
			Tracked.Clear();
			TrackedIds.Clear();
			OriginalVolumes.Clear();
			DropshipSources.Clear();
			_lastScene = "";
			_nextScan = 0f;
		}

		internal static void Tick()
		{
			try
			{
				ApplyTracked();
				if (Time.unscaledTime >= _nextScan)
				{
					_nextScan = Time.unscaledTime + 8f;
					Scan();
				}
			}
			catch (Exception ex)
			{
				ManualLogSource log = Plugin.Log;
				if (log != null)
				{
					log.LogWarning((object)("MusicController.Tick: " + ex.Message));
				}
			}
		}

		internal static void Scan()
		{
			//IL_006a: Unknown result type (might be due to invalid IL or missing references)
			//IL_006f: Unknown result type (might be due to invalid IL or missing references)
			if (_soundManager == null)
			{
				_soundManager = FindSingleton("SoundManager");
			}
			if (_startOfRound == null)
			{
				_startOfRound = FindSingleton("StartOfRound");
			}
			if (_timeOfDay == null)
			{
				_timeOfDay = FindSingleton("TimeOfDay");
			}
			CollectFields(MenuManager);
			CollectFields(_soundManager);
			CollectFields(_startOfRound);
			CollectFields(_timeOfDay);
			Scene activeScene = SceneManager.GetActiveScene();
			string name = ((Scene)(ref activeScene)).name;
			if (name != _lastScene)
			{
				_lastScene = name;
				Dump();
			}
		}

		internal static void ApplyTracked()
		{
			float effectiveVolume = ModConfig.EffectiveVolume;
			for (int num = Tracked.Count - 1; num >= 0; num--)
			{
				AudioSource val = Tracked[num];
				if ((Object)(object)val == (Object)null || AudioNames.IsProtected(Names(val)))
				{
					if ((Object)(object)val == (Object)null)
					{
						Tracked.RemoveAt(num);
					}
					else
					{
						TrackedIds.Remove(((Object)val).GetInstanceID());
						Tracked.RemoveAt(num);
					}
				}
				else
				{
					ApplyToSource(val, effectiveVolume);
				}
			}
		}

		internal static void ApplyToSource(AudioSource source, float volume)
		{
			if (!((Object)(object)source == (Object)null))
			{
				int instanceID = ((Object)source).GetInstanceID();
				if (!OriginalVolumes.ContainsKey(instanceID))
				{
					OriginalVolumes[instanceID] = ((source.volume > 0.01f && !source.mute) ? source.volume : 1f);
				}
				source.mute = VolumeMath.IsSilent(volume);
				source.volume = OriginalVolumes[instanceID] * volume;
				if (VolumeMath.IsSilent(volume) && source.isPlaying)
				{
					source.Stop();
					source.playOnAwake = false;
				}
			}
		}

		internal static IEnumerator SilenceWhile(IEnumerator original, bool includeSpeaker)
		{
			if (original != null)
			{
				TrySilence(includeSpeaker);
				while (original.MoveNext())
				{
					TrySilence(includeSpeaker);
					yield return original.Current;
				}
				TrySilence(includeSpeaker);
			}
		}

		internal static void SilenceDropship(object instance)
		{
			Component val = (Component)((instance is Component) ? instance : null);
			if (val == null || !Object.op_Implicit((Object)(object)val))
			{
				return;
			}
			int instanceID = ((Object)val).GetInstanceID();
			if (!DropshipSources.TryGetValue(instanceID, out List<AudioSource> value))
			{
				value = new List<AudioSource>();
				AudioSource[] componentsInChildren = val.GetComponentsInChildren<AudioSource>(true);
				foreach (AudioSource val2 in componentsInChildren)
				{
					if (Object.op_Implicit((Object)(object)val2))
					{
						string clipName = (((Object)(object)val2.clip != (Object)null) ? ((Object)val2.clip).name : "");
						if (AudioNames.IsDropshipMelody(((Object)((Component)val2).gameObject).name, ((Object)val2).name, clipName))
						{
							value.Add(val2);
						}
					}
				}
				if (value.Count == 0)
				{
					return;
				}
				DropshipSources[instanceID] = value;
			}
			float effectiveVolume = ModConfig.EffectiveVolume;
			for (int j = 0; j < value.Count; j++)
			{
				AudioSource val3 = value[j];
				if (Object.op_Implicit((Object)(object)val3))
				{
					Track(val3);
					ApplyToSource(val3, effectiveVolume);
				}
			}
		}

		internal static void SilenceIntro(bool includeSpeaker)
		{
			if (VolumeMath.IsSilent(ModConfig.EffectiveVolume))
			{
				StopNamed(_timeOfDay, "TimeOfDayMusic", hardMute: true);
				StopNamed(_soundManager, "musicSource", hardMute: true);
				StopNamed(_startOfRound, "firstTimeAudio", hardMute: true);
				StopNamed(_startOfRound, "coldOpen2Audio", hardMute: true);
				if (includeSpeaker)
				{
					StopNamed(_startOfRound, "speakerAudioSource", hardMute: false);
					StopNamed(_startOfRound, "speakerAudio", hardMute: false);
				}
			}
		}

		private static void TrySilence(bool includeSpeaker)
		{
			try
			{
				SilenceIntro(includeSpeaker);
			}
			catch (Exception ex)
			{
				ManualLogSource log = Plugin.Log;
				if (log != null)
				{
					log.LogWarning((object)("SilenceIntro: " + ex.Message));
				}
			}
		}

		private static void StopNamed(object? instance, string field, bool hardMute)
		{
			if (instance == null)
			{
				return;
			}
			AudioSource member = GetMember<AudioSource>(instance, field);
			if (member != null && Object.op_Implicit((Object)(object)member))
			{
				member.Stop();
				if (hardMute)
				{
					member.mute = true;
					member.volume = 0f;
					member.playOnAwake = false;
				}
			}
		}

		private static void CollectFields(Component? component)
		{
			if (!Object.op_Implicit((Object)(object)component))
			{
				return;
			}
			string[] musicFields = MusicFields;
			foreach (string name in musicFields)
			{
				AudioSource member = GetMember<AudioSource>(component, name);
				if (member != null && Object.op_Implicit((Object)(object)member))
				{
					Track(member);
				}
			}
		}

		private static Component? FindSingleton(string typeName)
		{
			Type type = ResolveType(typeName);
			if (type == null)
			{
				return null;
			}
			try
			{
				object? obj = type.GetProperty("Instance", AnyMember)?.GetValue(null, null);
				Component val = (Component)((obj is Component) ? obj : null);
				if (val != null && Object.op_Implicit((Object)(object)val))
				{
					return val;
				}
				object? obj2 = type.GetField("Instance", AnyMember)?.GetValue(null);
				return (Component?)((obj2 is Component) ? obj2 : null);
			}
			catch
			{
				return null;
			}
		}

		private static Type? ResolveType(string typeName)
		{
			if (TypeCache.TryGetValue(typeName, out Type value))
			{
				return value;
			}
			Type type = AccessTools.TypeByName(typeName);
			if (type != null && type.Assembly.GetName().Name != "Assembly-CSharp")
			{
				type = null;
			}
			TypeCache[typeName] = type;
			return type;
		}

		private static T? GetMember<T>(object? obj, string name) where T : class
		{
			if (obj == null)
			{
				return null;
			}
			try
			{
				Type type = obj.GetType();
				if (type.GetField(name, AnyMember)?.GetValue(obj) is T result)
				{
					return result;
				}
				return type.GetProperty(name, AnyMember)?.GetValue(obj, null) as T;
			}
			catch
			{
				return null;
			}
		}

		private static void Track(AudioSource source)
		{
			if (!((Object)(object)source == (Object)null) && !AudioNames.IsProtected(Names(source)))
			{
				int instanceID = ((Object)source).GetInstanceID();
				if (TrackedIds.Add(instanceID))
				{
					Tracked.Add(source);
				}
			}
		}

		private static string Names(AudioSource source)
		{
			string text = (((Object)(object)source.clip != (Object)null) ? ((Object)source.clip).name : "");
			return ((Object)((Component)source).gameObject).name + " " + ((Object)source).name + " " + text;
		}

		private static void Dump()
		{
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			ManualLogSource log = Plugin.Log;
			if (log != null)
			{
				Scene activeScene = SceneManager.GetActiveScene();
				log.LogInfo((object)$"Scene={((Scene)(ref activeScene)).name} tracked={Tracked.Count}");
			}
		}
	}
	[BepInPlugin("lc.mutemusic", "Mute Music", "1.0.3")]
	public sealed class Plugin : BaseUnityPlugin
	{
		public const string PluginGuid = "lc.mutemusic";

		public const string PluginName = "Mute Music";

		public const string PluginVersion = "1.0.3";

		private Harmony? _harmony;

		private static GameObject? _ticker;

		internal static ManualLogSource Log { get; private set; }

		private void Awake()
		{
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: Expected O, but got Unknown
			try
			{
				Log = ((BaseUnityPlugin)this).Logger;
				ModConfig.Bind(((BaseUnityPlugin)this).Config);
				_harmony = new Harmony("lc.mutemusic");
				HarmonyPatches.Apply(_harmony);
				EnsureTicker();
				SceneManager.sceneLoaded += OnSceneLoaded;
				Log.LogInfo((object)string.Format("{0} {1} loaded. Music volume {2:0.00}.", "Mute Music", "1.0.3", ModConfig.EffectiveVolume));
			}
			catch (Exception arg)
			{
				((BaseUnityPlugin)this).Logger.LogError((object)$"Mute Music failed to load: {arg}");
			}
		}

		internal static void EnsureTicker()
		{
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: Expected O, but got Unknown
			if (!Object.op_Implicit((Object)(object)_ticker))
			{
				_ticker = new GameObject("MuteMusicTicker");
				Object.DontDestroyOnLoad((Object)(object)_ticker);
				_ticker.AddComponent<MuteMusicTicker>();
			}
		}

		internal static void TickAll()
		{
			try
			{
				MusicController.Tick();
			}
			catch (Exception ex)
			{
				ManualLogSource log = Log;
				if (log != null)
				{
					log.LogWarning((object)("tick: " + ex.Message));
				}
			}
		}

		private void OnSceneLoaded(Scene scene, LoadSceneMode mode)
		{
			ManualLogSource log = Log;
			if (log != null)
			{
				log.LogInfo((object)("Scene loaded: " + ((Scene)(ref scene)).name));
			}
			MusicController.OnSceneChanged();
			EnsureTicker();
			TickAll();
		}
	}
	internal sealed class MuteMusicTicker : MonoBehaviour
	{
		private void Start()
		{
			((MonoBehaviour)this).InvokeRepeating("SlowTick", 0.5f, 2f);
		}

		private void SlowTick()
		{
			Plugin.TickAll();
		}
	}
}