Decompiled source of UnityMDK v1.3.0

UnityMDK.dll

Decompiled 6 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 System.Text;
using System.Text.RegularExpressions;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using UnityEngine;
using UnityEngine.SceneManagement;
using UnityEngine.UIElements;
using UnityMDK.Injection;
using UnityMDK.Logging;
using UnityMDK.Patches;

[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("")]
[assembly: AssemblyCompany("Saradora")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("0.2.0.0")]
[assembly: AssemblyInformationalVersion("0.2.0")]
[assembly: AssemblyProduct("UnityMDK")]
[assembly: AssemblyTitle("UnityMDK")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("0.2.0.0")]
[module: UnverifiableCode]
namespace UnityMDK
{
	[BepInPlugin("Saradora.UnityMDK", "Unity MDK", "1.3.0")]
	public class PluginInitializer : BaseUnityPlugin
	{
		internal static readonly Harmony HarmonyInstance = new Harmony("Saradora.UnityMDK");

		private void Awake()
		{
			HarmonyInstance.PatchAll();
			UnityEngine_Object_Patching.PatchGenericInstantiate();
			SceneManager.sceneLoaded += OnSceneLoaded;
		}

		private static void OnSceneLoaded(Scene scene, LoadSceneMode loadMode)
		{
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			SceneManager.sceneLoaded -= OnSceneLoaded;
			new GameObject("Unity Injector (instance)").AddComponent<UnityMDK>();
		}
	}
	[Initializer(0)]
	public static class PrefabPatcher
	{
		private static readonly SortedDictionary<string, string> _prefabs = new SortedDictionary<string, string>();

		private static readonly List<GameObject> _patchedPrefabs = new List<GameObject>();

		[Initializer(0)]
		private static void Init()
		{
			SceneManager.sceneLoaded += OnSceneLoaded;
		}

		private static void OnSceneLoading(int scene)
		{
			PatchPrefabs();
		}

		private static void OnSceneLoaded(Scene scene, LoadSceneMode loadSceneMode)
		{
			PatchPrefabs();
		}

		private static void PatchPrefabs()
		{
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			if (SceneInjection.PrefabsToPatch.Count <= 0)
			{
				return;
			}
			GameObject[] array = Resources.FindObjectsOfTypeAll<GameObject>();
			foreach (GameObject val in array)
			{
				if ((Object)(object)val.transform.parent != (Object)null)
				{
					continue;
				}
				Scene scene = val.scene;
				if (((Scene)(ref scene)).IsValid() || _patchedPrefabs.Contains(val))
				{
					continue;
				}
				_patchedPrefabs.Add(val);
				if (!SceneInjection.PrefabsToPatch.TryGetValue(((Object)val).name, out var value))
				{
					continue;
				}
				foreach (IPrefabInjector item in value)
				{
					item.OnInject(val);
				}
				SceneInjection.PrefabsToPatch.Remove(((Object)val).name);
			}
		}

		private static void LogPrefab(GameObject gameObject, ref int prefabsLogged)
		{
			string name = ((Object)gameObject).name;
			string key = "P" + StringUtilsExtensions.ToPascalCase(name);
			if (_prefabs.TryGetValue(key, out var value))
			{
				if (value != name)
				{
					Log.Error("Couldn't log prefab " + name + " because its Pascal variant " + value + " already exists...");
				}
			}
			else
			{
				_prefabs.Add(key, name);
				prefabsLogged++;
			}
		}

		private static void OnApplicationQuitting()
		{
			if (_prefabs.Count <= 0)
			{
				return;
			}
			string directoryName = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
			if (string.IsNullOrEmpty(directoryName))
			{
				Log.Error("Couldn't find path for assembly");
				return;
			}
			using FileStream stream = File.Open(directoryName + "/PrefabList.cs", FileMode.Create, FileAccess.Write);
			using StreamWriter streamWriter = new StreamWriter(stream);
			StringBuilder stringBuilder = new StringBuilder();
			stringBuilder.AppendLine("// ----- AUTO-GENERATED CODE ----- //");
			stringBuilder.AppendLine("");
			stringBuilder.AppendLine("public class PrefabList");
			stringBuilder.AppendLine("{");
			foreach (var (text3, text4) in _prefabs)
			{
				stringBuilder.AppendLine("\tpublic const string " + text3 + " = \"" + text4 + "\";");
			}
			stringBuilder.AppendLine("}");
			streamWriter.Write(stringBuilder.ToString());
		}
	}
	public static class PrefabUtils
	{
		private static GameObject _prefabRoot;

		private static GameObject PrefabRoot
		{
			get
			{
				//IL_0017: Unknown result type (might be due to invalid IL or missing references)
				//IL_0021: Expected O, but got Unknown
				if (Object.op_Implicit((Object)(object)_prefabRoot))
				{
					return _prefabRoot;
				}
				_prefabRoot = new GameObject("PrefabRoot");
				_prefabRoot.SetActive(false);
				((Object)_prefabRoot).hideFlags = (HideFlags)61;
				return _prefabRoot;
			}
		}

