Decompiled source of MusicRando v0.1.2

MusicRando.dll

Decompiled 3 days ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
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 GlobalEnums;
using Md.AudioManager;
using Md.GameManager;
using Md.QuitToMenu;
using Microsoft.CodeAnalysis;
using MonoDetour;
using MonoDetour.Cil;
using MonoDetour.DetourTypes;
using MonoDetour.HookGen;
using MonoDetour.Reflection.Unspeakable;
using MonoMod.Utils;
using MusicRando.Cache;
using MusicRando.MusicSelectionStrategies;
using Newtonsoft.Json;
using Silksong.AssetHelper.Core;
using Silksong.AssetHelper.ManagedAssets;
using Silksong.ModMenu.Plugin;
using UnityEngine;
using UnityEngine.ResourceManagement.ResourceLocations;

[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("MusicRando")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("0.1.2.0")]
[assembly: AssemblyInformationalVersion("0.1.2+6beca92a7da41451cc7a5ba55100ed84813d1b59")]
[assembly: AssemblyProduct("MusicRando")]
[assembly: AssemblyTitle("MusicRando")]
[assembly: AssemblyMetadata("RepositoryUrl", "https://github.com/flibber-hk/Silksong.MusicRando")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("0.1.2.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
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;
		}
	}
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.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 System.Runtime.Versioning
{
	[AttributeUsage(AttributeTargets.Assembly | AttributeTargets.Module | AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Enum | AttributeTargets.Constructor | AttributeTargets.Method | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Interface | AttributeTargets.Delegate, Inherited = false)]
	[ExcludeFromCodeCoverage]
	internal sealed class RequiresPreviewFeaturesAttribute : Attribute
	{
		public string? Message { get; }

		public string? Url { get; set; }

		public RequiresPreviewFeaturesAttribute()
		{
		}

		public RequiresPreviewFeaturesAttribute(string? message)
		{
			Message = message;
		}
	}
}
namespace System.Runtime.CompilerServices
{
	[AttributeUsage(AttributeTargets.Parameter, AllowMultiple = false, Inherited = false)]
	[ExcludeFromCodeCoverage]
	internal sealed class CallerArgumentExpressionAttribute : Attribute
	{
		public string ParameterName { get; }

		public CallerArgumentExpressionAttribute(string parameterName)
		{
			ParameterName = parameterName;
		}
	}
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Interface, Inherited = false)]
	[ExcludeFromCodeCoverage]
	internal sealed class CollectionBuilderAttribute : Attribute
	{
		public Type BuilderType { get; }

		public string MethodName { get; }

		public CollectionBuilderAttribute(Type builderType, string methodName)
		{
			BuilderType = builderType;
			MethodName = methodName;
		}
	}
	[AttributeUsage(AttributeTargets.All, AllowMultiple = true, Inherited = false)]
	[ExcludeFromCodeCoverage]
	internal sealed class CompilerFeatureRequiredAttribute : Attribute
	{
		public const string RefStructs = "RefStructs";

		public const string RequiredMembers = "RequiredMembers";

		public string FeatureName { get; }

		public bool IsOptional { get; set; }

		public CompilerFeatureRequiredAttribute(string featureName)
		{
			FeatureName = featureName;
		}
	}
	[AttributeUsage(AttributeTargets.Parameter, AllowMultiple = false, Inherited = false)]
	[ExcludeFromCodeCoverage]
	internal sealed class InterpolatedStringHandlerArgumentAttribute : Attribute
	{
		public string[] Arguments { get; }

		public InterpolatedStringHandlerArgumentAttribute(string argument)
		{
			Arguments = new string[1] { argument };
		}

		public InterpolatedStringHandlerArgumentAttribute(params string[] arguments)
		{
			Arguments = arguments;
		}
	}
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct, AllowMultiple = false, Inherited = false)]
	[ExcludeFromCodeCoverage]
	internal sealed class InterpolatedStringHandlerAttribute : Attribute
	{
	}
	[EditorBrowsable(EditorBrowsableState.Never)]
	[ExcludeFromCodeCoverage]
	internal static class IsExternalInit
	{
	}
	[AttributeUsage(AttributeTargets.Method, Inherited = false)]
	[ExcludeFromCodeCoverage]
	internal sealed class ModuleInitializerAttribute : Attribute
	{
	}
	[AttributeUsage(AttributeTargets.Constructor | AttributeTargets.Method | AttributeTargets.Property, AllowMultiple = false, Inherited = false)]
	[ExcludeFromCodeCoverage]
	internal sealed class OverloadResolutionPriorityAttribute : Attribute
	{
		public int Priority { get; }

		public OverloadResolutionPriorityAttribute(int priority)
		{
			Priority = priority;
		}
	}
	[AttributeUsage(AttributeTargets.Parameter, Inherited = true, AllowMultiple = false)]
	[ExcludeFromCodeCoverage]
	internal sealed class ParamCollectionAttribute : Attribute
	{
	}
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Property | AttributeTargets.Field, AllowMultiple = false, Inherited = false)]
	[ExcludeFromCodeCoverage]
	internal sealed class RequiredMemberAttribute : Attribute
	{
	}
	[AttributeUsage(AttributeTargets.Parameter, Inherited = false)]
	[EditorBrowsable(EditorBrowsableState.Never)]
	[ExcludeFromCodeCoverage]
	internal sealed class RequiresLocationAttribute : Attribute
	{
	}
	[AttributeUsage(AttributeTargets.Module | AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Constructor | AttributeTargets.Method | AttributeTargets.Property | AttributeTargets.Event | AttributeTargets.Interface, Inherited = false)]
	[ExcludeFromCodeCoverage]
	internal sealed class SkipLocalsInitAttribute : Attribute
	{
	}
}
namespace System.Diagnostics.CodeAnalysis
{
	[AttributeUsage(AttributeTargets.Parameter, Inherited = false)]
	[ExcludeFromCodeCoverage]
	internal sealed class ConstantExpectedAttribute : Attribute
	{
		public object? Min { get; set; }

