Decompiled source of MusicCenterMusicReplacer v0.1.0

BepInEx\plugins\MusicCenterMusicReplacer\MusicCenterMusicReplacer.dll

Decompiled 13 hours ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
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.Networking;

[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("MusicCenterMusicReplacer")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("0.1.0.0")]
[assembly: AssemblyInformationalVersion("0.1.0")]
[assembly: AssemblyProduct("MusicCenterMusicReplacer")]
[assembly: AssemblyTitle("MusicCenterMusicReplacer")]
[assembly: AssemblyVersion("0.1.0.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 MusicCenterMusicReplacer
{
	internal static class AudioFileLoader
	{
		internal static IEnumerator LoadFromPluginFolder(string fileName, Action<AudioClip?> onLoaded)
		{
			string directoryName = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
			if (string.IsNullOrWhiteSpace(directoryName))
			{
				Plugin.Log.LogError((object)"Could not determine the plugin directory.");
				onLoaded(null);
				yield break;
			}
			string fullPath = Path.Combine(directoryName, fileName);
			if (!File.Exists(fullPath))
			{
				Plugin.Log.LogWarning((object)("Music file not found: " + fullPath));
				Plugin.Log.LogWarning((object)"Place boombox.ogg, boombox.wav or boombox.mp3 next to the DLL.");
				onLoaded(null);
				yield break;
			}
			AudioType audioType = GetAudioType(Path.GetExtension(fullPath));
			if ((int)audioType == 0)
			{
				Plugin.Log.LogError((object)("Unsupported audio extension: " + Path.GetExtension(fullPath)));
				onLoaded(null);
				yield break;
			}
			string absoluteUri = new Uri(fullPath).AbsoluteUri;
			UnityWebRequest request = UnityWebRequestMultimedia.GetAudioClip(absoluteUri, audioType);
			try
			{
				yield return request.SendWebRequest();
				if ((int)request.result != 1)
				{
					Plugin.Log.LogError((object)("Could not load music: " + request.error));
					onLoaded(null);
					yield break;
				}
				AudioClip content = DownloadHandlerAudioClip.GetContent(request);
				if ((Object)(object)content == (Object)null)
				{
					Plugin.Log.LogError((object)"Unity returned an empty AudioClip.");
					onLoaded(null);
				}
				else
				{
					((Object)content).name = "MusicCenter_" + Path.GetFileNameWithoutExtension(fullPath);
					Plugin.Log.LogInfo((object)$"Music loaded: {Path.GetFileName(fullPath)} ({content.length:0.00}s).");
					onLoaded(content);
				}
			}
			finally
			{
				((IDisposable)request)?.Dispose();
			}
		}

		private static AudioType GetAudioType(string extension)
		{
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			//IL_0037: Unknown result type (might be due to invalid IL or missing references)
			//IL_003c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0040: Unknown result type (might be due to invalid IL or missing references)
			return (AudioType)(extension.ToLowerInvariant() switch
			{
				".ogg" => 14, 
				".wav" => 20, 
				".mp3" => 13, 
				_ => 0, 
			});
		}
	}
	[BepInPlugin("com.artem.musiccentermusicreplacer", "Music Center Music Replacer", "0.1.0")]
	[BepInProcess("REPO.exe")]
	public sealed class Plugin : BaseUnityPlugin
	{
		public const string PluginGuid = "com.artem.musiccentermusicreplacer";

		public const string PluginName = "Music Center Music Replacer";

		public const string PluginVersion = "0.1.0";

		private static readonly HashSet<Sound> BoomboxSounds = new HashSet<Sound>();

		private ConfigEntry<bool> _enabled;

		private ConfigEntry<string> _audioFileName;

		private ConfigEntry<bool> _forceLoop;

		private AudioClip? _replacementClip;

		private Harmony? _harmony;

		internal static Plugin? Instance { get; private set; }

		internal static ManualLogSource Log { get; private set; } = null;

		private void Awake()
		{
			//IL_007e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0088: Expected O, but got Unknown
			Instance = this;
			Log = ((BaseUnityPlugin)this).Logger;
			_enabled = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "Enabled", true, "Enables replacement of the Museum Boombox / music center track.");
			_audioFileName = ((BaseUnityPlugin)this).Config.Bind<string>("Audio", "AudioFileName", "boombox.ogg", "Audio file placed next to the DLL. Supported: .ogg, .wav and .mp3.");
			_forceLoop = ((BaseUnityPlugin)this).Config.Bind<bool>("Playback", "ForceLoop", true, "Loops the custom track while the boombox is being held.");
			_harmony = new Harmony("com.artem.musiccentermusicreplacer");
			_harmony.PatchAll();
			((MonoBehaviour)this).StartCoroutine(AudioFileLoader.LoadFromPluginFolder(_audioFileName.Value, OnReplacementLoaded));
			Log.LogInfo((object)"Music Center Music Replacer v0.1.0 loaded.");
		}

		private void OnDestroy()
		{
			Harmony? harmony = _harmony;
			if (harmony != null)
			{
				harmony.UnpatchSelf();
			}
			BoomboxSounds.Clear();
			Instance = null;
		}

		private void OnReplacementLoaded(AudioClip? clip)
		{
			_replacementClip = clip;
			if (!((Object)(object)clip == (Object)null))
			{
				ValuableBoombox[] array = Resources.FindObjectsOfTypeAll<ValuableBoombox>();
				for (int i = 0; i < array.Length; i++)
				{
					RegisterBoombox(array[i]);
				}
			}
		}

		internal static void RegisterBoombox(ValuableBoombox? boombox)
		{
			Plugin instance = Instance;
			if (!((Object)(object)instance == (Object)null) && !((Object)(object)boombox == (Object)null) && boombox.soundBoomboxMusic != null)
			{
				Sound soundBoomboxMusic = boombox.soundBoomboxMusic;
				BoomboxSounds.Add(soundBoomboxMusic);
				instance.ApplyReplacement(soundBoomboxMusic, restartIfPlaying: true);
			}
		}

		private void ApplyReplacement(Sound sound, bool restartIfPlaying)
		{
			AudioClip replacementClip = _replacementClip;
			if (!_enabled.Value || (Object)(object)replacementClip == (Object)null)
			{
				return;
			}
			AudioSource source = sound.Source;
			bool flag = (Object)(object)source != (Object)null && source.isPlaying;
			sound.Sounds = (AudioClip[])(object)new AudioClip[1] { replacementClip };
			if ((Object)(object)source != (Object)null)
			{
				source.loop = _forceLoop.Value;
				if (restartIfPlaying && flag)
				{
					source.Stop();
					source.clip = replacementClip;
					source.time = 0f;
					source.Play();
					Log.LogInfo((object)"[MUSIC START] Music center restarted from 0:00.");
				}
			}
		}

		internal static void BeforeSoundPlay(Sound? sound)
		{
			Plugin instance = Instance;
			if ((Object)(object)instance == (Object)null || sound == null || !BoomboxSounds.Contains(sound))
			{
				return;
			}
			AudioClip replacementClip = instance._replacementClip;
			if (instance._enabled.Value && !((Object)(object)replacementClip == (Object)null))
			{
				sound.Sounds = (AudioClip[])(object)new AudioClip[1] { replacementClip };
				AudioSource source = sound.Source;
				if ((Object)(object)source != (Object)null)
				{
					source.Stop();
					source.clip = replacementClip;
					source.time = 0f;
					source.loop = instance._forceLoop.Value;
				}
			}
		}

		internal static void AfterSoundPlay(Sound? sound)
		{
			Plugin instance = Instance;
			if ((Object)(object)instance == (Object)null || sound == null || !BoomboxSounds.Contains(sound))
			{
				return;
			}
			AudioClip replacementClip = instance._replacementClip;
			if (!instance._enabled.Value || (Object)(object)replacementClip == (Object)null)
			{
				return;
			}
			AudioSource source = sound.Source;
			if (!((Object)(object)source == (Object)null))
			{
				source.clip = replacementClip;
				source.loop = instance._forceLoop.Value;
				source.time = 0f;
				if (!source.isPlaying)
				{
					source.Play();
				}
				Log.LogInfo((object)"[MUSIC START] Music center started from 0:00.");
			}
		}
	}
	[HarmonyPatch(typeof(ValuableBoombox), "Start")]
	internal static class ValuableBoomboxStartPatch
	{
		private static void Postfix(ValuableBoombox __instance)
		{
			Plugin.RegisterBoombox(__instance);
		}
	}
	[HarmonyPatch]
	internal static class BoomboxSoundPlayPatch
	{
		private static IEnumerable<MethodBase> TargetMethods()
		{
			return from method in AccessTools.GetDeclaredMethods(typeof(Sound))
				where method.Name == "Play"
				select method;
		}

		private static void Prefix(Sound __instance)
		{
			Plugin.BeforeSoundPlay(__instance);
		}

		private static void Postfix(Sound __instance)
		{
			Plugin.AfterSoundPlay(__instance);
		}
	}
}