Decompiled source of SoundpackLoader v0.2.6

SoundpackLoader.dll

Decompiled 4 months 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 System.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using Newtonsoft.Json;
using UnityEngine;
using UnityEngine.Networking;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: TargetFramework(".NETFramework,Version=v4.8.1", FrameworkDisplayName = ".NET Framework 4.8.1")]
[assembly: AssemblyCompany("SoundpackLoader")]
[assembly: AssemblyConfiguration("Debug")]
[assembly: AssemblyDescription("Loads custom soundpacks")]
[assembly: AssemblyFileVersion("0.2.6.0")]
[assembly: AssemblyInformationalVersion("0.2.6")]
[assembly: AssemblyProduct("SoundpackLoader")]
[assembly: AssemblyTitle("SoundpackLoader")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("0.2.6.0")]
[module: UnverifiableCode]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.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]
	[Microsoft.CodeAnalysis.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;
		}
	}
}
namespace SoundpackLoader
{
	internal static class AccessExtensions
	{
		public static T CallStaticMethod<T>(this Type type, string methodName, params object[] args)
		{
			MethodInfo method = type.GetMethod(methodName, BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
			if (method == null)
			{
				throw new MissingMemberException(type.Name, methodName);
			}
			return (T)method.Invoke(null, args);
		}
	}
	internal static class CollectionExtensions
	{
		public static T GetRandom<T>(this IEnumerable<T> vals)
		{
			return vals.OrderBy((T x) => Guid.NewGuid()).First();
		}

		public static IEnumerable<T> WhereNotNull<T>(this IEnumerable<T?> source) where T : class
		{
			return source.Where((T item) => item != null);
		}

		public static IEnumerable<T> WhereNotNull<T>(this IEnumerable<T?> source) where T : struct
		{
			return source.Where(delegate(T? item)
			{
				T? val2 = item;
				return val2.HasValue;
			}).Select(delegate(T? item)
			{
				T? val = item;
				return val.Value;
			});
		}
	}
	public static class VanillaExtensions
	{
		public static void ChangePack(this GameController self, Soundpack soundpack)
		{
			SoundpackManager.ChangePack(self, soundpack);
		}
	}
	[BepInPlugin("org.crispykevin.soundpackloader", "SoundpackLoader", "0.2.6")]
	internal class Plugin : BaseUnityPlugin
	{
		public static ManualLogSource Logger = null;

		public static SoundpackLoader Loader = null;

		public static ConfigEntry<KeyCode> CycleForwards = null;

		public static ConfigEntry<KeyCode> CycleBackwards = null;

		public static ConfigEntry<int> SelectedIdx = null;

		public static string CustomSoundpacksPath = Path.Combine(Paths.BepInExRootPath, "CustomSoundpacks");

		public Plugin()
		{
			Logger = ((BaseUnityPlugin)this).Logger;
		}

		private void Awake()
		{
			//IL_0062: Unknown result type (might be due to invalid IL or missing references)
			CycleForwards = ((BaseUnityPlugin)this).Config.Bind<KeyCode>("General", "CycleForwards", (KeyCode)281, (ConfigDescription)null);
			CycleBackwards = ((BaseUnityPlugin)this).Config.Bind<KeyCode>("General", "CycleBackwards", (KeyCode)280, (ConfigDescription)null);
			SelectedIdx = ((BaseUnityPlugin)this).Config.Bind<int>("General", "Soundpack Index", 0, (ConfigDescription)null);
			new Harmony("org.crispykevin.soundpackloader").PatchAll();
			Logger.LogInfo((object)"Plugin org.crispykevin.soundpackloader v0.2.6 is loaded!");
		}

		private void Start()
		{
			Loader = ((Component)this).gameObject.AddComponent<SoundpackLoader>();
			LoadVanillaSoundpacks();
			LoadCustomSoundpacks();
			SoundpackManager.CurrentPack = SoundpackManager.soundpacks[0];
			SoundpackManager.SoundpackChanged += delegate(object _, SoundpackChangedEventArgs e)
			{
				int num = SoundpackManager.soundpacks.IndexOf(e.NewPack);
				if (num != -1)
				{
					SelectedIdx.Value = num;
				}
				Logger.LogInfo((object)$"{SelectedIdx.Value}. {e.NewPack}");
			};
		}