		public object? Max { get; set; }
	}
	[AttributeUsage(AttributeTargets.Assembly | AttributeTargets.Module | AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Enum | AttributeTargets.Constructor | AttributeTargets.Method | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Interface | AttributeTargets.Delegate, Inherited = false)]
	[ExcludeFromCodeCoverage]
	internal sealed class ExperimentalAttribute : Attribute
	{
		public string DiagnosticId { get; }

		public string? UrlFormat { get; set; }

		public ExperimentalAttribute(string diagnosticId)
		{
			DiagnosticId = diagnosticId;
		}
	}
	[AttributeUsage(AttributeTargets.Method | AttributeTargets.Property, Inherited = false, AllowMultiple = true)]
	[ExcludeFromCodeCoverage]
	internal sealed class MemberNotNullAttribute : Attribute
	{
		public string[] Members { get; }

		public MemberNotNullAttribute(string member)
		{
			Members = new string[1] { member };
		}

		public MemberNotNullAttribute(params string[] members)
		{
			Members = members;
		}
	}
	[AttributeUsage(AttributeTargets.Method | AttributeTargets.Property, Inherited = false, AllowMultiple = true)]
	[ExcludeFromCodeCoverage]
	internal sealed class MemberNotNullWhenAttribute : Attribute
	{
		public bool ReturnValue { get; }

		public string[] Members { get; }

		public MemberNotNullWhenAttribute(bool returnValue, string member)
		{
			ReturnValue = returnValue;
			Members = new string[1] { member };
		}

		public MemberNotNullWhenAttribute(bool returnValue, params string[] members)
		{
			ReturnValue = returnValue;
			Members = members;
		}
	}
	[AttributeUsage(AttributeTargets.Constructor, AllowMultiple = false, Inherited = false)]
	[ExcludeFromCodeCoverage]
	internal sealed class SetsRequiredMembersAttribute : Attribute
	{
	}
	[AttributeUsage(AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Parameter, AllowMultiple = false, Inherited = false)]
	[ExcludeFromCodeCoverage]
	internal sealed class StringSyntaxAttribute : Attribute
	{
		public const string CompositeFormat = "CompositeFormat";

		public const string DateOnlyFormat = "DateOnlyFormat";

		public const string DateTimeFormat = "DateTimeFormat";

		public const string EnumFormat = "EnumFormat";

		public const string GuidFormat = "GuidFormat";

		public const string Json = "Json";

		public const string NumericFormat = "NumericFormat";

		public const string Regex = "Regex";

		public const string TimeOnlyFormat = "TimeOnlyFormat";

		public const string TimeSpanFormat = "TimeSpanFormat";

		public const string Uri = "Uri";

		public const string Xml = "Xml";

		public string Syntax { get; }

		public object?[] Arguments { get; }

		public StringSyntaxAttribute(string syntax)
		{
			Syntax = syntax;
			Arguments = new object[0];
		}

		public StringSyntaxAttribute(string syntax, params object?[] arguments)
		{
			Syntax = syntax;
			Arguments = arguments;
		}
	}
	[AttributeUsage(AttributeTargets.Method | AttributeTargets.Property | AttributeTargets.Parameter, AllowMultiple = false, Inherited = false)]
	[ExcludeFromCodeCoverage]
	internal sealed class UnscopedRefAttribute : Attribute
	{
	}
}
namespace Md.AudioManager
{
	internal static class Start
	{
		public delegate void PrefixSignature(AudioManager self);

		public delegate void PostfixSignature(AudioManager self);

		public static MonoDetourHook Prefix(PrefixSignature hook, MonoDetourConfig? config = null, bool applyByDefault = true, MonoDetourManager? manager = null)
		{
			return (manager ?? DefaultMonoDetourManager.Instance).Hook<PrefixDetour>(Target(), (Delegate)hook, config, applyByDefault);
		}

		public static MonoDetourHook Postfix(PostfixSignature hook, MonoDetourConfig? config = null, bool applyByDefault = true, MonoDetourManager? manager = null)
		{
			return (manager ?? DefaultMonoDetourManager.Instance).Hook<PostfixDetour>(Target(), (Delegate)hook, config, applyByDefault);
		}

		public static MonoDetourHook ILHook(Manipulator manipulator, MonoDetourConfig? config = null, bool applyByDefault = true, MonoDetourManager? manager = null)
		{
			return (manager ?? DefaultMonoDetourManager.Instance).ILHook(Target(), manipulator, config, applyByDefault);
		}

		public static MethodBase Target()
		{
			return typeof(AudioManager).GetMethod("Start", (BindingFlags)(-1), null, Array.Empty<Type>(), null) ?? throw new MissingMethodException("AudioManager", "Start");
		}
	}
	internal static class ApplyMusicCue
	{
		public delegate void PrefixSignature(AudioManager self, ref MusicCue musicCue, ref float delayTime, ref float transitionTime, ref bool applySnapshot);

		public delegate void PostfixSignature(AudioManager self, ref MusicCue musicCue, ref float delayTime, ref float transitionTime, ref bool applySnapshot);

		public static MonoDetourHook Prefix(PrefixSignature hook, MonoDetourConfig? config = null, bool applyByDefault = true, MonoDetourManager? manager = null)
		{
			return (manager ?? DefaultMonoDetourManager.Instance).Hook<PrefixDetour>(Target(), (Delegate)hook, config, applyByDefault);
		}

		public static MonoDetourHook Postfix(PostfixSignature hook, MonoDetourConfig? config = null, bool applyByDefault = true, MonoDetourManager? manager = null)
		{
			return (manager ?? DefaultMonoDetourManager.Instance).Hook<PostfixDetour>(Target(), (Delegate)hook, config, applyByDefault);
		}