		public static GameObject GetEmptyPrefab(string name)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: Expected O, but got Unknown
			GameObject val = new GameObject(name)
			{
				hideFlags = (HideFlags)61
			};
			val.transform.SetParent(PrefabRoot.transform);
			return val;
		}
	}
	public class UnityMDK : MonoBehaviour
	{
		public const string ModGuid = "Saradora.UnityMDK";

		public const string ModVersion = "1.3.0";

		public const string ModName = "Unity MDK";

		public static UnityMDK Instance { get; private set; }

		private void Awake()
		{
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)Instance != (Object)null)
			{
				Object.Destroy((Object)(object)((Component)this).gameObject);
				return;
			}
			SceneInjection.Initialize();
			InjectScene(((Component)this).gameObject.scene);
			SceneManager.sceneLoaded += OnSceneLoaded;
			Instance = this;
			Object.DontDestroyOnLoad((Object)(object)((Component)this).gameObject);
		}

		private void OnSceneLoaded(Scene scene, LoadSceneMode loadMode)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			InjectScene(scene);
		}

		private void InjectScene(Scene scene)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			((MonoBehaviour)this).StartCoroutine(InjectionRoutine(scene));
		}

		private static IEnumerator InjectionRoutine(Scene scene)
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			SceneInjection.InjectScene(scene);
			SceneInjection.ConstructScene(scene, EConstructorEvent.AfterAwake);
			yield return null;
			SceneInjection.ConstructScene(scene, EConstructorEvent.AfterStart);
			yield return null;
			SceneInjection.ConstructScene(scene, EConstructorEvent.AfterFirstUpdate);
		}
	}
}
namespace UnityMDK.Reflection
{
	public static class ReflectionUtility
	{
		private static readonly BindingFlags DefaultBindingFlags = BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic;

		public static void InvokeMethod(this object target, string methodName)
		{
			MethodInfo method = target.GetType().GetMethod(methodName, DefaultBindingFlags);
			if ((object)method == null)
			{
				Log.Error("Method " + methodName + " not found");
			}
			else
			{
				method.Invoke(target, null);
			}
		}

		public static TReturn InvokeMethod<TReturn>(this object target, string methodName)
		{
			MethodInfo method = target.GetType().GetMethod(methodName, DefaultBindingFlags);
			if ((object)method == null)
			{
				Log.Error("Method " + methodName + " not found");
				return default(TReturn);
			}
			object obj = method.Invoke(target, null);
			if (obj == null)
			{
				return default(TReturn);
			}
			if (obj is TReturn)
			{
				return (TReturn)obj;
			}
			throw new ArgumentException("Method " + methodName + " isn't of type " + typeof(TReturn).Name);
		}

		public static bool TryGetField<TObject>(this object target, string fieldName, out TObject outObject)
		{
			if (target.TryGetField(fieldName, out var outObject2) && outObject2 is TObject val)
			{
				outObject = val;
				return true;
			}
			outObject = default(TObject);
			return false;
		}

		public static bool TryGetField(this object target, string fieldName, out object outObject)
		{
			FieldInfo field = target.GetType().GetField(fieldName, DefaultBindingFlags);
			if ((object)field == null)
			{
				outObject = null;
				return false;
			}
			outObject = field.GetValue(target);
			return true;
		}

		public static bool TryGetProperty<TObject>(this object target, string fieldName, out TObject outObject)
		{
			PropertyInfo property = target.GetType().GetProperty(fieldName, DefaultBindingFlags);
			if ((object)property == null)
			{
				outObject = default(TObject);
				return false;
			}
			if (property.GetValue(target) is TObject val)
			{
				outObject = val;
				return true;
			}
			outObject = default(TObject);
			return true;
		}

		public static void SetProperty<TObject>(this object target, string propertyName, TObject value)
		{
			PropertyInfo property = target.GetType().GetProperty(propertyName, DefaultBindingFlags);
			if ((object)property == null)
			{
				Log.Error("Field " + propertyName + " not found");
			}
			else if (property.PropertyType != typeof(TObject))
			{
				Log.Error($"Property {propertyName} isn't of type {typeof(TObject)}");
			}
			else
			{
				property.SetValue(target, value);
			}
		}

		public static TObject GetField<TObject>(this object target, string fieldName)
		{
			object obj = target.GetType().GetField(fieldName, DefaultBindingFlags)?.GetValue(target);
			if (obj is TObject)
			{
				return (TObject)obj;
			}
			return default(TObject);
		}