		private void LoadVanillaSoundpacks()
		{
			Logger.LogInfo((object)"Loading vanilla soundpacks...");
			foreach (KeyValuePair<string, SoundpackInfo> item in SoundpackManager.VANILLA_SOUNDPACK_INFO)
			{
				SoundpackManager.AddPack(new Soundpack
				{
					Name = item.Key,
					Namespace = "vanilla",
					VolumeModifier = item.Value.volume
				});
			}
		}

		private void LoadCustomSoundpacks()
		{
			Logger.LogInfo((object)"Loading custom soundpacks...");
			DirectoryInfo directoryInfo = new DirectoryInfo(CustomSoundpacksPath);
			if (!directoryInfo.Exists)
			{
				Directory.CreateDirectory(CustomSoundpacksPath);
			}
			if (!directoryInfo.Exists)
			{
				return;
			}
			IEnumerable<DirectoryInfo> enumerable = directoryInfo.EnumerateDirectories();
			foreach (DirectoryInfo item in enumerable)
			{
				((MonoBehaviour)this).StartCoroutine(Loader.LoadSoundpack(item));
			}
		}
	}
	[HarmonyPatch(typeof(GameController))]
	internal class GameControllerPatch
	{
		private static EventHandler<SoundpackChangedEventArgs>? OnSoundpackChanged;

		private static GameObject? TrombClipsHolder;

		private static IEnumerator EmptyIEnumerator()
		{
			yield break;
		}

		[HarmonyPrefix]
		[HarmonyPatch("loadSoundBundleResources")]
		private static bool PatchOutSoundBundleResources(GameController __instance, ref IEnumerator __result)
		{
			if (!SoundpackManager.CurrentPack.IsVanilla)
			{
				__result = EmptyIEnumerator();
				__instance.fixAudioMixerStuff();
				return false;
			}
			return true;
		}

		[HarmonyPostfix]
		[HarmonyPatch("Start")]
		private static void AfterStart(GameController __instance)
		{
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: Expected O, but got Unknown
			GameController __instance2 = __instance;
			OnSoundpackChanged = delegate(object _, SoundpackChangedEventArgs e)
			{
				SoundpackManager.ChangePack(__instance2, e.NewPack);
			};
			SoundpackManager.SoundpackChanged += OnSoundpackChanged;
			TrombClipsHolder = new GameObject();
			__instance2.trombclips = TrombClipsHolder.AddComponent<AudioClipsTromb>();
			SoundpackManager.ChangePack(__instance2, SoundpackManager.CurrentPack);
		}

		[HarmonyPostfix]
		[HarmonyPatch("unloadBundles")]
		private static void AfterUnloadBundles(GameController __instance)
		{
			Plugin.Logger.LogInfo((object)"AfterUnloadBundles");
			SoundpackManager.SoundpackChanged -= OnSoundpackChanged;
			OnSoundpackChanged = null;
			Object.Destroy((Object)(object)TrombClipsHolder);
			TrombClipsHolder = null;
		}
	}
	[HarmonyPatch(typeof(CharSelectController_new))]
	internal class CharSelectControllerPatch
	{
		private static GameObject soundpackTextHolder;

		private static Text soundpackText;

		private static int soundpackIndex;

		[HarmonyPrefix]
		[HarmonyPatch("Start")]
		private static void BeforeStart()
		{
			soundpackIndex = Plugin.SelectedIdx.Value;
		}