		public static MonoDetourHook ILHook(Manipulator manipulator, MonoDetourConfig? config = null, bool applyByDefault = true, MonoDetourManager? manager = null)
		{
			return (manager ?? DefaultMonoDetourManager.Instance).ILHook(Target(), manipulator, config, applyByDefault);
		}

		public static MethodBase Target()
		{
			return typeof(AudioManager).GetMethod("ApplyMusicCue", (BindingFlags)(-1), null, new Type[4]
			{
				typeof(MusicCue),
				typeof(float),
				typeof(float),
				typeof(bool)
			}, null) ?? throw new MissingMethodException("AudioManager", "ApplyMusicCue");
		}
	}
}
namespace Md.QuitToMenu
{
	internal static class Start
	{
		public delegate void PrefixSignature(QuitToMenu self);

		public delegate void PostfixSignature(QuitToMenu self, ref IEnumerator returnValue);

		public delegate void PrefixMoveNextSignature(SpeakableEnumerator<object, QuitToMenu> self);

		public delegate void PostfixMoveNextSignature(SpeakableEnumerator<object, QuitToMenu> self, ref bool continueEnumeration);

		public static MonoDetourHook Prefix(PrefixSignature hook, MonoDetourConfig? config = null, bool applyByDefault = true, MonoDetourManager? manager = null)
		{
			return (manager ?? DefaultMonoDetourManager.Instance).Hook<PrefixDetour>(Target(), (Delegate)hook, config, applyByDefault);
		}

		public static MonoDetourHook Postfix(PostfixSignature hook, MonoDetourConfig? config = null, bool applyByDefault = true, MonoDetourManager? manager = null)
		{
			return (manager ?? DefaultMonoDetourManager.Instance).Hook<PostfixDetour>(Target(), (Delegate)hook, config, applyByDefault);
		}

		public static MonoDetourHook ILHook(Manipulator manipulator, MonoDetourConfig? config = null, bool applyByDefault = true, MonoDetourManager? manager = null)
		{
			return (manager ?? DefaultMonoDetourManager.Instance).ILHook(Target(), manipulator, config, applyByDefault);
		}

		public static MonoDetourHook PrefixMoveNext(PrefixMoveNextSignature hook, MonoDetourConfig? config = null, bool applyByDefault = true, MonoDetourManager? manager = null)
		{
			return (manager ?? DefaultMonoDetourManager.Instance).Hook<PrefixDetour>((MethodBase)StateMachineTarget(), (Delegate)hook, config, applyByDefault);
		}

		public static MonoDetourHook PostfixMoveNext(PostfixMoveNextSignature hook, MonoDetourConfig? config = null, bool applyByDefault = true, MonoDetourManager? manager = null)
		{
			return (manager ?? DefaultMonoDetourManager.Instance).Hook<PostfixDetour>((MethodBase)StateMachineTarget(), (Delegate)hook, config, applyByDefault);
		}

		public static MonoDetourHook ILHookMoveNext(Manipulator manipulator, MonoDetourConfig? config = null, bool applyByDefault = true, MonoDetourManager? manager = null)
		{
			return (manager ?? DefaultMonoDetourManager.Instance).ILHook((MethodBase)StateMachineTarget(), manipulator, config, applyByDefault);
		}

		public static MethodBase Target()
		{
			return typeof(QuitToMenu).GetMethod("Start", (BindingFlags)(-1), null, Array.Empty<Type>(), null) ?? throw new MissingMethodException("QuitToMenu", "Start");
		}

		public static MethodInfo StateMachineTarget()
		{
			return Extensions.GetStateMachineTarget((MethodInfo)Target());
		}
	}
}
namespace Md.GameManager
{
	internal static class ContinueGame
	{
		public delegate void PrefixSignature(GameManager self);

		public delegate void PostfixSignature(GameManager self);

		public static MonoDetourHook Prefix(PrefixSignature hook, MonoDetourConfig? config = null, bool applyByDefault = true, MonoDetourManager? manager = null)
		{
			return (manager ?? DefaultMonoDetourManager.Instance).Hook<PrefixDetour>(Target(), (Delegate)hook, config, applyByDefault);
		}

		public static MonoDetourHook Postfix(PostfixSignature hook, MonoDetourConfig? config = null, bool applyByDefault = true, MonoDetourManager? manager = null)
		{
			return (manager ?? DefaultMonoDetourManager.Instance).Hook<PostfixDetour>(Target(), (Delegate)hook, config, applyByDefault);
		}

		public static MonoDetourHook ILHook(Manipulator manipulator, MonoDetourConfig? config = null, bool applyByDefault = true, MonoDetourManager? manager = null)
		{
			return (manager ?? DefaultMonoDetourManager.Instance).ILHook(Target(), manipulator, config, applyByDefault);
		}

		public static MethodBase Target()
		{
			return typeof(GameManager).GetMethod("ContinueGame", (BindingFlags)(-1), null, Array.Empty<Type>(), null) ?? throw new MissingMethodException("GameManager", "ContinueGame");
		}
	}
	internal static class StartNewGame
	{
		public delegate void PrefixSignature(GameManager self, ref bool permadeathMode, ref bool bossRushMode);

		public delegate void PostfixSignature(GameManager self, ref bool permadeathMode, ref bool bossRushMode);

		public static MonoDetourHook Prefix(PrefixSignature hook, MonoDetourConfig? config = null, bool applyByDefault = true, MonoDetourManager? manager = null)
		{
			return (manager ?? DefaultMonoDetourManager.Instance).Hook<PrefixDetour>(Target(), (Delegate)hook, config, applyByDefault);
		}

		public static MonoDetourHook Postfix(PostfixSignature hook, MonoDetourConfig? config = null, bool applyByDefault = true, MonoDetourManager? manager = null)
		{
			return (manager ?? DefaultMonoDetourManager.Instance).Hook<PostfixDetour>(Target(), (Delegate)hook, config, applyByDefault);
		}