		public static void SetField<TObject>(this object target, string fieldName, TObject value)
		{
			FieldInfo field = target.GetType().GetField(fieldName, DefaultBindingFlags);
			if ((object)field == null)
			{
				Log.Error("Field " + fieldName + " not found");
			}
			else if (field.GetValue(target) is TObject)
			{
				field.SetValue(target, value);
			}
		}
	}
}
namespace UnityMDK.Logging
{
	public static class Log
	{
		private static readonly Dictionary<Assembly, ManualLogSource> LOGSources = new Dictionary<Assembly, ManualLogSource>();

		public static void Print(object message)
		{
			GetLogger(Assembly.GetCallingAssembly()).LogInfo(message ?? "Null");
		}

		public static void Warning(object message)
		{
			GetLogger(Assembly.GetCallingAssembly()).LogWarning(message ?? "Null");
		}

		public static void Error(object message)
		{
			GetLogger(Assembly.GetCallingAssembly()).LogError(message ?? "Null");
		}

		public static void Exception(Exception exception)
		{
			GetLogger(Assembly.GetCallingAssembly()).LogError((object)(exception?.Message ?? "Null"));
		}

		[Conditional("DEBUG")]
		public static void DebugPrint(object message)
		{
			Print(message);
		}

		[Conditional("DEBUG")]
		public static void DebugWarning(object message)
		{
			Warning(message);
		}

		[Conditional("DEBUG")]
		public static void DebugError(object message)
		{
			Error(message);
		}

		[Conditional("DEBUG")]
		public static void DebugException(Exception exception)
		{
			Exception(exception);
		}

		private static ManualLogSource GetLogger(Assembly assembly)
		{
			if (LOGSources.TryGetValue(assembly, out var value))
			{
				return value;
			}
			LOGSources[assembly] = Logger.CreateLogSource(assembly.GetName().Name);
			return LOGSources[assembly];
		}
	}
}
namespace UnityMDK.Patches
{
	public static class MDKSceneManager
	{
		public static event Action<int> LoadingScene;

		internal static void InvokeLoadingScene(int scene)
		{
			MDKSceneManager.LoadingScene?.Invoke(scene);
		}
	}
	[HarmonyPatch(typeof(SceneManager))]
	public static class SceneManager_Patching
	{
		[HarmonyPrefix]
		[HarmonyPatch("LoadScene", new Type[]
		{
			typeof(string),
			typeof(LoadSceneMode)
		})]
		[HarmonyPatch("LoadScene", new Type[]
		{
			typeof(string),
			typeof(LoadSceneParameters)
		})]
		[HarmonyPatch("LoadSceneAsync", new Type[]
		{
			typeof(string),
			typeof(LoadSceneMode)
		})]
		[HarmonyPatch("LoadSceneAsync", new Type[]
		{
			typeof(string),
			typeof(LoadSceneParameters)
		})]
		private static void LoadScene_String_Prefix(string sceneName)
		{
			LoadScene_Int_Prefix(SceneUtility.GetBuildIndexByScenePath(sceneName));
		}

		[HarmonyPrefix]
		[HarmonyPatch("LoadScene", new Type[]
		{
			typeof(int),
			typeof(LoadSceneMode)
		})]
		[HarmonyPatch("LoadScene", new Type[]
		{
			typeof(int),
			typeof(LoadSceneParameters)
		})]
		[HarmonyPatch("LoadSceneAsync", new Type[]
		{
			typeof(int),
			typeof(LoadSceneMode)
		})]
		[HarmonyPatch("LoadSceneAsync", new Type[]
		{
			typeof(int),
			typeof(LoadSceneParameters)
		})]
		private static void LoadScene_Int_Prefix(int sceneBuildIndex)
		{
			if (sceneBuildIndex >= 0 && sceneBuildIndex < SceneManager.sceneCountInBuildSettings)
			{
				MDKSceneManager.InvokeLoadingScene(sceneBuildIndex);
			}
		}
	}
	[HarmonyPatch(typeof(GameObject))]
	internal static class UnityEngine_GameObject_Patching
	{
		[HarmonyPatch("AddComponent", new Type[] { typeof(Type) })]
		[HarmonyPostfix]
		private static void AddComponent_PostFix(ref Component __result)
		{
			if (__result != null)
			{
				SceneInjection.InjectComponent(__result);
			}
		}
	}
	[HarmonyPatch(typeof(Object))]
	internal static class UnityEngine_Object_Patching
	{
		[HarmonyPatch("Instantiate", new Type[]
		{
			typeof(Object),
			typeof(Transform),
			typeof(bool)
		})]
		[HarmonyPatch("Instantiate", new Type[] { typeof(Object) })]
		[HarmonyPrefix]
		private static void Instantiate_Prefix(ref Object original)
		{
			InjectInstance(original);
		}

		[HarmonyPatch("Internal_InstantiateSingleWithParent", new Type[]
		{
			typeof(Object),
			typeof(Transform),
			typeof(Vector3),
			typeof(Quaternion)
		})]
		[HarmonyPatch("Internal_InstantiateSingle", new Type[]
		{
			typeof(Object),
			typeof(Vector3),
			typeof(Quaternion)
		})]
		[HarmonyPrefix]
		private static void Internal_InstantiateSingle_Prefix(ref Object data)
		{
			InjectInstance(data);
		}

