Decompiled source of RiskOfWaiting v2.0.1

plugins/RiskOfWaitingRedux.dll

Decompiled a month ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Logging;
using HG.Reflection;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using RiskOfWaitingRedux.Fixes;
using RoR2;
using RoR2.ConVar;
using UnityEngine;
using UnityEngine.Rendering.PostProcessing;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: IgnoresAccessChecksTo("Unity.Postprocessing.Runtime")]
[assembly: AssemblyCompany("RiskOfWaitingRedux")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0+7e54c57bea64249da8d4e2bd22eb80bf05700959")]
[assembly: AssemblyProduct("RiskOfWaitingRedux")]
[assembly: AssemblyTitle("RiskOfWaitingRedux")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.0.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[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 RiskOfWaitingRedux
{
	public static class CacheHelpers
	{
		public struct SerializableMembers
		{
			public Type type;

			public List<ushort> membersIndices;

			public readonly ushort MemberIndicesCount => (ushort)membersIndices.Count;
		}

		public static void Write(this BinaryWriter writer, Guid guid)
		{
			writer.Write(guid.ToByteArray());
		}

		public static Guid ReadGuid(this BinaryReader reader)
		{
			return new Guid(reader.ReadBytes(16));
		}

		public static void WriteAssemblyIdentifer(BinaryWriter writer, Assembly assembly)
		{
			writer.Write(assembly.ManifestModule.ModuleVersionId);
		}

		public static bool ReadAssemblyWasModified(BinaryReader reader, Assembly assembly)
		{
			Guid guid = reader.ReadGuid();
			return assembly.ManifestModule.ModuleVersionId != guid;
		}

		public static void WriteTypeCollection(BinaryWriter writer, ICollection<Type> typeCollection)
		{
			writer.Write(typeCollection.Count);
			foreach (Type item in typeCollection)
			{
				writer.Write(item.FullName);
			}
		}

		public static ICollection<Type> ReadTypeCollection(BinaryReader reader, Assembly assembly)
		{
			int num = reader.ReadInt32();
			Type[] array = new Type[num];
			for (int i = 0; i < num; i++)
			{
				string name = reader.ReadString();
				array[i] = assembly.GetType(name, throwOnError: true);
			}
			return array;
		}

		public static void WriteMembersCollection(BinaryWriter writer, ICollection<SerializableMembers> membersCollection)
		{
			writer.Write(membersCollection.Count);
			foreach (SerializableMembers item in membersCollection)
			{
				writer.Write(item.type.FullName);
				writer.Write(item.MemberIndicesCount);
				foreach (ushort membersIndex in item.membersIndices)
				{
					writer.Write(membersIndex);
				}
			}
		}

		public static ICollection<TMember> ReadMembersCollection<TMember>(BinaryReader reader, Assembly assembly, Func<Type, TMember[]> getTypeMembers)
		{
			List<TMember> list = new List<TMember>();
			int num = reader.ReadInt32();
			for (int i = 0; i < num; i++)
			{
				string name = reader.ReadString();
				Type type = assembly.GetType(name, throwOnError: true);
				TMember[] array = getTypeMembers(type);
				int num2 = reader.ReadUInt16();
				for (int j = 0; j < num2; j++)
				{
					list.Add(array[reader.ReadUInt16()]);
				}
			}
			return list;
		}

		public static bool IsLikelyMMHOOKAssembly(Assembly assembly)
		{
			return assembly.FullName.StartsWith("MMHOOK_");
		}

		public static string GetCacheDirectory(string cacheName)
		{
			return Path.Combine(RiskOfWaitingReduxPlugin.DataDirectory, cacheName);
		}

		public static int GetSerializableMembersCount(Array members)
		{
			return Math.Min(members.Length, 65535);
		}
	}
	[BepInPlugin("groovesalad.RiskOfWaitingRedux", "RiskOfWaitingRedux", "2.0.0")]
	public class RiskOfWaitingReduxPlugin : BaseUnityPlugin
	{
		public const string GUID = "groovesalad.RiskOfWaitingRedux";

		public const string NAME = "RiskOfWaitingRedux";

		public const string VERSION = "2.0.0";

		public static ManualLogSource Logger { get; private set; }

		public static Harmony Harmony { get; private set; }

		public static string DataDirectory { get; private set; }

		private void Awake()
		{
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_001a: Expected O, but got Unknown
			Logger = ((BaseUnityPlugin)this).Logger;
			Harmony = new Harmony("groovesalad.RiskOfWaitingRedux");
			DataDirectory = Path.Combine(Environment.CurrentDirectory, "RiskOfWaitingReduxData");
			PostProcessCache.Init();
			SearchableAttributeCache.Init();
			ConVarsCache.Init();
			EntityStateCatalogFix.Init();
		}
	}
}
namespace RiskOfWaitingRedux.Fixes
{
	public static class ConVarsCache
	{
		[Flags]
		public enum ConVarCacheFlags : byte
		{
			None = 0,
			HasConVarFields = 1,
			HasConVarProviders = 2
		}

		private static string cacheDirectory;

		public static void Init()
		{
			cacheDirectory = CacheHelpers.GetCacheDirectory("ConVarsCache");
			Directory.CreateDirectory(cacheDirectory);
			RiskOfWaitingReduxPlugin.Harmony.PatchAll(typeof(ConVarsCache));
		}

		[HarmonyPrefix]
		[HarmonyPatch(typeof(Console), "InternalInitConVarsCoroutine")]
		private static bool ReplaceInternalInitConVarsCoroutine(Console __instance, ref IEnumerator __result)
		{
			__instance.maxPassesBeforeYielding = 100;
			InitConVarsFromCache(__instance);
			return false;
		}

		private static void InitConVarsFromCache(Console console)
		{
			List<CacheHelpers.SerializableMembers> list = new List<CacheHelpers.SerializableMembers>();
			List<CacheHelpers.SerializableMembers> list2 = new List<CacheHelpers.SerializableMembers>();
			HashSet<string> hashSet = new HashSet<string>();
			Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies();
			foreach (Assembly assembly in assemblies)
			{
				if (assembly.GetCustomAttribute<OptInAttribute>() == null)
				{
					continue;
				}
				if (!hashSet.Add(assembly.FullName))
				{
					RiskOfWaitingReduxPlugin.Logger.LogWarning((object)("Not scanning an assembly for ConVars because it has the same name as " + assembly.FullName));
					continue;
				}
				string cachePath = Path.Combine(cacheDirectory, assembly.FullName);
				if (!TryLoadFromCache(console, assembly, cachePath))
				{
					RegisterConVarsInAssembly(console, assembly, list, list2);
					CreateCache(assembly, cachePath, list, list2);
				}
			}
			AudioManager.cvVolumeMaster.fallbackString = ((BaseConVar)AudioManager.cvVolumeMaster).GetString();
		}

		private static void RegisterConVarsInAssembly(Console console, Assembly assembly, List<CacheHelpers.SerializableMembers> conVarFieldsResult, List<CacheHelpers.SerializableMembers> conVarProvidersResult)
		{
			conVarFieldsResult.Clear();
			conVarProvidersResult.Clear();
			Type[] types = assembly.GetTypes();
			foreach (Type type in types)
			{
				if (TryRegisterConVarFields(console, type, out var conVarFieldIndices))
				{
					conVarFieldsResult.Add(new CacheHelpers.SerializableMembers
					{
						type = type,
						membersIndices = conVarFieldIndices
					});
				}
				if (TryRegisterConVarProviderMethods(console, type, out var conVarProviderMethodIndices))
				{
					conVarProvidersResult.Add(new CacheHelpers.SerializableMembers
					{
						type = type,
						membersIndices = conVarProviderMethodIndices
					});
				}
			}
		}

		private static bool TryRegisterConVarFields(Console console, Type type, out List<ushort> conVarFieldIndices)
		{
			bool flag = false;
			conVarFieldIndices = null;
			try
			{
				FieldInfo[] scannableFieldsFromType = GetScannableFieldsFromType(type);
				int serializableMembersCount = CacheHelpers.GetSerializableMembersCount(scannableFieldsFromType);
				for (ushort num = 0; num < serializableMembersCount; num++)
				{
					FieldInfo fieldInfo = scannableFieldsFromType[num];
					try
					{
						if (fieldInfo.FieldType.IsSubclassOf(typeof(BaseConVar)))
						{
							if (fieldInfo.IsStatic)
							{
								RegisterConVarField(console, fieldInfo);
								if (!flag)
								{
									flag = true;
									conVarFieldIndices = new List<ushort>();
								}
								conVarFieldIndices.Add(num);
							}
							else if (type.GetCustomAttribute<CompilerGeneratedAttribute>() == null)
							{
								RiskOfWaitingReduxPlugin.Logger.LogError((object)("ConVar defined as " + type.Name + "." + fieldInfo.Name + " could not be registered. ConVars must be static fields."));
							}
						}
					}
					catch (Exception arg)
					{
						RiskOfWaitingReduxPlugin.Logger.LogError((object)$"TryRegisterConVarFields failed for field {type.FullName}.{fieldInfo.Name}: {arg}");
					}
				}
			}
			catch (Exception arg2)
			{
				RiskOfWaitingReduxPlugin.Logger.LogError((object)$"TryRegisterConVarFields failed for type {type.FullName}: {arg2}");
			}
			return flag;
		}

		private static bool TryRegisterConVarProviderMethods(Console console, Type type, out List<ushort> conVarProviderMethodIndices)
		{
			bool flag = false;
			conVarProviderMethodIndices = null;
			try
			{
				MethodInfo[] scannableMethodsFromType = GetScannableMethodsFromType(type);
				int serializableMembersCount = CacheHelpers.GetSerializableMembersCount(scannableMethodsFromType);
				for (ushort num = 0; num < serializableMembersCount; num++)
				{
					MethodInfo methodInfo = scannableMethodsFromType[num];
					try
					{
						if (((MemberInfo)methodInfo).GetCustomAttribute<ConVarProviderAttribute>() != null)
						{
							if (methodInfo.ReturnType != typeof(IEnumerable<BaseConVar>) || methodInfo.GetParameters().Length != 0)
							{
								RiskOfWaitingReduxPlugin.Logger.LogError((object)"ConVar provider {type.Name}.{methodInfo.Name} does not match the signature \"static IEnumerable<ConVar.BaseConVar>()\".");
							}
							else if (!methodInfo.IsStatic)
							{
								RiskOfWaitingReduxPlugin.Logger.LogError((object)("ConVar provider " + type.Name + "." + methodInfo.Name + " could not be invoked. Methods marked with the ConVarProvider attribute must be static."));
							}
							else
							{
								RegisterConVarProvider(console, methodInfo);
								if (!flag)
								{
									flag = true;
									conVarProviderMethodIndices = new List<ushort>();
								}
								conVarProviderMethodIndices.Add(num);
							}
						}
					}
					catch (Exception arg)
					{
						RiskOfWaitingReduxPlugin.Logger.LogError((object)$"TryRegisterConVarProviderMethods failed for method {type.FullName}.{methodInfo.Name}: {arg}");
					}
				}
			}
			catch (Exception arg2)
			{
				RiskOfWaitingReduxPlugin.Logger.LogError((object)$"TryRegisterConVarProviderMethods failed for type {type.FullName}: {arg2}");
			}
			return flag;
		}

		private static FieldInfo[] GetScannableFieldsFromType(Type type)
		{
			return type.GetFields(BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
		}

		private static MethodInfo[] GetScannableMethodsFromType(Type type)
		{
			return type.GetMethods(BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
		}

		private static void RegisterConVarField(Console console, FieldInfo conVarField)
		{
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_0012: Expected O, but got Unknown
			console.RegisterConVarInternal((BaseConVar)conVarField.GetValue(null));
		}

		private static void RegisterConVarProvider(Console console, MethodInfo conVarProvider)
		{
			foreach (BaseConVar item in (IEnumerable<BaseConVar>)conVarProvider.Invoke(null, Array.Empty<object>()))
			{
				console.RegisterConVarInternal(item);
			}
		}

		private static void CreateCache(Assembly assembly, string cachePath, List<CacheHelpers.SerializableMembers> conVarFields, List<CacheHelpers.SerializableMembers> conVarProviders)
		{
			using FileStream output = File.OpenWrite(cachePath);
			using BinaryWriter binaryWriter = new BinaryWriter(output);
			CacheHelpers.WriteAssemblyIdentifer(binaryWriter, assembly);
			bool num = conVarFields.Count > 0;
			bool flag = conVarProviders.Count > 0;
			ConVarCacheFlags conVarCacheFlags = ConVarCacheFlags.None;
			if (num)
			{
				conVarCacheFlags |= ConVarCacheFlags.HasConVarFields;
			}
			if (flag)
			{
				conVarCacheFlags |= ConVarCacheFlags.HasConVarProviders;
			}
			binaryWriter.Write((byte)conVarCacheFlags);
			if (num)
			{
				CacheHelpers.WriteMembersCollection(binaryWriter, conVarFields);
			}
			if (flag)
			{
				CacheHelpers.WriteMembersCollection(binaryWriter, conVarProviders);
			}
		}

		private static bool TryLoadFromCache(Console console, Assembly assembly, string cachePath)
		{
			ICollection<FieldInfo> collection = null;
			ICollection<MethodInfo> collection2 = null;
			try
			{
				if (!File.Exists(cachePath))
				{
					RiskOfWaitingReduxPlugin.Logger.LogInfo((object)("ConVars cache for " + assembly.FullName + " doesn't exist - creating new cache"));
					return false;
				}
				using FileStream input = File.OpenRead(cachePath);
				using BinaryReader binaryReader = new BinaryReader(input);
				if (CacheHelpers.ReadAssemblyWasModified(binaryReader, assembly))
				{
					RiskOfWaitingReduxPlugin.Logger.LogInfo((object)("ConVars cache for " + assembly.FullName + " is outdated - creating new cache"));
					return false;
				}
				byte num = binaryReader.ReadByte();
				if ((num & 1) > 0)
				{
					collection = CacheHelpers.ReadMembersCollection(binaryReader, assembly, GetScannableFieldsFromType);
				}
				if ((num & 2) > 0)
				{
					collection2 = CacheHelpers.ReadMembersCollection(binaryReader, assembly, GetScannableMethodsFromType);
				}
			}
			catch (Exception arg)
			{
				RiskOfWaitingReduxPlugin.Logger.LogError((object)$"ConVars cache for {assembly.FullName} is likely corrupted - creating new cache: {arg}");
				return false;
			}
			if (collection != null)
			{
				foreach (FieldInfo item in collection)
				{
					RegisterConVarField(console, item);
				}
			}
			if (collection2 != null)
			{
				foreach (MethodInfo item2 in collection2)
				{
					RegisterConVarProvider(console, item2);
				}
			}
			return true;
		}
	}
	public static class EntityStateCatalogFix
	{
		public static void Init()
		{
			RiskOfWaitingReduxPlugin.Harmony.PatchAll(typeof(EntityStateCatalogFix));
		}

		[HarmonyPostfix]
		[HarmonyPatch(typeof(EntityStateCatalog), "SetElements")]
		private static IEnumerator SetElementsNoYielding(IEnumerator result)
		{
			int yieldAttemptsThisFrame = 0;
			while (result.MoveNext())
			{
				int num = yieldAttemptsThisFrame + 1;
				yieldAttemptsThisFrame = num;
				if (num > 80)
				{
					yieldAttemptsThisFrame = 0;
					yield return null;
				}
			}
		}
	}
	public static class PostProcessCache
	{
		private static string cacheDirectory;

		public static void Init()
		{
			cacheDirectory = CacheHelpers.GetCacheDirectory("PostProcessingCache");
			Directory.CreateDirectory(cacheDirectory);
			RiskOfWaitingReduxPlugin.Harmony.PatchAll(typeof(PostProcessCache));
		}

		[HarmonyPrefix]
		[HarmonyPatch(typeof(PostProcessManager), "ReloadBaseTypes")]
		private static bool ReloadBaseTypesFromCache(PostProcessManager __instance)
		{
			__instance.CleanBaseTypes();
			Assembly assembly = typeof(PostProcessEffectSettings).Assembly;
			Assembly assembly2 = typeof(PostProcessCache).Assembly;
			HashSet<string> hashSet = new HashSet<string> { assembly.FullName };
			HandleAssembly(__instance, assembly);
			string name = assembly.GetName().Name;
			Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies();
			foreach (Assembly assembly3 in assemblies)
			{
				if (CacheHelpers.IsLikelyMMHOOKAssembly(assembly3) || assembly3 == assembly2)
				{
					continue;
				}
				AssemblyName[] referencedAssemblies = assembly3.GetReferencedAssemblies();
				for (int j = 0; j < referencedAssemblies.Length; j++)
				{
					if (referencedAssemblies[j].Name == name)
					{
						if (!hashSet.Add(assembly3.FullName))
						{
							RiskOfWaitingReduxPlugin.Logger.LogWarning((object)("Not scanning an assembly for PostProcessing because it has the same name as " + assembly3.FullName));
						}
						else
						{
							HandleAssembly(__instance, assembly3);
						}
						break;
					}
				}
			}
			return false;
		}

		private static void RegisterSettingsType(PostProcessManager ppManager, Type settingsType, PostProcessAttribute ppAttribute)
		{
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: Expected O, but got Unknown
			ppManager.settingsTypes.Add(settingsType, ppAttribute);
			PostProcessEffectSettings val = (PostProcessEffectSettings)ScriptableObject.CreateInstance(settingsType);
			val.SetAllOverridesTo(true, false);
			ppManager.m_BaseSettings.Add(val);
		}

		private static void HandleAssembly(PostProcessManager ppManager, Assembly assembly)
		{
			string cachePath = Path.Combine(cacheDirectory, assembly.FullName);
			if (!TryLoadFromCache(ppManager, assembly, cachePath))
			{
				List<Type> settingsTypes = RegisterSettingsTypesInAssembly(ppManager, assembly);
				CreateCache(assembly, cachePath, settingsTypes);
			}
		}

		private static void CreateCache(Assembly assembly, string cachePath, List<Type> settingsTypes)
		{
			using FileStream output = File.OpenWrite(cachePath);
			using BinaryWriter writer = new BinaryWriter(output);
			CacheHelpers.WriteAssemblyIdentifer(writer, assembly);
			CacheHelpers.WriteTypeCollection(writer, settingsTypes);
		}

		private static List<Type> RegisterSettingsTypesInAssembly(PostProcessManager ppManager, Assembly assembly)
		{
			List<Type> list = new List<Type>();
			Type[] types = assembly.GetTypes();
			foreach (Type type in types)
			{
				if (type.IsSubclassOf(typeof(PostProcessEffectSettings)) && !type.IsAbstract)
				{
					PostProcessAttribute customAttribute = ((MemberInfo)type).GetCustomAttribute<PostProcessAttribute>(inherit: false);
					if (customAttribute != null)
					{
						list.Add(type);
						RegisterSettingsType(ppManager, type, customAttribute);
					}
				}
			}
			return list;
		}

		private static bool TryLoadFromCache(PostProcessManager ppManager, Assembly assembly, string cachePath)
		{
			ICollection<Type> collection;
			try
			{
				if (!File.Exists(cachePath))
				{
					RiskOfWaitingReduxPlugin.Logger.LogInfo((object)("PostProcessing cache for " + assembly.FullName + " doesn't exist - creating new cache"));
					return false;
				}
				using FileStream input = File.OpenRead(cachePath);
				using BinaryReader reader = new BinaryReader(input);
				if (CacheHelpers.ReadAssemblyWasModified(reader, assembly))
				{
					RiskOfWaitingReduxPlugin.Logger.LogInfo((object)("PostProcessing cache for " + assembly.FullName + " is outdated - creating new cache"));
					return false;
				}
				collection = CacheHelpers.ReadTypeCollection(reader, assembly);
			}
			catch (Exception arg)
			{
				RiskOfWaitingReduxPlugin.Logger.LogError((object)$"PostProcessing cache for {assembly.FullName} is likely corrupted - creating new cache: {arg}");
				return false;
			}
			foreach (Type item in collection)
			{
				RegisterSettingsType(ppManager, item, ((MemberInfo)item).GetCustomAttribute<PostProcessAttribute>(inherit: false));
			}
			return true;
		}
	}
	public static class SearchableAttributeCache
	{
		private static string cacheDirectory;

		public static void Init()
		{
			cacheDirectory = CacheHelpers.GetCacheDirectory("SearchableAttributeCache");
			Directory.CreateDirectory(cacheDirectory);
			RiskOfWaitingReduxPlugin.Harmony.PatchAll(typeof(SearchableAttributeCache));
		}

		[HarmonyPrefix]
		[HarmonyPatch(typeof(SearchableAttribute), "ScanAssembly")]
		public static bool UseCacheOrScanAssembly(Assembly assembly)
		{
			if (!SearchableAttribute.assemblyBlacklist.Add(assembly.FullName))
			{
				return false;
			}
			if (assembly.GetCustomAttribute<OptInAttribute>() == null)
			{
				return false;
			}
			string cachePath = Path.Combine(cacheDirectory, assembly.FullName);
			if (!TryLoadFromCache(assembly, cachePath))
			{
				RegisterAttributesInAssembly(assembly, out var typeTargets, out var memberTargets);
				CreateCache(assembly, cachePath, typeTargets, memberTargets);
			}
			return false;
		}

		private static SearchableAttribute[] GetSearchableAttributesOnMember(MemberInfo member)
		{
			return (SearchableAttribute[])(object)Attribute.GetCustomAttributes(member, typeof(SearchableAttribute), inherit: false);
		}

		private static void RegisterAttributesInAssembly(Assembly assembly, out List<Type> typeTargets, out List<CacheHelpers.SerializableMembers> memberTargets)
		{
			typeTargets = new List<Type>();
			memberTargets = new List<CacheHelpers.SerializableMembers>();
			Type[] types = assembly.GetTypes();
			foreach (Type type in types)
			{
				SearchableAttribute[] array = Array.Empty<SearchableAttribute>();
				try
				{
					array = GetSearchableAttributesOnMember(type);
				}
				catch (Exception ex)
				{
					RiskOfWaitingReduxPlugin.Logger.LogDebug((object)("ScanAssembly GetSearchableAttributesOnMember failed for :  " + type.FullName + Environment.NewLine + ex));
				}
				if (array.Length != 0)
				{
					typeTargets.Add(type);
					SearchableAttribute[] array2 = array;
					foreach (SearchableAttribute val in array2)
					{
						try
						{
							SearchableAttribute.RegisterAttribute(val, (object)type);
						}
						catch (Exception ex2)
						{
							RiskOfWaitingReduxPlugin.Logger.LogDebug((object)("SearchableAttribute.RegisterAttribute(attribute, type) failed for : " + type.FullName + Environment.NewLine + ex2));
						}
					}
				}
				List<ushort> list = null;
				bool flag = false;
				MemberInfo[] array3 = Array.Empty<MemberInfo>();
				try
				{
					array3 = GetScannableMembersFromType(type);
				}
				catch (Exception ex3)
				{
					RiskOfWaitingReduxPlugin.Logger.LogDebug((object)("type.GetMembers failed for : " + type.FullName + Environment.NewLine + ex3));
				}
				int serializableMembersCount = CacheHelpers.GetSerializableMembersCount(array3);
				for (ushort num = 0; num < serializableMembersCount; num++)
				{
					MemberInfo memberInfo = array3[num];
					SearchableAttribute[] array4 = Array.Empty<SearchableAttribute>();
					try
					{
						array4 = GetSearchableAttributesOnMember(memberInfo);
					}
					catch (Exception ex4)
					{
						RiskOfWaitingReduxPlugin.Logger.LogDebug((object)("GetSearchableAttributesOnMember failed for : " + type.FullName + Environment.NewLine + memberInfo.Name + Environment.NewLine + ex4));
					}
					if (array4.Length != 0)
					{
						if (!flag)
						{
							flag = true;
							list = new List<ushort>();
						}
						list.Add(num);
						SearchableAttribute[] array2 = array4;
						foreach (SearchableAttribute val2 in array2)
						{
							try
							{
								SearchableAttribute.RegisterAttribute(val2, (object)memberInfo);
							}
							catch (Exception ex5)
							{
								RiskOfWaitingReduxPlugin.Logger.LogDebug((object)("SearchableAttribute.RegisterAttribute(attribute, memberInfo) failed for : " + type.FullName + Environment.NewLine + memberInfo.Name + Environment.NewLine + ex5));
							}
						}
					}
				}
				if (flag)
				{
					memberTargets.Add(new CacheHelpers.SerializableMembers
					{
						type = type,
						membersIndices = list
					});
				}
			}
		}

		private static MemberInfo[] GetScannableMembersFromType(Type type)
		{
			return type.GetMembers(BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
		}

		private static void CreateCache(Assembly assembly, string cachePath, List<Type> typeTargets, List<CacheHelpers.SerializableMembers> memberTargets)
		{
			using FileStream output = File.OpenWrite(cachePath);
			using BinaryWriter writer = new BinaryWriter(output);
			CacheHelpers.WriteAssemblyIdentifer(writer, assembly);
			CacheHelpers.WriteTypeCollection(writer, typeTargets);
			CacheHelpers.WriteMembersCollection(writer, memberTargets);
		}

		private static bool TryLoadFromCache(Assembly assembly, string cachePath)
		{
			new List<(SearchableAttribute, object)>();
			ICollection<Type> collection;
			ICollection<MemberInfo> collection2;
			try
			{
				if (!File.Exists(cachePath))
				{
					RiskOfWaitingReduxPlugin.Logger.LogInfo((object)("SearchableAttribute cache for " + assembly.FullName + " doesn't exist - creating new cache"));
					return false;
				}
				using FileStream input = File.OpenRead(cachePath);
				using BinaryReader reader = new BinaryReader(input);
				if (CacheHelpers.ReadAssemblyWasModified(reader, assembly))
				{
					RiskOfWaitingReduxPlugin.Logger.LogInfo((object)("SearchableAttribute cache for " + assembly.FullName + " is outdated - creating new cache"));
					return false;
				}
				collection = CacheHelpers.ReadTypeCollection(reader, assembly);
				collection2 = CacheHelpers.ReadMembersCollection(reader, assembly, GetScannableMembersFromType);
			}
			catch (Exception arg)
			{
				RiskOfWaitingReduxPlugin.Logger.LogError((object)$"SearchableAttribute cache for {assembly.FullName} is likely corrupted - creating new cache: {arg}");
				return false;
			}
			foreach (Type item in collection)
			{
				SearchableAttribute[] searchableAttributesOnMember = GetSearchableAttributesOnMember(item);
				for (int i = 0; i < searchableAttributesOnMember.Length; i++)
				{
					SearchableAttribute.RegisterAttribute(searchableAttributesOnMember[i], (object)item);
				}
			}
			foreach (MemberInfo item2 in collection2)
			{
				SearchableAttribute[] searchableAttributesOnMember = GetSearchableAttributesOnMember(item2);
				for (int i = 0; i < searchableAttributesOnMember.Length; i++)
				{
					SearchableAttribute.RegisterAttribute(searchableAttributesOnMember[i], (object)item2);
				}
			}
			return true;
		}
	}
}
namespace System.Runtime.CompilerServices
{
	[AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)]
	internal sealed class IgnoresAccessChecksToAttribute : Attribute
	{
		internal IgnoresAccessChecksToAttribute(string assemblyName)
		{
		}
	}
}