		public static MonoDetourHook ILHook(Manipulator manipulator, MonoDetourConfig? config = null, bool applyByDefault = true, MonoDetourManager? manager = null)
		{
			return (manager ?? DefaultMonoDetourManager.Instance).ILHook(Target(), manipulator, config, applyByDefault);
		}

		public static MethodBase Target()
		{
			return typeof(GameManager).GetMethod("StartNewGame", (BindingFlags)(-1), null, new Type[2]
			{
				typeof(bool),
				typeof(bool)
			}, null) ?? throw new MissingMethodException("GameManager", "StartNewGame");
		}
	}
	internal static class Start
	{
		public delegate void PrefixSignature(GameManager self);

		public delegate void PostfixSignature(GameManager self);

		public static MonoDetourHook Prefix(PrefixSignature hook, MonoDetourConfig? config = null, bool applyByDefault = true, MonoDetourManager? manager = null)
		{
			return (manager ?? DefaultMonoDetourManager.Instance).Hook<PrefixDetour>(Target(), (Delegate)hook, config, applyByDefault);
		}

		public static MonoDetourHook Postfix(PostfixSignature hook, MonoDetourConfig? config = null, bool applyByDefault = true, MonoDetourManager? manager = null)
		{
			return (manager ?? DefaultMonoDetourManager.Instance).Hook<PostfixDetour>(Target(), (Delegate)hook, config, applyByDefault);
		}

		public static MonoDetourHook ILHook(Manipulator manipulator, MonoDetourConfig? config = null, bool applyByDefault = true, MonoDetourManager? manager = null)
		{
			return (manager ?? DefaultMonoDetourManager.Instance).ILHook(Target(), manipulator, config, applyByDefault);
		}

		public static MethodBase Target()
		{
			return typeof(GameManager).GetMethod("Start", (BindingFlags)(-1), null, Array.Empty<Type>(), null) ?? throw new MissingMethodException("GameManager", "Start");
		}
	}
	internal static class PausedEvent
	{
		internal static class Invoke
		{
			public delegate void PrefixSignature(PausedEvent self, ref bool isPaused);

			public delegate void PostfixSignature(PausedEvent self, ref bool isPaused);

			public static MonoDetourHook Prefix(PrefixSignature hook, MonoDetourConfig? config = null, bool applyByDefault = true, MonoDetourManager? manager = null)
			{
				return (manager ?? DefaultMonoDetourManager.Instance).Hook<PrefixDetour>(Target(), (Delegate)hook, config, applyByDefault);
			}

			public static MonoDetourHook Postfix(PostfixSignature hook, MonoDetourConfig? config = null, bool applyByDefault = true, MonoDetourManager? manager = null)
			{
				return (manager ?? DefaultMonoDetourManager.Instance).Hook<PostfixDetour>(Target(), (Delegate)hook, config, applyByDefault);
			}

			public static MonoDetourHook ILHook(Manipulator manipulator, MonoDetourConfig? config = null, bool applyByDefault = true, MonoDetourManager? manager = null)
			{
				return (manager ?? DefaultMonoDetourManager.Instance).ILHook(Target(), manipulator, config, applyByDefault);
			}

			public static MethodBase Target()
			{
				return typeof(PausedEvent).GetMethod("Invoke", (BindingFlags)(-1), null, new Type[1] { typeof(bool) }, null) ?? throw new MissingMethodException("GameManager+PausedEvent", "Invoke");
			}
		}
	}
	internal static class GameStateEvent
	{
		internal static class Invoke
		{
			public delegate void PrefixSignature(GameStateEvent self, ref GameState gameState);

			public delegate void PostfixSignature(GameStateEvent self, ref GameState gameState);

			public static MonoDetourHook Prefix(PrefixSignature hook, MonoDetourConfig? config = null, bool applyByDefault = true, MonoDetourManager? manager = null)
			{
				return (manager ?? DefaultMonoDetourManager.Instance).Hook<PrefixDetour>(Target(), (Delegate)hook, config, applyByDefault);
			}

			public static MonoDetourHook Postfix(PostfixSignature hook, MonoDetourConfig? config = null, bool applyByDefault = true, MonoDetourManager? manager = null)
			{
				return (manager ?? DefaultMonoDetourManager.Instance).Hook<PostfixDetour>(Target(), (Delegate)hook, config, applyByDefault);
			}

			public static MonoDetourHook ILHook(Manipulator manipulator, MonoDetourConfig? config = null, bool applyByDefault = true, MonoDetourManager? manager = null)
			{
				return (manager ?? DefaultMonoDetourManager.Instance).ILHook(Target(), manipulator, config, applyByDefault);
			}

			public static MethodBase Target()
			{
				return typeof(GameStateEvent).GetMethod("Invoke", (BindingFlags)(-1), null, new Type[1] { typeof(GameState) }, null) ?? throw new MissingMethodException("GameManager+GameStateEvent", "Invoke");
			}
		}
	}
	internal static class BossLoad
	{
		internal static class Invoke
		{
			public delegate void PrefixSignature(BossLoad self);

			public delegate void PostfixSignature(BossLoad self);

			public static MonoDetourHook Prefix(PrefixSignature hook, MonoDetourConfig? config = null, bool applyByDefault = true, MonoDetourManager? manager = null)
			{
				return (manager ?? DefaultMonoDetourManager.Instance).Hook<PrefixDetour>(Target(), (Delegate)hook, config, applyByDefault);
			}

			public static MonoDetourHook Postfix(PostfixSignature hook, MonoDetourConfig? config = null, bool applyByDefault = true, MonoDetourManager? manager = null)
			{
				return (manager ?? DefaultMonoDetourManager.Instance).Hook<PostfixDetour>(Target(), (Delegate)hook, config, applyByDefault);
			}