		[HarmonyPatch("Instantiate", new Type[]
		{
			typeof(Object),
			typeof(Transform),
			typeof(bool)
		})]
		[HarmonyPatch("Instantiate", new Type[] { typeof(Object) })]
		[HarmonyPostfix]
		private static void Instantiate_Postfix(ref Object __result)
		{
			InjectInstancePostFix(__result);
		}

		[HarmonyPatch("Internal_InstantiateSingleWithParent", new Type[]
		{
			typeof(Object),
			typeof(Transform),
			typeof(Vector3),
			typeof(Quaternion)
		})]
		[HarmonyPatch("Internal_InstantiateSingle", new Type[]
		{
			typeof(Object),
			typeof(Vector3),
			typeof(Quaternion)
		})]
		[HarmonyPostfix]
		private static void Internal_InstantiateSingle_Postfix(ref Object __result)
		{
			InjectInstancePostFix(__result);
		}

		internal static void PatchGenericInstantiate()
		{
			//IL_00ab: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00be: Expected O, but got Unknown
			//IL_00be: Expected O, but got Unknown
			MethodInfo[] methods = typeof(Object).GetMethods(BindingFlags.Static | BindingFlags.Public);
			MethodInfo methodInfo = null;
			MethodInfo[] array = methods;
			foreach (MethodInfo methodInfo2 in array)
			{
				if (methodInfo2.GetGenericArguments().Length == 1 && !(methodInfo2.Name != "Instantiate") && methodInfo2.GetParameters().Length == 1)
				{
					methodInfo = methodInfo2;
					break;
				}
			}
			methodInfo = methodInfo.MakeGenericMethod(typeof(Object));
			MethodInfo method = typeof(UnityEngine_Object_Patching).GetMethod("GenericInstantiate_Prefix", BindingFlags.Static | BindingFlags.NonPublic);
			MethodInfo method2 = typeof(UnityEngine_Object_Patching).GetMethod("GenericInstantiate_Postfix", BindingFlags.Static | BindingFlags.NonPublic);
			PluginInitializer.HarmonyInstance.Patch((MethodBase)methodInfo, new HarmonyMethod(method), new HarmonyMethod(method2), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
		}

		private static void GenericInstantiate_Prefix(Object original)
		{
			InjectInstance(original);
		}

		private static void GenericInstantiate_Postfix(Object __result)
		{
			InjectInstancePostFix(__result);
		}

		private static void InjectInstance(Object data)
		{
			GameObject val = (GameObject)(object)((data is GameObject) ? data : null);
			if (val == null)
			{
				Component val2 = (Component)(object)((data is Component) ? data : null);
				if (val2 != null)
				{
					SceneInjection.InjectGameObject(val2.gameObject);
				}
			}
			else
			{
				SceneInjection.InjectGameObject(val);
			}
		}

		private static void InjectInstancePostFix(Object data)
		{
			GameObject val = (GameObject)(object)((data is GameObject) ? data : null);
			if (val == null)
			{
				Component val2 = (Component)(object)((data is Component) ? data : null);
				if (val2 != null)
				{
					SceneInjection.InjectGameObjectPost(val2.gameObject);
				}
			}
			else
			{
				SceneInjection.InjectGameObjectPost(val);
			}
		}
	}
}
namespace UnityMDK.Injection
{
	public readonly struct AddComponentInjector : IInjectable
	{
		private readonly Type _type;

		public AddComponentInjector(Type type)
		{
			if (!typeof(Component).IsAssignableFrom(type))
			{
				throw new ArgumentException($"{type} is not a component.");
			}
			_type = type;
		}

		public bool CanBeInjected(Component component)
		{
			return !Object.op_Implicit((Object)(object)component.GetComponent(_type));
		}

		public void Inject(Component component)
		{
			component.gameObject.AddComponent(_type);
		}
	}
	public abstract class ComponentInjector : IInjectable
	{
		public abstract bool CanBeInjected(Component component);

		public abstract void Inject(Component component);
	}
	public abstract class ComponentInjector<TComponent> : IInjectable where TComponent : Component
	{
		public bool CanBeInjected(Component component)
		{
			return CanBeInjected((TComponent)(object)component);
		}

		public void Inject(Component component)
		{
			Inject((TComponent)(object)component);
		}

		protected abstract bool CanBeInjected(TComponent component);

		protected abstract void Inject(TComponent component);
	}
	public enum EConstructorEvent
	{
		AfterAwake,
		AfterStart,
		AfterFirstUpdate
	}
	internal interface IInjectable
	{
		bool CanBeInjected(Component component);