		[HarmonyPostfix]
		[HarmonyPatch("Start")]
		private static void AfterStart(CharSelectController_new __instance)
		{
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f4: Unknown result type (might be due to invalid IL or missing references)
			//IL_0113: Unknown result type (might be due to invalid IL or missing references)
			//IL_0137: Unknown result type (might be due to invalid IL or missing references)
			Plugin.Logger.LogInfo((object)"AfterStart");
			__instance.chooseSoundPack(soundpackIndex);
			GameObject gameObject = __instance.all_sfx_buttons[0].img_text.gameObject;
			soundpackTextHolder = Object.Instantiate<GameObject>(gameObject, Vector3.zero, Quaternion.identity, GameObject.Find("Canvas").transform);
			soundpackTextHolder.SetActive(true);
			soundpackText = soundpackTextHolder.GetComponent<Text>();
			string name = SoundpackManager.CurrentPack.Name;
			soundpackText.text = name;
			((Component)((Component)soundpackText).transform.GetChild(0)).GetComponent<Text>().text = name;
			((Graphic)soundpackText).rectTransform.anchorMin = new Vector2(0.7f, 1f);
			((Graphic)soundpackText).rectTransform.anchorMax = new Vector2(1f, 1f);
			((Graphic)soundpackText).rectTransform.offsetMin = new Vector2(0f, -75f);
			((Graphic)soundpackText).rectTransform.offsetMax = new Vector2(0f, -75f);
			((Transform)((Graphic)soundpackText).rectTransform).localScale = new Vector3(0.6f, 0.6f, 1f);
			soundpackText.alignment = (TextAnchor)7;
			SoundpackManager.SoundpackChanged += OnSoundpackChanged;
		}

		private static void OnSoundpackChanged(object? sender, SoundpackChangedEventArgs e)
		{
			soundpackText.text = e.NewPack.Name;
			((Component)((Component)soundpackText).transform.GetChild(0)).GetComponent<Text>().text = e.NewPack.Name;
		}

		[HarmonyPostfix]
		[HarmonyPatch("Update")]
		private static void Update(CharSelectController_new __instance)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0061: Unknown result type (might be due to invalid IL or missing references)
			if (Input.GetKeyDown(Plugin.CycleForwards.Value))
			{
				ConfigEntry<int> selectedIdx = Plugin.SelectedIdx;
				int num2 = (selectedIdx.Value += 1);
				if (num2 >= SoundpackManager.soundpacks.Count)
				{
					Plugin.SelectedIdx.Value = 0;
				}
				__instance.chooseSoundPack(Plugin.SelectedIdx.Value);
			}
			if (Input.GetKeyDown(Plugin.CycleBackwards.Value))
			{
				ConfigEntry<int> selectedIdx2 = Plugin.SelectedIdx;
				int num2 = (selectedIdx2.Value -= 1);
				if (num2 < 0)
				{
					Plugin.SelectedIdx.Value = SoundpackManager.soundpacks.Count - 1;
				}
				__instance.chooseSoundPack(Plugin.SelectedIdx.Value);
			}
		}

		[HarmonyPostfix]
		[HarmonyPatch("loadNextScene")]
		private static void OnLeaveSelectScreen(CharSelectController_new __instance)
		{
			Plugin.Logger.LogInfo((object)"Cleaning up char select screen");
			soundpackTextHolder.SetActive(false);
			Object.Destroy((Object)(object)soundpackTextHolder);
			SoundpackManager.SoundpackChanged -= OnSoundpackChanged;
		}

		[HarmonyPrefix]
		[HarmonyPatch("chooseSoundPack")]
		private static bool BeforeChooseSoundPack(CharSelectController_new __instance, int sfx_choice)
		{
			SoundpackManager.CurrentPack = SoundpackManager.soundpacks[sfx_choice];
			for (int i = 0; i < __instance.all_sfx_buttons.Length; i++)
			{
				if (i != sfx_choice)
				{
					__instance.all_sfx_buttons[i].deselectBtn();
				}
			}
			return sfx_choice < __instance.all_sfx_buttons.Length;
		}
	}
	public class Soundpack
	{
		public string Name { get; init; } = "Custom Soundpack";


		public string Namespace { get; init; } = "unknown";