			public static MonoDetourHook ILHook(Manipulator manipulator, MonoDetourConfig? config = null, bool applyByDefault = true, MonoDetourManager? manager = null)
			{
				return (manager ?? DefaultMonoDetourManager.Instance).ILHook(Target(), manipulator, config, applyByDefault);
			}

			public static MethodBase Target()
			{
				return typeof(BossLoad).GetMethod("Invoke", (BindingFlags)(-1), null, Array.Empty<Type>(), null) ?? throw new MissingMethodException("GameManager+BossLoad", "Invoke");
			}
		}
	}
	internal static class EnterSceneEvent
	{
		internal static class Invoke
		{
			public delegate void PrefixSignature(EnterSceneEvent self);

			public delegate void PostfixSignature(EnterSceneEvent self);

			public static MonoDetourHook Prefix(PrefixSignature hook, MonoDetourConfig? config = null, bool applyByDefault = true, MonoDetourManager? manager = null)
			{
				return (manager ?? DefaultMonoDetourManager.Instance).Hook<PrefixDetour>(Target(), (Delegate)hook, config, applyByDefault);
			}

			public static MonoDetourHook Postfix(PostfixSignature hook, MonoDetourConfig? config = null, bool applyByDefault = true, MonoDetourManager? manager = null)
			{
				return (manager ?? DefaultMonoDetourManager.Instance).Hook<PostfixDetour>(Target(), (Delegate)hook, config, applyByDefault);
			}

			public static MonoDetourHook ILHook(Manipulator manipulator, MonoDetourConfig? config = null, bool applyByDefault = true, MonoDetourManager? manager = null)
			{
				return (manager ?? DefaultMonoDetourManager.Instance).ILHook(Target(), manipulator, config, applyByDefault);
			}

			public static MethodBase Target()
			{
				return typeof(EnterSceneEvent).GetMethod("Invoke", (BindingFlags)(-1), null, Array.Empty<Type>(), null) ?? throw new MissingMethodException("GameManager+EnterSceneEvent", "Invoke");
			}
		}
	}
	internal static class SceneTransitionFinishEvent
	{
		internal static class Invoke
		{
			public delegate void PrefixSignature(SceneTransitionFinishEvent self);

			public delegate void PostfixSignature(SceneTransitionFinishEvent self);

			public static MonoDetourHook Prefix(PrefixSignature hook, MonoDetourConfig? config = null, bool applyByDefault = true, MonoDetourManager? manager = null)
			{
				return (manager ?? DefaultMonoDetourManager.Instance).Hook<PrefixDetour>(Target(), (Delegate)hook, config, applyByDefault);
			}

			public static MonoDetourHook Postfix(PostfixSignature hook, MonoDetourConfig? config = null, bool applyByDefault = true, MonoDetourManager? manager = null)
			{
				return (manager ?? DefaultMonoDetourManager.Instance).Hook<PostfixDetour>(Target(), (Delegate)hook, config, applyByDefault);
			}

			public static MonoDetourHook ILHook(Manipulator manipulator, MonoDetourConfig? config = null, bool applyByDefault = true, MonoDetourManager? manager = null)
			{
				return (manager ?? DefaultMonoDetourManager.Instance).ILHook(Target(), manipulator, config, applyByDefault);
			}

			public static MethodBase Target()
			{
				return typeof(SceneTransitionFinishEvent).GetMethod("Invoke", (BindingFlags)(-1), null, Array.Empty<Type>(), null) ?? throw new MissingMethodException("GameManager+SceneTransitionFinishEvent", "Invoke");
			}
		}
	}
	internal static class SceneTransitionBeganDelegate
	{
		internal static class Invoke
		{
			public delegate void PrefixSignature(SceneTransitionBeganDelegate self, ref SceneLoad sceneLoad);

			public delegate void PostfixSignature(SceneTransitionBeganDelegate self, ref SceneLoad sceneLoad);

			public static MonoDetourHook Prefix(PrefixSignature hook, MonoDetourConfig? config = null, bool applyByDefault = true, MonoDetourManager? manager = null)
			{
				return (manager ?? DefaultMonoDetourManager.Instance).Hook<PrefixDetour>(Target(), (Delegate)hook, config, applyByDefault);
			}

			public static MonoDetourHook Postfix(PostfixSignature hook, MonoDetourConfig? config = null, bool applyByDefault = true, MonoDetourManager? manager = null)
			{
				return (manager ?? DefaultMonoDetourManager.Instance).Hook<PostfixDetour>(Target(), (Delegate)hook, config, applyByDefault);
			}

			public static MonoDetourHook ILHook(Manipulator manipulator, MonoDetourConfig? config = null, bool applyByDefault = true, MonoDetourManager? manager = null)
			{
				return (manager ?? DefaultMonoDetourManager.Instance).ILHook(Target(), manipulator, config, applyByDefault);
			}

			public static MethodBase Target()
			{
				return typeof(SceneTransitionBeganDelegate).GetMethod("Invoke", (BindingFlags)(-1), null, new Type[1] { typeof(SceneLoad) }, null) ?? throw new MissingMethodException("GameManager+SceneTransitionBeganDelegate", "Invoke");
			}
		}
	}
}
namespace MonoDetour.HookGen
{
	internal static class DefaultMonoDetourManager
	{
		internal static MonoDetourManager Instance { get; } = New();


		internal static MonoDetourManager New()
		{
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: Expected O, but got Unknown
			return new MonoDetourManager(typeof(DefaultMonoDetourManager).Assembly.GetName().Name);
		}
	}
	[AttributeUsage(AttributeTargets.Assembly | AttributeTargets.Class, AllowMultiple = true, Inherited = false)]
	internal class MonoDetourTargetsAttribute : Attribute, IMonoDetourTargets
	{
		public Type? TargetType { get; }

		public bool IncludeNestedTypes { get; set; }

		public string[]? Members { get; set; }

		public string[]? MemberNamePrefixes { get; set; }