		void Inject(Component component);
	}
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)]
	public class InitializerAttribute : Attribute
	{
		public readonly int Order;

		public InitializerAttribute(int order = 0)
		{
			Order = order;
		}
	}
	[AttributeUsage(AttributeTargets.Class)]
	public class InjectToComponentAttribute : Attribute
	{
		internal readonly Type ComponentType;

		internal readonly bool PostAwake;

		public InjectToComponentAttribute(Type type, bool postAwake = false)
		{
			if (!typeof(Component).IsAssignableFrom(type))
			{
				throw new ArgumentException(type.Name + " isn't a Component.");
			}
			PostAwake = postAwake;
			ComponentType = type;
		}
	}
	[AttributeUsage(AttributeTargets.Class)]
	public class InjectToPrefabAttribute : Attribute
	{
		internal string PrefabName { get; }

		public InjectToPrefabAttribute(string prefabName)
		{
			PrefabName = prefabName;
		}
	}
	public interface IPrefabInjector
	{
		protected internal void OnInject(GameObject obj);
	}
	[AttributeUsage(AttributeTargets.Class)]
	public class SceneConstructorAttribute : Attribute
	{
		public EConstructorEvent Event { get; }

		public SceneConstructorAttribute()
		{
			Event = EConstructorEvent.AfterAwake;
		}

		public SceneConstructorAttribute(EConstructorEvent @event)
		{
			Event = @event;
		}
	}
	public static class SceneInjection
	{
		private static readonly SortedList<int, List<MethodInfo>> Initializers = new SortedList<int, List<MethodInfo>>();

		private static readonly Dictionary<EConstructorEvent, List<MethodInfo>> SceneConstructors = new Dictionary<EConstructorEvent, List<MethodInfo>>();

		private static readonly Dictionary<Type, List<IInjectable>> ObjectPreInjectors = new Dictionary<Type, List<IInjectable>>();

		private static readonly Dictionary<Type, List<IInjectable>> ObjectPostInjectors = new Dictionary<Type, List<IInjectable>>();

		private static readonly List<GameObject> ConstructedPrefabs = new List<GameObject>();

		private static readonly List<int> ConstructedScenes = new List<int>();

		internal static readonly Dictionary<string, List<IPrefabInjector>> PrefabsToPatch = new Dictionary<string, List<IPrefabInjector>>();

		private static bool _initialized;

		private static readonly Type ComponentType = typeof(Component);

		private static readonly Type InjectAttributeType = typeof(InjectToComponentAttribute);

		private static readonly Type IPrefabInjectorType = typeof(IPrefabInjector);

		private static Scene _dontDestroyOnLoadScene;

		public static void Initialize()
		{
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Expected O, but got Unknown
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Expected O, but got Unknown
			if (_initialized)
			{
				return;
			}
			_initialized = true;
			GameObject val = new GameObject("Dummy");
			Object.DontDestroyOnLoad((Object)val);
			_dontDestroyOnLoadScene = val.scene;
			Object.Destroy((Object)val);
			foreach (EConstructorEvent value in Enum.GetValues(typeof(EConstructorEvent)))
			{
				SceneConstructors.Add(value, new List<MethodInfo>());
			}
			Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies();
			foreach (Assembly assembly in assemblies)
			{
				try
				{
					Type[] types = assembly.GetTypes();
					foreach (Type type in types)
					{
						try
						{
							RegisterPrefabInjector(type);
							RegisterInjector(type);
							RegisterSceneConstructor(type);
							RegisterInitializer(type);
						}
						catch
						{
							string text = type.Assembly.GetName().Name + ".";
							if (!string.IsNullOrEmpty(type.Namespace))
							{
								text = text + type.Namespace + ".";
							}
							text += type.Name;
							Log.Warning("Failed analysis of [" + text + "]. If this type doesn't use UnityMDK, this message can be safely ignored.");
						}
					}
				}
				catch
				{
					Log.Warning("Failed analysis of [" + assembly.GetName().Name + "]. If this assembly doesn't use UnityMDK, this message can be safely ignored.");
				}
			}
			RunInitializers();
			SceneManager.sceneUnloaded += OnSceneUnloaded;
		}

		public static void AddComponentInjector<TComponent>(ComponentInjector injector, bool postAwake = false) where TComponent : Component
		{
			Type typeFromHandle = typeof(TComponent);
			if (typeFromHandle == ComponentType)
			{
				Log.Error("Specified component type is too vague");
			}
			else
			{
				DoAddComponentInjector(typeFromHandle, injector, postAwake);
			}
		}

		public static void AddComponentInjector<TComponent>(ComponentInjector<TComponent> injector, bool postAwake = false) where TComponent : Component
		{
			Type typeFromHandle = typeof(TComponent);
			if (typeFromHandle == ComponentType)
			{
				Log.Error("Specified component type is too vague");
			}
			else
			{
				DoAddComponentInjector(typeFromHandle, injector, postAwake);
			}
		}

		private static void DoAddComponentInjector(Type type, IInjectable injectable, bool postAwake)
		{
			if (postAwake)
			{
				if (!ObjectPostInjectors.ContainsKey(type))
				{
					ObjectPostInjectors.Add(type, new List<IInjectable>());
				}
				ObjectPostInjectors[type].Add(injectable);
			}
			else
			{
				if (!ObjectPreInjectors.ContainsKey(type))
				{
					ObjectPreInjectors.Add(type, new List<IInjectable>());
				}
				ObjectPreInjectors[type].Add(injectable);
			}
			Log.Warning($"Constructable: Adding {injectable.GetType()} to {type}");
		}

		public static void RemoveComponentInjector<TComponent>(bool postAwake = false) where TComponent : Component
		{
			DoRemoveComponentInjector(typeof(TComponent), postAwake);
		}

		private static void DoRemoveComponentInjector(Type type, bool postAwake)
		{
			if (postAwake)
			{
				ObjectPostInjectors.Remove(type);
			}
			else
			{
				ObjectPreInjectors.Remove(type);
			}
		}

		private static void RegisterInjector(Type type)
		{
			if (!type.IsDefined(InjectAttributeType, inherit: false) || !ComponentType.IsAssignableFrom(type))
			{
				return;
			}
			InjectToComponentAttribute injectToComponentAttribute = (InjectToComponentAttribute)type.GetCustomAttribute(InjectAttributeType);
			if ((object)injectToComponentAttribute.ComponentType == null)
			{
				return;
			}
			if (injectToComponentAttribute.PostAwake)
			{
				if (!ObjectPostInjectors.ContainsKey(injectToComponentAttribute.ComponentType))
				{
					ObjectPostInjectors.Add(injectToComponentAttribute.ComponentType, new List<IInjectable>());
				}
				ObjectPostInjectors[injectToComponentAttribute.ComponentType].Add(new AddComponentInjector(type));
			}
			else
			{
				if (!ObjectPreInjectors.ContainsKey(injectToComponentAttribute.ComponentType))
				{
					ObjectPreInjectors.Add(injectToComponentAttribute.ComponentType, new List<IInjectable>());
				}
				ObjectPreInjectors[injectToComponentAttribute.ComponentType].Add(new AddComponentInjector(type));
			}
			Log.Warning($"Constructable: Adding {type} to {injectToComponentAttribute.ComponentType}");
		}

		private static void RegisterPrefabInjector(Type type)
		{
			if (!IPrefabInjectorType.IsAssignableFrom(type))
			{
				return;
			}
			InjectToPrefabAttribute customAttribute = type.GetCustomAttribute<InjectToPrefabAttribute>(inherit: true);
			if (customAttribute == null || string.IsNullOrEmpty(customAttribute.PrefabName))
			{
				return;
			}
			if (!PrefabsToPatch.ContainsKey(customAttribute.PrefabName))
			{
				PrefabsToPatch.Add(customAttribute.PrefabName, new List<IPrefabInjector>());
			}
			try
			{
				IPrefabInjector prefabInjector = (IPrefabInjector)Activator.CreateInstance(type);
				PrefabsToPatch[customAttribute.PrefabName].Add(prefabInjector);
				Log.Warning("Added Prefab '" + customAttribute.PrefabName + "' patch: " + prefabInjector.GetType().Name);
			}
			catch (Exception exception)
			{
				Log.Exception(exception);
			}
		}

		private static void RegisterSceneConstructor(Type type)
		{
			SceneConstructorAttribute sceneConstructorAttribute = (SceneConstructorAttribute)type.GetCustomAttribute(typeof(SceneConstructorAttribute));
			if (sceneConstructorAttribute == null)
			{
				return;
			}
			MethodInfo method = type.GetMethod("SceneConstructor", BindingFlags.Static | BindingFlags.NonPublic);
			if ((object)method != null)
			{
				ParameterInfo[] parameters = method.GetParameters();
				if (parameters.Length == 1 && !(parameters[0].ParameterType != typeof(Scene)))
				{
					Log.Warning($"Constructable: Adding {type} to scene constructors");
					SceneConstructors[sceneConstructorAttribute.Event].Add(method);
				}
			}
		}

		private static void RegisterInitializer(Type type)
		{
			InitializerAttribute customAttribute = type.GetCustomAttribute<InitializerAttribute>();
			if (customAttribute == null)
			{
				return;
			}
			SortedList<int, List<MethodInfo>> sortedList = new SortedList<int, List<MethodInfo>>();
			MethodInfo[] methods = type.GetMethods(BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
			foreach (MethodInfo methodInfo in methods)
			{
				InitializerAttribute customAttribute2 = methodInfo.GetCustomAttribute<InitializerAttribute>();
				if (customAttribute2 != null && methodInfo.GetParameters().Length == 0)
				{
					if (!sortedList.ContainsKey(customAttribute2.Order))
					{
						sortedList.Add(customAttribute2.Order, new List<MethodInfo>());
					}
					sortedList[customAttribute2.Order].Add(methodInfo);
				}
			}
			if (!Initializers.ContainsKey(customAttribute.Order))
			{
				Initializers.Add(customAttribute.Order, new List<MethodInfo>());
			}
			foreach (KeyValuePair<int, List<MethodInfo>> item in sortedList)
			{
				Initializers[customAttribute.Order].AddRange(item.Value);
			}
		}

		private static void RunInitializers()
		{
			object[] parameters = Array.Empty<object>();
			foreach (KeyValuePair<int, List<MethodInfo>> initializer in Initializers)
			{
				foreach (MethodInfo item in initializer.Value)
				{
					item.Invoke(null, parameters);
				}
			}
		}

		private static void OnSceneUnloaded(Scene scene)
		{
			ConstructedScenes.Remove(((Scene)(ref scene)).handle);
		}

		internal static void InjectScene(Scene scene)
		{
			if (!ConstructedScenes.Contains(((Scene)(ref scene)).handle))
			{
				Log.Print("Injecting scene: " + ((Scene)(ref scene)).name);
				GameObject[] rootGameObjects = ((Scene)(ref scene)).GetRootGameObjects();
				for (int i = 0; i < rootGameObjects.Length; i++)
				{
					InjectGameObject(rootGameObjects[i]);
				}
				ConstructedScenes.Add(((Scene)(ref scene)).handle);
			}
		}

		internal static void ConstructScene(Scene scene, EConstructorEvent eventType)
		{
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			object[] parameters = new object[1] { scene };
			Log.Print("Constructing scene " + ((Scene)(ref scene)).name + " [" + eventType.ToString() + "]");
			if (!SceneConstructors.TryGetValue(eventType, out var value))
			{
				return;
			}
			foreach (MethodInfo item in value)
			{
				item.Invoke(null, parameters);
			}
			InjectDontDestroyOnLoadScene();
		}

		private static void InjectDontDestroyOnLoadScene()
		{
			if (((Scene)(ref _dontDestroyOnLoadScene)).IsValid())
			{
				GameObject[] rootGameObjects = ((Scene)(ref _dontDestroyOnLoadScene)).GetRootGameObjects();
				for (int i = 0; i < rootGameObjects.Length; i++)
				{
					InjectGameObject(rootGameObjects[i]);
				}
			}
		}

		internal static void InjectGameObject(GameObject gameObject)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			Scene scene = gameObject.scene;
			if (((Scene)(ref scene)).IsValid())
			{
				List<int> constructedScenes = ConstructedScenes;
				scene = gameObject.scene;
				if (!constructedScenes.Contains(((Scene)(ref scene)).handle))
				{
					DoInjectGameObject(gameObject);
				}
			}
			else if (!ConstructedPrefabs.Contains(gameObject))
			{
				DoInjectGameObject(gameObject);
				ConstructedPrefabs.Add(gameObject);
			}
		}

		internal static void InjectGameObjectPost(GameObject gameObject)
		{
			foreach (KeyValuePair<Type, List<IInjectable>> objectPostInjector in ObjectPostInjectors)
			{
				objectPostInjector.Deconstruct(out var key, out var value);
				Type type = key;
				List<IInjectable> list = value;
				Component[] componentsInChildren = gameObject.GetComponentsInChildren(type, true);
				foreach (Component component in componentsInChildren)
				{
					foreach (IInjectable item in list)
					{
						if (item.CanBeInjected(component))
						{
							item.Inject(component);
						}
					}
				}
			}
		}

		private static void DoInjectGameObject(GameObject gameObject)
		{
			foreach (KeyValuePair<Type, List<IInjectable>> objectPreInjector in ObjectPreInjectors)
			{
				objectPreInjector.Deconstruct(out var key, out var value);
				Type type = key;
				List<IInjectable> list = value;
				Component[] componentsInChildren = gameObject.GetComponentsInChildren(type, true);
				foreach (Component component in componentsInChildren)
				{
					foreach (IInjectable item in list)
					{
						if (item.CanBeInjected(component))
						{
							item.Inject(component);
						}
					}
				}
			}
		}

		internal static void InjectComponent(Component component)
		{
			Type type = ((object)component).GetType();
			Type key;
			List<IInjectable> value;
			foreach (KeyValuePair<Type, List<IInjectable>> objectPreInjector in ObjectPreInjectors)
			{
				objectPreInjector.Deconstruct(out key, out value);
				Type type2 = key;
				List<IInjectable> list = value;
				if (!type2.IsAssignableFrom(type))
				{
					continue;
				}
				foreach (IInjectable item in list)
				{
					if (item.CanBeInjected(component))
					{
						item.Inject(component);
					}
				}
			}
			foreach (KeyValuePair<Type, List<IInjectable>> objectPostInjector in ObjectPostInjectors)
			{
				objectPostInjector.Deconstruct(out key, out value);
				Type type3 = key;
				List<IInjectable> list2 = value;
				if (!type3.IsAssignableFrom(type))
				{
					continue;
				}
				foreach (IInjectable item2 in list2)
				{
					if (item2.CanBeInjected(component))
					{
						item2.Inject(component);
					}
				}
			}
		}
	}
}
namespace UnityMDK.Config
{
	[AttributeUsage(AttributeTargets.Property | AttributeTargets.Field)]
	public class ConfigSectionAttribute : Attribute
	{
		internal string Section;