		public float VolumeModifier { get; init; } = 1f;


		public DirectoryInfo Directory { get; init; } = null;


		public AudioClip[] Notes { get; init; } = (AudioClip[])(object)new AudioClip[15];


		public bool IsVanilla => Namespace == "vanilla";

		public string QualifiedName => Namespace + ":" + Name;

		internal Soundpack()
		{
		}

		public override string ToString()
		{
			return QualifiedName;
		}
	}
	internal record SoundpackInfo(int order, float volume);
	internal class SoundpackJsonMetadata
	{
		public int SoundpackFormatRevision = -1;

		public string Name { get; set; } = "Custom Soundpack";


		public string Namespace { get; set; } = "unknown";


		public float VolumeModifier { get; set; } = 1f;

	}
	public class SoundpackChangedEventArgs : EventArgs
	{
		public Soundpack NewPack { get; }

		public Soundpack OldPack { get; }

		internal SoundpackChangedEventArgs(Soundpack newPack, Soundpack oldPack)
		{
			NewPack = newPack;
			OldPack = oldPack;
		}
	}
	public class SoundpackLoader : MonoBehaviour
	{
		public IEnumerator LoadSoundpack(DirectoryInfo dir)
		{
			FileInfo jsonFile = dir.GetFiles("*.json").FirstOrDefault();
			if (jsonFile == null)
			{
				Plugin.Logger.LogWarning((object)("No JSON file in soundpack directory: " + dir.FullName));
				yield break;
			}
			SoundpackJsonMetadata metadata = JsonUtil.ReadFile<SoundpackJsonMetadata>(jsonFile);
			if (metadata == null)
			{
				Plugin.Logger.LogWarning((object)("Failed to read JSON file: " + jsonFile.FullName));
				yield break;
			}
			if (metadata.SoundpackFormatRevision == -1)
			{
				Plugin.Logger.LogWarning((object)("Missing SoundpackFormatRevision number in soundpack " + metadata.Namespace + ":" + metadata.Name + "! (Located in " + dir.Name + ")"));
			}
			Soundpack soundpack = new Soundpack
			{
				Name = metadata.Name,
				Namespace = metadata.Namespace,
				VolumeModifier = metadata.VolumeModifier,
				Directory = dir
			};
			((MonoBehaviour)this).StartCoroutine(LoadNoteAudioFilesCoroutine(soundpack));
			SoundpackManager.AddPack(soundpack);
			yield return null;
		}

		private IEnumerator GetAudioClipCoroutine(FileInfo fileInfo, Action<AudioClip> onSuccess, Action<string> onError)
		{
			Dictionary<string, AudioType> EXTENSION_TO_AUD_TYPE = new Dictionary<string, AudioType>
			{
				["wav"] = (AudioType)20,
				["mp3"] = (AudioType)13,
				["ogg"] = (AudioType)14
			};
			AudioType audType = CollectionExtensions.GetValueOrDefault<string, AudioType>((IReadOnlyDictionary<string, AudioType>)EXTENSION_TO_AUD_TYPE, fileInfo.Extension.ToLower(), (AudioType)0);
			string uri = "file://" + fileInfo.FullName;
			UnityWebRequest www = UnityWebRequestMultimedia.GetAudioClip(uri, audType);
			try
			{
				((DownloadHandlerAudioClip)www.downloadHandler).streamAudio = false;
				yield return www.SendWebRequest();
				if (www.error != null)
				{
					onError(www.error);
					yield break;
				}
				AudioClip myClip = DownloadHandlerAudioClip.GetContent(www);
				onSuccess(myClip);
			}
			finally
			{
				((IDisposable)www)?.Dispose();
			}
		}