		public string[]? MemberNameSuffixes { get; set; }

		public bool GenerateControlFlowVariants { get; set; }

		public MonoDetourTargetsAttribute(Type? targetType = null)
		{
			TargetType = targetType;
			IncludeNestedTypes = true;
			base..ctor();
		}
	}
}
namespace BepInEx
{
	[AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = false)]
	[Conditional("CodeGeneration")]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class BepInAutoPluginAttribute : Attribute
	{
		public BepInAutoPluginAttribute(string? id = null, string? name = null, string? version = null)
		{
		}
	}
}
namespace BepInEx.Preloader.Core.Patching
{
	[AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = false)]
	[Conditional("CodeGeneration")]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class PatcherAutoPluginAttribute : Attribute
	{
		public PatcherAutoPluginAttribute(string? id = null, string? name = null, string? version = null)
		{
		}
	}
}
namespace Microsoft.CodeAnalysis
{
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace MusicRando
{
	internal static class ConfigSettings
	{
		public static ConfigEntry<RandomizationStrategyOption>? MusicRandomization;

		public static void Init(ConfigFile config)
		{
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_002b: Expected O, but got Unknown
			MusicRandomization = config.Bind<RandomizationStrategyOption>("General", "MusicRandomization", RandomizationStrategyOption.OnChange, new ConfigDescription("When to randomize the music", (AcceptableValueBase)null, new object[1] { MenuElementGenerators.CreateRightDescGenerator(false) }));
		}
	}
	public enum RandomizationStrategyOption
	{
		[Description("Randomize whenever the music changes")]
		OnChange,
		[Description("Randomize more often than usual")]
		Chaos,
		[Description("Select a song dependent on the vanilla song")]
		Consistent,
		[Description("Randomly decide when to randomize the music")]
		RandoRando,
		[Description("Do not randomize music")]
		Disabled
	}
	public enum MusicAction
	{
		Ignore,
		Replay,
		Randomize
	}
	[MonoDetourTargets(typeof(GameManager))]
	[MonoDetourTargets(typeof(QuitToMenu))]
	internal static class GameEvents
	{
		private static readonly string Id = "MusicRando.GameEvents";

		private static readonly MonoDetourManager mgr = new MonoDetourManager(Id);

		public static bool IsInGame { get; private set; }

		public static event Action? OnEnterGame;

		public static event Action? OnQuitToMenu;

		internal static void Hook()
		{
			ContinueGame.Postfix(AfterContinueGame, null, applyByDefault: true, mgr);
			StartNewGame.Postfix(AfterStartNewGame, null, applyByDefault: true, mgr);
			Md.QuitToMenu.Start.Postfix(AfterQuitGame, null, applyByDefault: true, mgr);
		}

		private static void AfterQuitGame(QuitToMenu self, ref IEnumerator returnValue)
		{
			AfterGameExit();
		}

		private static void AfterStartNewGame(GameManager self, ref bool permadeathMode, ref bool bossRushMode)
		{
			AfterGameEnter();
		}

		private static void AfterContinueGame(GameManager self)
		{
			AfterGameEnter();
		}

		private static void AfterGameEnter()
		{
			IsInGame = true;
			Delegate[] array = GameEvents.OnEnterGame?.GetInvocationList() ?? Array.Empty<Action>();
			for (int i = 0; i < array.Length; i++)
			{
				((Action)array[i])?.Invoke();
			}
		}

		private static void AfterGameExit()
		{
			IsInGame = false;
			Delegate[] array = GameEvents.OnQuitToMenu?.GetInvocationList() ?? Array.Empty<Action>();
			for (int i = 0; i < array.Length; i++)
			{
				((Action)array[i])?.Invoke();
			}
		}
	}
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[MonoDetourTargets(typeof(AudioManager))]
	[BepInPlugin("io.github.flibber-hk.musicrando", "MusicRando", "0.1.2")]
	public class MusicRandoPlugin : BaseUnityPlugin
	{
		private ManagedResourceLocation<MusicCue>? _lastMusicCueLocation;

		public const string Id = "io.github.flibber-hk.musicrando";

		private static Dictionary<RandomizationStrategyOption, SelectionStrategy> Strategies { get; set; }

		internal static ManualLogSource InstanceLogger { get; private set; }

		public static string Name => "MusicRando";

		public static string Version => "0.1.2";

		private void Awake()
		{
			InstanceLogger = ((BaseUnityPlugin)this).Logger;
			ConfigSettings.Init(((BaseUnityPlugin)this).Config);
			GameEvents.Hook();
			Strategies = new Dictionary<RandomizationStrategyOption, SelectionStrategy>
			{
				[RandomizationStrategyOption.OnChange] = new OnChangeSelectionStrategy(),
				[RandomizationStrategyOption.Chaos] = new ChaosSelectionStrategy(),
				[RandomizationStrategyOption.Consistent] = new ConsistentSelectionStrategy(),
				[RandomizationStrategyOption.RandoRando] = new RandoRandoSelectionStrategy(),
				[RandomizationStrategyOption.Disabled] = new DisabledSelectionStrategy()
			};
			ConfigEntry<RandomizationStrategyOption>? musicRandomization = ConfigSettings.MusicRandomization;
			if (musicRandomization != null)
			{
				musicRandomization.SettingChanged += delegate
				{
					SelectionStrategy.Reset();
					_lastMusicCueLocation = null;
					if (Strategies.TryGetValue(ConfigSettings.MusicRandomization.Value, out SelectionStrategy value))
					{
						value.InitStrategy();
					}
				};
			}
			AddressablesData.InvokeAfterAddressablesLoaded((Action)FindAudioCues);
			ApplyMusicCue.Prefix(OnApplyMusicCue);
			GameEvents.OnQuitToMenu += OnQuitToMenu;
			((BaseUnityPlugin)this).Logger.LogInfo((object)("Plugin " + Name + " (io.github.flibber-hk.musicrando) has loaded!"));
		}

		private void OnApplyMusicCue(AudioManager self, ref MusicCue musicCue, ref float delayTime, ref float transitionTime, ref bool applySnapshot)
		{
			//IL_00b1: 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_00e2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e7: 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)
			//IL_0066: Unknown result type (might be due to invalid IL or missing references)
			//IL_0090: Unknown result type (might be due to invalid IL or missing references)
			//IL_0095: Unknown result type (might be due to invalid IL or missing references)
			RandomizationStrategyOption key = ConfigSettings.MusicRandomization?.Value ?? RandomizationStrategyOption.OnChange;
			ManagedResourceLocation<MusicCue> location;
			MusicAction musicAction = Strategies[key].Select(musicCue, out location);
			if (location != null && !location.IsLoaded)
			{
				((BaseUnityPlugin)this).Logger.LogInfo((object)"Failed to apply music cue: not loaded");
				musicAction = MusicAction.Ignore;
			}
			if (musicAction == MusicAction.Replay)
			{
				if (_lastMusicCueLocation != null)
				{
					((BaseUnityPlugin)this).Logger.LogInfo((object)("Re-applying " + ((Object)_lastMusicCueLocation.Handle.Result).name + ", over " + ((Object)musicCue).name));
					musicCue = _lastMusicCueLocation.Handle.Result;
					return;
				}
				musicAction = MusicAction.Ignore;
			}
			if (musicAction != 0)
			{
				((BaseUnityPlugin)this).Logger.LogInfo((object)("Applying " + ((Object)location.Handle.Result).name + " over " + ((Object)musicCue).name));
				_lastMusicCueLocation = location;
				musicCue = location.Handle.Result;
			}
		}

		private void OnQuitToMenu()
		{
			SelectionStrategy.Reset();
			_lastMusicCueLocation = null;
			foreach (SelectionStrategy value in Strategies.Values)
			{
				value.InitStrategy();
			}
		}

		private void FindAudioCues()
		{
			Stopwatch stopwatch = Stopwatch.StartNew();
			List<string> cached = CacheManager.GetCached("musicrando.musiccues.json", Version, "0.1.0", GetMusicCuePrimaryKeys);
			List<IResourceLocation> list = new List<IResourceLocation>();
			IList<IResourceLocation> collection = default(IList<IResourceLocation>);
			foreach (string item in cached)
			{
				if (AddressablesData.MainLocator.Locate((object)item, typeof(MusicCue), ref collection))
				{
					list.AddRange(collection);
				}
			}
			SelectionStrategy.SetResourceLocations(list);
			stopwatch.Stop();
			((BaseUnityPlugin)this).Logger.LogInfo((object)$"Prepared music cue locations in {stopwatch.ElapsedMilliseconds} ms");
		}

		private List<string> GetMusicCuePrimaryKeys()
		{
			List<string> list = new List<string>();
			IList<IResourceLocation> list2 = default(IList<IResourceLocation>);
			foreach (string item in AddressablesData.MainLocator.Keys.OfType<string>())
			{
				if (AddressablesData.MainLocator.Locate((object)item, typeof(MusicCue), ref list2))
				{
					list.Add(item);
				}
			}
			return list;
		}
	}
	internal static class RngExt
	{
		public static T Choose<T>(this Random rng, IList<T> things)
		{
			int index = rng.Next(things.Count);
			return things[index];
		}

		public static T Choose<T>(this Random rng, IList<T> things, Func<T, bool> predicate)
		{
			List<T> things2 = things.Where(predicate).ToList();
			return rng.Choose(things2);
		}
	}
}
namespace MusicRando.MusicSelectionStrategies
{
	internal class ChaosSelectionStrategy : SelectionStrategy
	{
		protected override bool TrySelect(MusicCue origToPlay, out string? selected)
		{
			selected = SelectionStrategy.rng.Choose(SelectionStrategy.DifferentLocationKeys);
			return true;
		}
	}
	internal class ConsistentSelectionStrategy : SelectionStrategy
	{
		private readonly Dictionary<string, string> _previouslySelected = new Dictionary<string, string>();