		public ConfigSectionAttribute(string section)
		{
			Section = section;
		}
	}
	[AttributeUsage(AttributeTargets.Property | AttributeTargets.Field)]
	public class ConfigDescriptionAttribute : Attribute
	{
		internal string Description;

		public ConfigDescriptionAttribute(string description)
		{
			Description = description;
		}
	}
	public static class ConfigBinder
	{
		private static readonly Type ConfigDataType = typeof(IConfigData);

		private static ConfigFile _currentFile;

		public static void BindAll(ConfigFile cfg)
		{
			_currentFile = cfg;
			Type[] types = Assembly.GetCallingAssembly().GetTypes();
			for (int i = 0; i < types.Length; i++)
			{
				BindType(types[i]);
			}
			_currentFile = null;
		}

		private static void BindType(Type type)
		{
			string section = "General";
			MemberInfo[] members = type.GetMembers(BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
			foreach (MemberInfo memberInfo in members)
			{
				if (!memberInfo.MemberType.HasFlag((MemberTypes)0))
				{
					continue;
				}
				ConfigSectionAttribute customAttribute = memberInfo.GetCustomAttribute<ConfigSectionAttribute>();
				if (customAttribute != null)
				{
					section = customAttribute.Section;
				}
				string description = memberInfo.GetCustomAttribute<ConfigDescriptionAttribute>()?.Description;
				string input = memberInfo.Name.Replace("_", "");
				input = Regex.Replace(input, "\\b\\p{Ll}", (Match match) => match.Value.ToUpper());
				FieldInfo fieldInfo2 = ((memberInfo is PropertyInfo) ? type.GetField("<" + memberInfo.Name + ">k__BackingField", BindingFlags.Static | BindingFlags.NonPublic) : ((!(memberInfo is FieldInfo fieldInfo)) ? null : (fieldInfo.Name.Contains("k__BackingField") ? null : fieldInfo)));
				FieldInfo fieldInfo3 = fieldInfo2;
				if ((object)fieldInfo3 != null)
				{
					Type fieldType = fieldInfo3.FieldType;
					if (ConfigDataType.IsAssignableFrom(fieldType))
					{
						BindField(fieldInfo3, section, input, description);
					}
				}
			}
		}

		private static void BindField(FieldInfo fieldInfo, string section, string name, string description)
		{
			Type type = fieldInfo.FieldType.GetGenericArguments()[0];
			if (!TomlTypeConverter.CanConvert(type))
			{
				Log.Error("Type " + type.Name + " is not supported by the config system. Supported types: " + string.Join(", ", (from x in TomlTypeConverter.GetSupportedTypes()
					select x.Name).ToArray()));
				return;
			}
			IConfigData configData = (IConfigData)fieldInfo.GetValue(null);
			if (configData == null)
			{
				configData = (IConfigData)Activator.CreateInstance(typeof(ConfigData<>).MakeGenericType(type));
				fieldInfo.SetValue(null, configData);
			}
			configData.Bind(_currentFile, name, section, description);
		}
	}
	internal interface IConfigData
	{
		internal void Bind(ConfigFile cfg, string name, string section, string description);
	}
	public class ConfigData<T> : IConfigData
	{
		private ConfigEntry<T> _configEntry;

		private readonly T _defaultValue;

		public T Value => _configEntry.Value;

		public event Action<T> ConfigChanged;

		public static implicit operator T(ConfigData<T> config)
		{
			return config.Value;
		}

		public ConfigData(T defaultValue = default(T))
		{
			_defaultValue = defaultValue;
		}

		void IConfigData.Bind(ConfigFile cfg, string name, string section, string description)
		{
			if (_configEntry != null)
			{
				Log.Warning("Config " + name + " is already bound");
				return;
			}
			if (description == null)
			{
				_configEntry = cfg.Bind<T>(section, name, _defaultValue, (ConfigDescription)null);
			}
			else
			{
				_configEntry = cfg.Bind<T>(section, name, _defaultValue, description);
			}
			_configEntry.SettingChanged += OnSettingChanged;
		}

		private void OnSettingChanged(object sender, EventArgs e)
		{
			this.ConfigChanged?.Invoke(Value);
		}
	}
}
namespace System.Runtime.CompilerServices
{
	[AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)]
	internal sealed class IgnoresAccessChecksToAttribute : Attribute
	{
		public IgnoresAccessChecksToAttribute(string assemblyName)
		{
		}
	}
}