		private IEnumerator LoadNoteAudioFilesCoroutine(Soundpack soundpack)
		{
			Soundpack soundpack2 = soundpack;
			string[] NOTE_NAMES = new string[15]
			{
				"C1", "D1", "E1", "F1", "G1", "A1", "B1", "C2", "D2", "E2",
				"F2", "G2", "A2", "B2", "C3"
			};
			int numLoadedClips = 0;
			bool isWaiting = false;
			Plugin.Logger.LogInfo((object)soundpack2.QualifiedName);
			int i = 0;
			while (i < NOTE_NAMES.Length)
			{
				if (isWaiting)
				{
					yield return null;
				}
				string noteName = NOTE_NAMES[i];
				FileInfo noteFile = soundpack2.Directory.GetFiles("*" + noteName + ".*").FirstOrDefault();
				if (noteFile == null)
				{
					string err2 = "Audio file not found for note " + noteName + " in soundpack " + soundpack2.QualifiedName;
					Plugin.Logger.LogWarning((object)err2);
					break;
				}
				int idx = i;
				((MonoBehaviour)this).StartCoroutine(GetAudioClipCoroutine(noteFile, delegate(AudioClip clip)
				{
					soundpack2.Notes[idx] = clip;
					int num2 = NOTE_NAMES.Length;
					int num3 = numLoadedClips + 1;
					numLoadedClips = num3;
					if (num2 == num3)
					{
						Plugin.Logger.LogInfo((object)("Successfully loaded soundpack: " + soundpack2.QualifiedName));
					}
					isWaiting = false;
				}, delegate(string err)
				{
					string text = "Error loading note " + noteName + " in soundpack " + soundpack2.QualifiedName + ": " + err;
					Plugin.Logger.LogWarning((object)text);
				}));
				isWaiting = true;
				yield return null;
				int num = i + 1;
				i = num;
			}
		}
	}
	public class SoundpackManager
	{
		internal static List<Soundpack> soundpacks = new List<Soundpack>();

		internal static readonly Dictionary<string, SoundpackInfo> VANILLA_SOUNDPACK_INFO = new Dictionary<string, SoundpackInfo>
		{
			["default"] = new SoundpackInfo(0, 1f),
			["bass"] = new SoundpackInfo(1, 0.72f),
			["muted"] = new SoundpackInfo(2, 0.34f),
			["eightbit"] = new SoundpackInfo(3, 0.25f),
			["club"] = new SoundpackInfo(4, 0.25f),
			["fart"] = new SoundpackInfo(5, 0.75f)
		};

		internal static Soundpack _currentPack = new Soundpack();

		public static Soundpack CurrentPack
		{
			get
			{
				return _currentPack;
			}
			set
			{
				Soundpack currentPack = _currentPack;
				_currentPack = value;
				if (currentPack != _currentPack)
				{
					OnSoundpackChanged(_currentPack, currentPack);
				}
			}
		}

		public static event EventHandler<SoundpackChangedEventArgs>? SoundpackChanged;

		public static IEnumerable<Soundpack> GetAllPacks()
		{
			return soundpacks;
		}

		public static IEnumerable<Soundpack> GetVanillaPacks()
		{
			return from p in GetAllPacks()
				where p.IsVanilla
				select p;
		}

		public static IEnumerable<Soundpack> GetCustomPacks()
		{
			return from p in GetAllPacks()
				where !p.IsVanilla
				select p;
		}

		public static Soundpack? FindPack(string nmspace, string name)
		{
			string nmspace2 = nmspace;
			string name2 = name;
			return soundpacks.FirstOrDefault((Soundpack s) => s.Namespace == nmspace2 && s.Name == name2);
		}

		public static void AddPack(Soundpack pack)
		{
			soundpacks.Add(pack);
		}

		public static bool RemovePack(Soundpack pack)
		{
			return soundpacks.Remove(pack);
		}

		public static Soundpack? RemovePack(string nmspace, string name)
		{
			string nmspace2 = nmspace;
			string name2 = name;
			int num = soundpacks.FindIndex((Soundpack p) => p.Namespace == nmspace2 && p.Name == name2);
			if (num != -1)
			{
				Soundpack result = soundpacks[num];
				soundpacks.RemoveAt(num);
				return result;
			}
			return null;
		}