		private string? _lastOrigMusicCue;

		public override void InitStrategy()
		{
			_previouslySelected.Clear();
			_lastOrigMusicCue = null;
		}

		protected override bool TrySelect(MusicCue origToPlay, out string? selected)
		{
			if (_lastOrigMusicCue == ((Object)origToPlay).name)
			{
				selected = null;
				return false;
			}
			if (_previouslySelected.TryGetValue(((Object)origToPlay).name, out selected))
			{
				return true;
			}
			selected = SelectionStrategy.rng.Choose(SelectionStrategy.DifferentLocationKeys);
			_previouslySelected[((Object)origToPlay).name] = selected;
			return true;
		}
	}
	internal class DisabledSelectionStrategy : SelectionStrategy
	{
		protected override bool TrySelect(MusicCue origToPlay, out string? selected)
		{
			selected = null;
			return false;
		}
	}
	internal class OnChangeSelectionStrategy : SelectionStrategy
	{
		private string? _lastOrigMusicCue;

		public override void InitStrategy()
		{
			_lastOrigMusicCue = null;
		}

		protected override bool TrySelect(MusicCue origToPlay, out string? selected)
		{
			if (((Object)origToPlay).name == _lastOrigMusicCue)
			{
				selected = null;
				return false;
			}
			_lastOrigMusicCue = ((Object)origToPlay).name;
			selected = SelectionStrategy.rng.Choose(SelectionStrategy.DifferentLocationKeys);
			return true;
		}
	}
	internal class RandoRandoSelectionStrategy : SelectionStrategy
	{
		protected override bool TrySelect(MusicCue origToPlay, out string? selected)
		{
			if (SelectionStrategy.rng.Next(8) != 5)
			{
				selected = null;
				return false;
			}
			selected = SelectionStrategy.rng.Choose(SelectionStrategy.DifferentLocationKeys);
			return true;
		}
	}
	internal abstract class SelectionStrategy
	{
		protected static Random rng = new Random();

		protected static Dictionary<string, ManagedResourceLocation<MusicCue>>? MusicResourceLocations;

		protected static List<string> DifferentLocationKeys => MusicResourceLocations?.Keys.Where((string x) => (LastSelectedLocationKey ?? string.Empty) != x).ToList() ?? new List<string>();

		protected static string? LastSelectedLocationKey { get; private set; }

		internal static void SetResourceLocations(IEnumerable<IResourceLocation> locs)
		{
			if (MusicResourceLocations != null)
			{
				throw new InvalidOperationException("Can't set locs more than once!");
			}
			MusicResourceLocations = new Dictionary<string, ManagedResourceLocation<MusicCue>>();
			Dictionary<string, IResourceLocation> dictionary = new Dictionary<string, IResourceLocation>();
			foreach (IResourceLocation loc in locs)
			{
				if (!loc.InternalId.EndsWith("None.asset") && !MusicResourceLocations.ContainsKey(loc.InternalId))
				{
					MusicResourceLocations.Add(loc.InternalId, new ManagedResourceLocation<MusicCue>(loc));
					dictionary.Add(loc.InternalId, loc);
				}
			}
			MusicRandoPlugin.InstanceLogger.LogInfo((object)$"Found {MusicResourceLocations.Count} distinct music cues");
			GameEvents.OnEnterGame += delegate
			{
				//IL_0019: Unknown result type (might be due to invalid IL or missing references)
				foreach (ManagedResourceLocation<MusicCue> value in MusicResourceLocations.Values)
				{
					value.Load();
				}
			};
			GameEvents.OnQuitToMenu += delegate
			{
				foreach (ManagedResourceLocation<MusicCue> value2 in MusicResourceLocations.Values)
				{
					value2.Unload();
				}
			};
		}

		protected abstract bool TrySelect(MusicCue origToPlay, out string? selected);

		public virtual void InitStrategy()
		{
		}

		private MusicAction RunSelection(MusicCue origToPlay, out string? location)
		{
			location = null;
			if ((MusicResourceLocations?.Count ?? 0) <= 0)
			{
				return MusicAction.Ignore;
			}
			if (!GameEvents.IsInGame)
			{
				return MusicAction.Ignore;
			}
			if (((Object)origToPlay).name == "None")
			{
				return MusicAction.Ignore;
			}
			if (!TrySelect(origToPlay, out location))
			{
				return MusicAction.Replay;
			}
			return MusicAction.Randomize;
		}

		internal MusicAction Select(MusicCue origToPlay, out ManagedResourceLocation<MusicCue>? location)
		{
			string location2;
			MusicAction musicAction = RunSelection(origToPlay, out location2);
			if (musicAction == MusicAction.Ignore || musicAction == MusicAction.Replay)
			{
				location = null;
				return musicAction;
			}
			LastSelectedLocationKey = location2;
			location = MusicResourceLocations[location2];
			return musicAction;
		}

		public static void Reset()
		{
			LastSelectedLocationKey = null;
		}
	}
}
namespace MusicRando.Cache
{
	internal class CachedObject<T> where T : class
	{
		public string? SilksongVersion { get; set; }

		public string? PluginVersion { get; set; }

		public required T Value { get; set; }
	}
	public static class CacheManager
	{
		private static string? _silksongVersion;

		public static string SilksongVersion
		{
			get
			{
				if (_silksongVersion == null)
				{
					_silksongVersion = GetSilksongVersion();
				}
				return _silksongVersion;
			}
		}

		private static string GetSilksongVersion()
		{
			return (typeof(Constants).GetField("GAME_VERSION", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic)?.GetRawConstantValue() as string) ?? "UNKNOWN";
		}

		private static bool MetadataMismatch<T>(CachedObject<T> cached, string earliestAcceptableVersion) where T : class
		{
			if (cached.SilksongVersion == null || cached.SilksongVersion != SilksongVersion)
			{
				return true;
			}
			if (!Version.TryParse(earliestAcceptableVersion, out Version result))
			{
				return true;
			}
			if (cached.PluginVersion == null || !Version.TryParse(cached.PluginVersion, out Version result2))
			{
				return true;
			}
			if (result2 < result)
			{
				return true;
			}
			return false;
		}

		public static T GetCached<T>(string fileName, string currentPluginVersion, string earliestAcceptableVersion, Func<T> getter) where T : class
		{
			if (!Version.TryParse(currentPluginVersion, out Version _))
			{
				throw new ArgumentException("Cannot parse current plugin version to Version");
			}
			string filePath = Path.Combine(Paths.CachePath, fileName);
			if (JsonHelper.TryLoadFromFile<CachedObject<T>>(filePath, out CachedObject<T> obj) && !MetadataMismatch(obj, earliestAcceptableVersion))
			{
				return obj.Value;
			}
			T val = getter();
			new CachedObject<T>
			{
				SilksongVersion = SilksongVersion,
				PluginVersion = currentPluginVersion,
				Value = val
			}.SerializeToFile(filePath);
			return val;
		}
	}
	internal static class JsonHelper
	{
		public static void SerializeToFile<T>(this T self, string filePath)
		{
			string contents = JsonConvert.SerializeObject((object)self, (Formatting)1);
			File.WriteAllText(filePath, contents);
		}

		public static bool TryLoadFromFile<T>(string filePath, [NotNullWhen(true)] out T? obj)
		{
			obj = default(T);
			if (string.IsNullOrEmpty(filePath) || !File.Exists(filePath))
			{
				return false;
			}
			try
			{
				string text = File.ReadAllText(filePath);
				obj = JsonConvert.DeserializeObject<T>(text);
				return obj != null;
			}
			catch (Exception)
			{
				return false;
			}
		}
	}
}