		public static Soundpack ClonePack(Soundpack pack)
		{
			Soundpack soundpack = new Soundpack
			{
				Name = pack.Name,
				Namespace = pack.Namespace,
				Directory = pack.Directory,
				VolumeModifier = pack.VolumeModifier
			};
			float[] buf = new float[pack.Notes.Max((AudioClip n) => n.channels * n.samples)];
			for (int i = 0; i < pack.Notes.Length; i++)
			{
				soundpack.Notes[i] = AudioUtil.CloneAudioClip(pack.Notes[i], buf);
			}
			return soundpack;
		}

		public static void ChangePack(GameController gc, Soundpack soundpack)
		{
			CurrentPack = soundpack;
			if (!soundpack.IsVanilla)
			{
				gc.trombclips.tclips = soundpack.Notes;
				float trombvol_current = (gc.currentnotesound.volume = soundpack.VolumeModifier);
				gc.trombvol_default = (gc.trombvol_current = trombvol_current);
			}
		}

		internal static void OnSoundpackChanged(Soundpack newPack, Soundpack oldPack)
		{
			SoundpackManager.SoundpackChanged?.Invoke(null, new SoundpackChangedEventArgs(CurrentPack, oldPack));
		}
	}
	internal class AudioUtil
	{
		public static AudioClip CloneAudioClip(AudioClip clip, float[]? buf = null)
		{
			AudioClip val = AudioClip.Create(((Object)clip).name, clip.samples, clip.channels, clip.frequency, false);
			if (buf == null || buf.Length < clip.samples * clip.channels)
			{
				buf = new float[clip.samples * clip.channels];
			}
			object[] array = new object[4] { clip, buf, clip.samples, 0 };
			typeof(AudioClip).CallStaticMethod<bool>("GetData", array);
			array[0] = val;
			typeof(AudioClip).CallStaticMethod<bool>("SetData", array);
			return val;
		}
	}
	internal class DebugUtil
	{
		public static void Dump(object? obj, LogLevel level = 16, string objExpression = "<unknown>")
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Expected O, but got Unknown
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			JsonSerializerSettings val = new JsonSerializerSettings();
			val.Formatting = (Formatting)1;
			val.MaxDepth = 6;
			val.ReferenceLoopHandling = (ReferenceLoopHandling)1;
			string text = JsonConvert.SerializeObject(obj, val);
			Plugin.Logger.Log(level, (object)(objExpression + " = " + text));
		}
	}
	internal class JsonUtil
	{
		public static T? ReadFile<T>(FileInfo file) where T : class
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Expected O, but got Unknown
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_000d: Expected O, but got Unknown
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Expected O, but got Unknown
			JsonSerializerSettings val = new JsonSerializerSettings();
			JsonSerializer val2 = new JsonSerializer();
			using StreamReader streamReader = new StreamReader(file.FullName);
			JsonTextReader val3 = new JsonTextReader((TextReader)streamReader);
			try
			{
				return val2.Deserialize<T>((JsonReader)(object)val3);
			}
			catch (Exception obj)
			{
				DebugUtil.Dump(obj, (LogLevel)4);
				return null;
			}
			finally
			{
				((IDisposable)val3)?.Dispose();
			}
		}

		public static T? ReadFile<T>(string path) where T : class
		{
			return ReadFile<T>(new FileInfo(path));
		}
	}
	public static class PluginInfo
	{
		public const string PLUGIN_GUID = "org.crispykevin.soundpackloader";

		public const string PLUGIN_NAME = "SoundpackLoader";

		public const string PLUGIN_VERSION = "0.2.6";
	}
}
namespace System.Runtime.CompilerServices
{
	[AttributeUsage(AttributeTargets.Parameter, AllowMultiple = false, Inherited = false)]
	internal sealed class CallerArgumentExpressionAttribute : Attribute
	{
		public string ParameterName { get; }

		public CallerArgumentExpressionAttribute(string parameterName)
		{
			ParameterName = parameterName;
		}
	}
	internal static class IsExternalInit
	{
	}
}