Decompiled source of Jotunn v2.21.2

plugins/Jotunn.dll

Decompiled 2 days ago
using System;
using System.CodeDom.Compiler;
using System.Collections;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.IO.Compression;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
using System.Reflection.Emit;
using System.Resources;
using System.Runtime.CompilerServices;
using System.Runtime.Serialization;
using System.Runtime.Versioning;
using System.Security.Cryptography;
using System.Security.Permissions;
using System.Text;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using Jotunn;
using Jotunn.Configs;
using Jotunn.Entities;
using Jotunn.Extensions;
using Jotunn.GUI;
using Jotunn.Managers;
using Jotunn.Managers.MockSystem;
using Jotunn.Utils;
using Microsoft.CodeAnalysis;
using Mono.Cecil.Cil;
using MonoMod.Cil;
using SimpleJson;
using SimpleJson.Reflection;
using SoftReferenceableAssets;
using TMPro;
using UnityEngine;
using UnityEngine.Audio;
using UnityEngine.EventSystems;
using UnityEngine.Events;
using UnityEngine.InputSystem;
using UnityEngine.InputSystem.LowLevel;
using UnityEngine.SceneManagement;
using UnityEngine.U2D;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: InternalsVisibleTo("JotunnTests")]
[assembly: InternalsVisibleTo("JotunnDoc")]
[assembly: TargetFramework(".NETFramework,Version=v4.6.2", FrameworkDisplayName = ".NET Framework 4.6.2")]
[assembly: AssemblyCompany("Valheim-Modding team")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyDescription("Jötunn (/ˈjɔːtʊn/, \"giant\") is a modding library for Valheim, with the goal of making the lives of mod developers easier.")]
[assembly: AssemblyFileVersion("2.21.2.0")]
[assembly: AssemblyInformationalVersion("2.21.2+05edc88f08287ea2dde0fe14c9a834f052ceb50a")]
[assembly: AssemblyProduct("JotunnLib")]
[assembly: AssemblyTitle("Jotunn")]
[assembly: AssemblyMetadata("RepositoryUrl", "https://github.com/Valheim-Modding/Jotunn")]
[assembly: NeutralResourcesLanguage("en")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("2.21.2.0")]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class IsReadOnlyAttribute : Attribute
	{
	}
}
internal class CompatibilityWindow : MonoBehaviour
{
	public ScrollRect scrollRect;

	public Text failedConnection;

	public Text localVersion;

	public Text remoteVersion;

	public Text errorMessages;

	public Button continueButton;

	public Button logFileButton;

	public Button troubleshootingButton;

	public void UpdateTextPositions()
	{
		//IL_003b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0040: Unknown result type (might be due to invalid IL or missing references)
		//IL_004d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0052: Unknown result type (might be due to invalid IL or missing references)
		//IL_0068: Unknown result type (might be due to invalid IL or missing references)
		//IL_0072: Unknown result type (might be due to invalid IL or missing references)
		//IL_0087: Unknown result type (might be due to invalid IL or missing references)
		//IL_0091: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a6: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ab: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ca: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d4: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ee: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f5: Expected O, but got Unknown
		float preferredHeight = failedConnection.preferredHeight;
		float preferredHeight2 = localVersion.preferredHeight;
		float preferredHeight3 = remoteVersion.preferredHeight;
		float preferredHeight4 = errorMessages.preferredHeight;
		Vector2 anchoredPosition = ((Graphic)localVersion).rectTransform.anchoredPosition;
		Vector2 anchoredPosition2 = ((Graphic)remoteVersion).rectTransform.anchoredPosition;
		float num = preferredHeight + 32f;
		((Graphic)localVersion).rectTransform.anchoredPosition = new Vector2(anchoredPosition.x, 0f - num);
		((Graphic)remoteVersion).rectTransform.anchoredPosition = new Vector2(anchoredPosition2.x, 0f - num);
		Vector2 anchoredPosition3 = ((Graphic)errorMessages).rectTransform.anchoredPosition;
		float num2 = num + Mathf.Max(preferredHeight2, preferredHeight3) + 32f;
		((Graphic)errorMessages).rectTransform.anchoredPosition = new Vector2(anchoredPosition3.x, 0f - num2);
		RectTransform val = (RectTransform)((Component)scrollRect.content).transform;
		val.SetSizeWithCurrentAnchors((Axis)1, num2 + preferredHeight4);
	}
}
public sealed class ConfigurationManagerAttributes
{
	public bool? ShowRangeAsPercent;

	public Action<ConfigEntryBase> CustomDrawer;

	public bool? Browsable;

	public string Category;

	public object DefaultValue;

	public bool? HideDefaultButton;

	public bool? HideSettingName;

	public string Description;

	public string DispName;

	public int? Order;

	public bool? ReadOnly;

	public bool? IsAdvanced;

	public Func<object, string> ObjToStr;

	public Func<string, object> StrToObj;

	private bool isAdminOnly;

	private bool isUnlocked;

	private static readonly PropertyInfo[] _myProperties = typeof(ConfigurationManagerAttributes).GetProperties(BindingFlags.Instance | BindingFlags.Public);

	private static readonly FieldInfo[] _myFields = typeof(ConfigurationManagerAttributes).GetFields(BindingFlags.Instance | BindingFlags.Public);

	public bool IsAdminOnly
	{
		get
		{
			return isAdminOnly;
		}
		set
		{
			isAdminOnly = value;
			bool flag = isAdminOnly && !SynchronizationManager.Instance.PlayerIsAdmin;
			IsUnlocked = !flag;
		}
	}

	public Color EntryColor { get; set; }

	public Color DescriptionColor { get; set; }

	public bool IsUnlocked
	{
		get
		{
			return isUnlocked;
		}
		internal set
		{
			ReadOnly = !value;
			HideDefaultButton = !value;
			isUnlocked = value;
		}
	}

	public ConfigurationManagerAttributes()
	{
		//IL_001b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0026: Unknown result type (might be due to invalid IL or missing references)
		EntryColor = new Color(1f, 0.631f, 0.235f, 1f);
		DescriptionColor = Color.white;
	}

	public void SetFromAttributes(object[] attribs)
	{
		if (attribs == null || attribs.Length == 0)
		{
			return;
		}
		foreach (object obj in attribs)
		{
			if (obj == null)
			{
				continue;
			}
			if (!(obj is DisplayNameAttribute displayNameAttribute))
			{
				if (!(obj is CategoryAttribute categoryAttribute))
				{
					if (!(obj is DescriptionAttribute descriptionAttribute))
					{
						if (!(obj is DefaultValueAttribute defaultValueAttribute))
						{
							if (!(obj is ReadOnlyAttribute readOnlyAttribute))
							{
								if (!(obj is BrowsableAttribute browsableAttribute))
								{
									if (obj is string text)
									{
										switch (text)
										{
										case "ReadOnly":
											ReadOnly = true;
											break;
										case "Browsable":
											Browsable = true;
											break;
										case "Unbrowsable":
										case "Hidden":
											Browsable = false;
											break;
										case "Advanced":
											IsAdvanced = true;
											break;
										}
										continue;
									}
									Type type = obj.GetType();
									if (!(type.Name == "ConfigurationManagerAttributes"))
									{
										break;
									}
									FieldInfo[] fields = type.GetFields(BindingFlags.Instance | BindingFlags.Public);
									foreach (var item in from my in _myProperties
										join other in fields on my.Name equals other.Name
										select new { my, other })
									{
										try
										{
											object obj2 = item.other.GetValue(obj);
											if (obj2 != null)
											{
												if (item.my.PropertyType != item.other.FieldType && typeof(Delegate).IsAssignableFrom(item.my.PropertyType))
												{
													obj2 = Delegate.CreateDelegate(item.my.PropertyType, ((Delegate)obj2).Target, ((Delegate)obj2).Method);
												}
												item.my.SetValue(this, obj2, null);
											}
										}
										catch (Exception ex)
										{
											Logger.LogWarning("Failed to copy value " + item.my.Name + " from provided tag object " + type.FullName + " - " + ex.Message);
										}
									}
									foreach (var item2 in from my in _myFields
										join other in fields on my.Name equals other.Name
										select new { my, other })
									{
										try
										{
											object obj3 = item2.other.GetValue(obj);
											if (obj3 != null)
											{
												if (item2.my.FieldType != item2.other.FieldType && typeof(Delegate).IsAssignableFrom(item2.my.FieldType))
												{
													obj3 = Delegate.CreateDelegate(item2.my.FieldType, ((Delegate)obj3).Target, ((Delegate)obj3).Method);
												}
												item2.my.SetValue(this, obj3);
											}
										}
										catch (Exception ex2)
										{
											Logger.LogWarning("Failed to copy value " + item2.my.Name + " from provided tag object " + type.FullName + " - " + ex2.Message);
										}
									}
								}
								else
								{
									Browsable = browsableAttribute.Browsable;
								}
							}
							else
							{
								ReadOnly = readOnlyAttribute.IsReadOnly;
							}
						}
						else
						{
							DefaultValue = defaultValueAttribute.Value;
						}
					}
					else
					{
						Description = descriptionAttribute.Description;
					}
				}
				else
				{
					Category = categoryAttribute.Category;
				}
			}
			else
			{
				DispName = displayNameAttribute.DisplayName;
			}
		}
	}
}
public static class ObjImporter
{
	private struct meshStruct
	{
		public Vector3[] vertices;

		public Vector3[] normals;

		public Vector2[] uv;

		public Vector2[] uv1;

		public Vector2[] uv2;

		public int[] triangles;

		public int[] faceVerts;

		public int[] faceUVs;

		public Vector3[] faceData;

		public string name;

		public string fileName;
	}

	public static Mesh ImportFile(string filePath)
	{
		//IL_004f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0054: Unknown result type (might be due to invalid IL or missing references)
		//IL_005f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0069: Unknown result type (might be due to invalid IL or missing references)
		//IL_006e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0073: Unknown result type (might be due to invalid IL or missing references)
		//IL_00e0: Unknown result type (might be due to invalid IL or missing references)
		//IL_00e7: Expected O, but got Unknown
		//IL_009e: Unknown result type (might be due to invalid IL or missing references)
		//IL_008a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0094: Unknown result type (might be due to invalid IL or missing references)
		//IL_0099: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b5: Unknown result type (might be due to invalid IL or missing references)
		//IL_00bf: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c4: Unknown result type (might be due to invalid IL or missing references)
		meshStruct mesh = CreateMeshStruct(filePath);
		PopulateMeshStruct(ref mesh);
		Vector3[] array = (Vector3[])(object)new Vector3[mesh.faceData.Length];
		Vector2[] array2 = (Vector2[])(object)new Vector2[mesh.faceData.Length];
		Vector3[] array3 = (Vector3[])(object)new Vector3[mesh.faceData.Length];
		int num = 0;
		Vector3[] faceData = mesh.faceData;
		foreach (Vector3 val in faceData)
		{
			array[num] = mesh.vertices[(int)val.x - 1];
			if (val.y >= 1f)
			{
				array2[num] = mesh.uv[(int)val.y - 1];
			}
			if (val.z >= 1f)
			{
				array3[num] = mesh.normals[(int)val.z - 1];
			}
			num++;
		}
		Mesh val2 = new Mesh();
		val2.vertices = array;
		val2.uv = array2;
		val2.normals = array3;
		val2.triangles = mesh.triangles;
		val2.RecalculateBounds();
		val2.Optimize();
		return val2;
	}

	private static meshStruct CreateMeshStruct(string filename)
	{
		int num = 0;
		int num2 = 0;
		int num3 = 0;
		int num4 = 0;
		int num5 = 0;
		meshStruct result = default(meshStruct);
		result.fileName = filename;
		StreamReader streamReader = File.OpenText(filename);
		string s = streamReader.ReadToEnd();
		streamReader.Close();
		using (StringReader stringReader = new StringReader(s))
		{
			string text = stringReader.ReadLine();
			char[] separator = new char[1] { ' ' };
			while (text != null)
			{
				if (!text.StartsWith("f ") && !text.StartsWith("v ") && !text.StartsWith("vt ") && !text.StartsWith("vn "))
				{
					text = stringReader.ReadLine();
					if (text != null)
					{
						text = text.Replace("  ", " ");
					}
					continue;
				}
				text = text.Trim();
				string[] array = text.Split(separator, 50);
				switch (array[0])
				{
				case "v":
					num2++;
					break;
				case "vt":
					num3++;
					break;
				case "vn":
					num4++;
					break;
				case "f":
					num5 = num5 + array.Length - 1;
					num += 3 * (array.Length - 2);
					break;
				}
				text = stringReader.ReadLine();
				if (text != null)
				{
					text = text.Replace("  ", " ");
				}
			}
		}
		result.triangles = new int[num];
		result.vertices = (Vector3[])(object)new Vector3[num2];
		result.uv = (Vector2[])(object)new Vector2[num3];
		result.normals = (Vector3[])(object)new Vector3[num4];
		result.faceData = (Vector3[])(object)new Vector3[num5];
		return result;
	}

	private static void PopulateMeshStruct(ref meshStruct mesh)
	{
		//IL_0329: Unknown result type (might be due to invalid IL or missing references)
		//IL_032e: Unknown result type (might be due to invalid IL or missing references)
		//IL_02cb: Unknown result type (might be due to invalid IL or missing references)
		//IL_02d0: Unknown result type (might be due to invalid IL or missing references)
		//IL_0390: Unknown result type (might be due to invalid IL or missing references)
		//IL_0395: Unknown result type (might be due to invalid IL or missing references)
		//IL_0358: Unknown result type (might be due to invalid IL or missing references)
		//IL_035d: Unknown result type (might be due to invalid IL or missing references)
		//IL_02fa: Unknown result type (might be due to invalid IL or missing references)
		//IL_02ff: Unknown result type (might be due to invalid IL or missing references)
		//IL_03b6: Unknown result type (might be due to invalid IL or missing references)
		//IL_0423: Unknown result type (might be due to invalid IL or missing references)
		//IL_0425: Unknown result type (might be due to invalid IL or missing references)
		StreamReader streamReader = File.OpenText(mesh.fileName);
		string s = streamReader.ReadToEnd();
		streamReader.Close();
		using StringReader stringReader = new StringReader(s);
		string text = stringReader.ReadLine();
		char[] separator = new char[1] { ' ' };
		char[] separator2 = new char[1] { '/' };
		int num = 0;
		int num2 = 0;
		int num3 = 0;
		int num4 = 0;
		int num5 = 0;
		int num6 = 0;
		int num7 = 0;
		while (text != null)
		{
			if (!text.StartsWith("f ") && !text.StartsWith("v ") && !text.StartsWith("vt ") && !text.StartsWith("vn ") && !text.StartsWith("g ") && !text.StartsWith("usemtl ") && !text.StartsWith("mtllib ") && !text.StartsWith("vt1 ") && !text.StartsWith("vt2 ") && !text.StartsWith("vc ") && !text.StartsWith("usemap "))
			{
				text = stringReader.ReadLine();
				if (text != null)
				{
					text = text.Replace("  ", " ");
				}
				continue;
			}
			text = text.Trim();
			string[] array = text.Split(separator, 50);
			switch (array[0])
			{
			case "v":
				mesh.vertices[num3] = new Vector3(Convert.ToSingle(array[1]), Convert.ToSingle(array[2]), Convert.ToSingle(array[3]));
				num3++;
				break;
			case "vt":
				mesh.uv[num5] = new Vector2(Convert.ToSingle(array[1]), Convert.ToSingle(array[2]));
				num5++;
				break;
			case "vt1":
				mesh.uv[num6] = new Vector2(Convert.ToSingle(array[1]), Convert.ToSingle(array[2]));
				num6++;
				break;
			case "vt2":
				mesh.uv[num7] = new Vector2(Convert.ToSingle(array[1]), Convert.ToSingle(array[2]));
				num7++;
				break;
			case "vn":
				mesh.normals[num4] = new Vector3(Convert.ToSingle(array[1]), Convert.ToSingle(array[2]), Convert.ToSingle(array[3]));
				num4++;
				break;
			case "f":
			{
				int num8 = 1;
				List<int> list = new List<int>();
				while (num8 < array.Length && (array[num8] ?? "").Length > 0)
				{
					Vector3 val = default(Vector3);
					string[] array2 = array[num8].Split(separator2, 3);
					val.x = Convert.ToInt32(array2[0]);
					if (array2.Length > 1)
					{
						if (array2[1] != "")
						{
							val.y = Convert.ToInt32(array2[1]);
						}
						val.z = Convert.ToInt32(array2[2]);
					}
					num8++;
					mesh.faceData[num2] = val;
					list.Add(num2);
					num2++;
				}
				for (num8 = 1; num8 + 2 < array.Length; num8++)
				{
					mesh.triangles[num] = list[0];
					num++;
					mesh.triangles[num] = list[num8];
					num++;
					mesh.triangles[num] = list[num8 + 1];
					num++;
				}
				break;
			}
			}
			text = stringReader.ReadLine();
			if (text != null)
			{
				text = text.Replace("  ", " ");
			}
		}
	}
}
namespace SimpleJson
{
	[GeneratedCode("simple-json", "1.0.0")]
	[EditorBrowsable(EditorBrowsableState.Never)]
	public class JsonArray : List<object>
	{
		public JsonArray()
		{
		}

		public JsonArray(int capacity)
			: base(capacity)
		{
		}

		public override string ToString()
		{
			return SimpleJson.SerializeObject(this) ?? string.Empty;
		}
	}
	[GeneratedCode("simple-json", "1.0.0")]
	[EditorBrowsable(EditorBrowsableState.Never)]
	public class JsonObject : IDictionary<string, object>, ICollection<KeyValuePair<string, object>>, IEnumerable<KeyValuePair<string, object>>, IEnumerable
	{
		private readonly Dictionary<string, object> _members;

		public object this[int index] => GetAtIndex(_members, index);

		public ICollection<string> Keys => _members.Keys;

		public ICollection<object> Values => _members.Values;

		public object this[string key]
		{
			get
			{
				return _members[key];
			}
			set
			{
				_members[key] = value;
			}
		}

		public int Count => _members.Count;

		public bool IsReadOnly => false;

		public JsonObject()
		{
			_members = new Dictionary<string, object>();
		}

		public JsonObject(IEqualityComparer<string> comparer)
		{
			_members = new Dictionary<string, object>(comparer);
		}

		internal static object GetAtIndex(IDictionary<string, object> obj, int index)
		{
			if (obj == null)
			{
				throw new ArgumentNullException("obj");
			}
			if (index >= obj.Count)
			{
				throw new ArgumentOutOfRangeException("index");
			}
			int num = 0;
			foreach (KeyValuePair<string, object> item in obj)
			{
				if (num++ == index)
				{
					return item.Value;
				}
			}
			return null;
		}

		public void Add(string key, object value)
		{
			_members.Add(key, value);
		}

		public bool ContainsKey(string key)
		{
			return _members.ContainsKey(key);
		}

		public bool Remove(string key)
		{
			return _members.Remove(key);
		}

		public bool TryGetValue(string key, out object value)
		{
			return _members.TryGetValue(key, out value);
		}

		public void Add(KeyValuePair<string, object> item)
		{
			_members.Add(item.Key, item.Value);
		}

		public void Clear()
		{
			_members.Clear();
		}

		public bool Contains(KeyValuePair<string, object> item)
		{
			if (_members.ContainsKey(item.Key))
			{
				return _members[item.Key] == item.Value;
			}
			return false;
		}

		public void CopyTo(KeyValuePair<string, object>[] array, int arrayIndex)
		{
			if (array == null)
			{
				throw new ArgumentNullException("array");
			}
			int num = Count;
			using IEnumerator<KeyValuePair<string, object>> enumerator = GetEnumerator();
			while (enumerator.MoveNext())
			{
				KeyValuePair<string, object> current = enumerator.Current;
				array[arrayIndex++] = current;
				if (--num <= 0)
				{
					break;
				}
			}
		}

		public bool Remove(KeyValuePair<string, object> item)
		{
			return _members.Remove(item.Key);
		}

		public IEnumerator<KeyValuePair<string, object>> GetEnumerator()
		{
			return _members.GetEnumerator();
		}

		IEnumerator IEnumerable.GetEnumerator()
		{
			return _members.GetEnumerator();
		}

		public override string ToString()
		{
			return SimpleJson.SerializeObject(this);
		}
	}
	[GeneratedCode("simple-json", "1.0.0")]
	public static class SimpleJson
	{
		private const int TOKEN_NONE = 0;

		private const int TOKEN_CURLY_OPEN = 1;

		private const int TOKEN_CURLY_CLOSE = 2;

		private const int TOKEN_SQUARED_OPEN = 3;

		private const int TOKEN_SQUARED_CLOSE = 4;

		private const int TOKEN_COLON = 5;

		private const int TOKEN_COMMA = 6;

		private const int TOKEN_STRING = 7;

		private const int TOKEN_NUMBER = 8;

		private const int TOKEN_TRUE = 9;

		private const int TOKEN_FALSE = 10;

		private const int TOKEN_NULL = 11;

		private const int BUILDER_CAPACITY = 2000;

		private static readonly char[] EscapeTable;

		private static readonly char[] EscapeCharacters;

		private static readonly string EscapeCharactersString;

		private static IJsonSerializerStrategy _currentJsonSerializerStrategy;

		private static PocoJsonSerializerStrategy _pocoJsonSerializerStrategy;

		public static IJsonSerializerStrategy CurrentJsonSerializerStrategy
		{
			get
			{
				return _currentJsonSerializerStrategy ?? (_currentJsonSerializerStrategy = PocoJsonSerializerStrategy);
			}
			set
			{
				_currentJsonSerializerStrategy = value;
			}
		}

		[EditorBrowsable(EditorBrowsableState.Advanced)]
		public static PocoJsonSerializerStrategy PocoJsonSerializerStrategy => _pocoJsonSerializerStrategy ?? (_pocoJsonSerializerStrategy = new PocoJsonSerializerStrategy());

		static SimpleJson()
		{
			EscapeCharacters = new char[7] { '"', '\\', '\b', '\f', '\n', '\r', '\t' };
			EscapeCharactersString = new string(EscapeCharacters);
			EscapeTable = new char[93];
			EscapeTable[34] = '"';
			EscapeTable[92] = '\\';
			EscapeTable[8] = 'b';
			EscapeTable[12] = 'f';
			EscapeTable[10] = 'n';
			EscapeTable[13] = 'r';
			EscapeTable[9] = 't';
		}

		public static object DeserializeObject(string json)
		{
			if (TryDeserializeObject(json, out var obj))
			{
				return obj;
			}
			throw new SerializationException("Invalid JSON string");
		}

		public static bool TryDeserializeObject(string json, out object obj)
		{
			bool success = true;
			if (json != null)
			{
				char[] json2 = json.ToCharArray();
				int index = 0;
				obj = ParseValue(json2, ref index, ref success);
			}
			else
			{
				obj = null;
			}
			return success;
		}

		public static object DeserializeObject(string json, Type type, IJsonSerializerStrategy jsonSerializerStrategy)
		{
			object obj = DeserializeObject(json);
			if (!(type == null) && (obj == null || !ReflectionUtils.IsAssignableFrom(obj.GetType(), type)))
			{
				return (jsonSerializerStrategy ?? CurrentJsonSerializerStrategy).DeserializeObject(obj, type);
			}
			return obj;
		}

		public static object DeserializeObject(string json, Type type)
		{
			return DeserializeObject(json, type, null);
		}

		public static T DeserializeObject<T>(string json, IJsonSerializerStrategy jsonSerializerStrategy)
		{
			return (T)DeserializeObject(json, typeof(T), jsonSerializerStrategy);
		}

		public static T DeserializeObject<T>(string json)
		{
			return (T)DeserializeObject(json, typeof(T), null);
		}

		public static string SerializeObject(object json, IJsonSerializerStrategy jsonSerializerStrategy)
		{
			StringBuilder stringBuilder = new StringBuilder(2000);
			if (!SerializeValue(jsonSerializerStrategy, json, stringBuilder))
			{
				return null;
			}
			return stringBuilder.ToString();
		}

		public static string SerializeObject(object json)
		{
			return SerializeObject(json, CurrentJsonSerializerStrategy);
		}

		public static string EscapeToJavascriptString(string jsonString)
		{
			if (string.IsNullOrEmpty(jsonString))
			{
				return jsonString;
			}
			StringBuilder stringBuilder = new StringBuilder();
			int num = 0;
			while (num < jsonString.Length)
			{
				char c = jsonString[num++];
				if (c == '\\')
				{
					int num2 = jsonString.Length - num;
					if (num2 >= 2)
					{
						switch (jsonString[num])
						{
						case '\\':
							stringBuilder.Append('\\');
							num++;
							break;
						case '"':
							stringBuilder.Append("\"");
							num++;
							break;
						case 't':
							stringBuilder.Append('\t');
							num++;
							break;
						case 'b':
							stringBuilder.Append('\b');
							num++;
							break;
						case 'n':
							stringBuilder.Append('\n');
							num++;
							break;
						case 'r':
							stringBuilder.Append('\r');
							num++;
							break;
						}
					}
				}
				else
				{
					stringBuilder.Append(c);
				}
			}
			return stringBuilder.ToString();
		}

		private static IDictionary<string, object> ParseObject(char[] json, ref int index, ref bool success)
		{
			IDictionary<string, object> dictionary = new JsonObject();
			NextToken(json, ref index);
			bool flag = false;
			while (!flag)
			{
				switch (LookAhead(json, index))
				{
				case 0:
					success = false;
					return null;
				case 6:
					NextToken(json, ref index);
					continue;
				case 2:
					NextToken(json, ref index);
					return dictionary;
				}
				string key = ParseString(json, ref index, ref success);
				if (!success)
				{
					success = false;
					return null;
				}
				int num = NextToken(json, ref index);
				if (num != 5)
				{
					success = false;
					return null;
				}
				object value = ParseValue(json, ref index, ref success);
				if (!success)
				{
					success = false;
					return null;
				}
				dictionary[key] = value;
			}
			return dictionary;
		}

		private static JsonArray ParseArray(char[] json, ref int index, ref bool success)
		{
			JsonArray jsonArray = new JsonArray();
			NextToken(json, ref index);
			bool flag = false;
			while (!flag)
			{
				switch (LookAhead(json, index))
				{
				case 0:
					success = false;
					return null;
				case 6:
					NextToken(json, ref index);
					continue;
				case 4:
					break;
				default:
				{
					object item = ParseValue(json, ref index, ref success);
					if (!success)
					{
						return null;
					}
					jsonArray.Add(item);
					continue;
				}
				}
				NextToken(json, ref index);
				break;
			}
			return jsonArray;
		}

		private static object ParseValue(char[] json, ref int index, ref bool success)
		{
			switch (LookAhead(json, index))
			{
			case 7:
				return ParseString(json, ref index, ref success);
			case 8:
				return ParseNumber(json, ref index, ref success);
			case 1:
				return ParseObject(json, ref index, ref success);
			case 3:
				return ParseArray(json, ref index, ref success);
			case 9:
				NextToken(json, ref index);
				return true;
			case 10:
				NextToken(json, ref index);
				return false;
			case 11:
				NextToken(json, ref index);
				return null;
			default:
				success = false;
				return null;
			}
		}

		private static string ParseString(char[] json, ref int index, ref bool success)
		{
			StringBuilder stringBuilder = new StringBuilder(2000);
			EatWhitespace(json, ref index);
			char c = json[index++];
			bool flag = false;
			while (!flag && index != json.Length)
			{
				c = json[index++];
				switch (c)
				{
				case '"':
					flag = true;
					break;
				case '\\':
				{
					if (index == json.Length)
					{
						break;
					}
					switch (json[index++])
					{
					case '"':
						stringBuilder.Append('"');
						continue;
					case '\\':
						stringBuilder.Append('\\');
						continue;
					case '/':
						stringBuilder.Append('/');
						continue;
					case 'b':
						stringBuilder.Append('\b');
						continue;
					case 'f':
						stringBuilder.Append('\f');
						continue;
					case 'n':
						stringBuilder.Append('\n');
						continue;
					case 'r':
						stringBuilder.Append('\r');
						continue;
					case 't':
						stringBuilder.Append('\t');
						continue;
					case 'u':
						break;
					default:
						continue;
					}
					int num = json.Length - index;
					if (num < 4)
					{
						break;
					}
					if (!(success = uint.TryParse(new string(json, index, 4), NumberStyles.HexNumber, CultureInfo.InvariantCulture, out var result)))
					{
						return "";
					}
					if (55296 <= result && result <= 56319)
					{
						index += 4;
						num = json.Length - index;
						if (num < 6 || !(new string(json, index, 2) == "\\u") || !uint.TryParse(new string(json, index + 2, 4), NumberStyles.HexNumber, CultureInfo.InvariantCulture, out var result2) || 56320 > result2 || result2 > 57343)
						{
							success = false;
							return "";
						}
						stringBuilder.Append((char)result);
						stringBuilder.Append((char)result2);
						index += 6;
					}
					else
					{
						stringBuilder.Append(ConvertFromUtf32((int)result));
						index += 4;
					}
					continue;
				}
				default:
					stringBuilder.Append(c);
					continue;
				}
				break;
			}
			if (!flag)
			{
				success = false;
				return null;
			}
			return stringBuilder.ToString();
		}

		private static string ConvertFromUtf32(int utf32)
		{
			if (utf32 < 0 || utf32 > 1114111)
			{
				throw new ArgumentOutOfRangeException("utf32", "The argument must be from 0 to 0x10FFFF.");
			}
			if (55296 <= utf32 && utf32 <= 57343)
			{
				throw new ArgumentOutOfRangeException("utf32", "The argument must not be in surrogate pair range.");
			}
			if (utf32 < 65536)
			{
				return new string((char)utf32, 1);
			}
			utf32 -= 65536;
			return new string(new char[2]
			{
				(char)((utf32 >> 10) + 55296),
				(char)(utf32 % 1024 + 56320)
			});
		}

		private static object ParseNumber(char[] json, ref int index, ref bool success)
		{
			EatWhitespace(json, ref index);
			int lastIndexOfNumber = GetLastIndexOfNumber(json, index);
			int length = lastIndexOfNumber - index + 1;
			string text = new string(json, index, length);
			object result2;
			if (text.IndexOf(".", StringComparison.OrdinalIgnoreCase) != -1 || text.IndexOf("e", StringComparison.OrdinalIgnoreCase) != -1)
			{
				success = double.TryParse(new string(json, index, length), NumberStyles.Any, CultureInfo.InvariantCulture, out var result);
				result2 = result;
			}
			else
			{
				success = long.TryParse(new string(json, index, length), NumberStyles.Any, CultureInfo.InvariantCulture, out var result3);
				result2 = result3;
			}
			index = lastIndexOfNumber + 1;
			return result2;
		}

		private static int GetLastIndexOfNumber(char[] json, int index)
		{
			int i;
			for (i = index; i < json.Length && "0123456789+-.eE".IndexOf(json[i]) != -1; i++)
			{
			}
			return i - 1;
		}

		private static void EatWhitespace(char[] json, ref int index)
		{
			while (index < json.Length && " \t\n\r\b\f".IndexOf(json[index]) != -1)
			{
				index++;
			}
		}

		private static int LookAhead(char[] json, int index)
		{
			int index2 = index;
			return NextToken(json, ref index2);
		}

		private static int NextToken(char[] json, ref int index)
		{
			EatWhitespace(json, ref index);
			if (index == json.Length)
			{
				return 0;
			}
			char c = json[index];
			index++;
			switch (c)
			{
			case '{':
				return 1;
			case '}':
				return 2;
			case '[':
				return 3;
			case ']':
				return 4;
			case ',':
				return 6;
			case '"':
				return 7;
			case '-':
			case '0':
			case '1':
			case '2':
			case '3':
			case '4':
			case '5':
			case '6':
			case '7':
			case '8':
			case '9':
				return 8;
			case ':':
				return 5;
			default:
			{
				index--;
				int num = json.Length - index;
				if (num >= 5 && json[index] == 'f' && json[index + 1] == 'a' && json[index + 2] == 'l' && json[index + 3] == 's' && json[index + 4] == 'e')
				{
					index += 5;
					return 10;
				}
				if (num >= 4 && json[index] == 't' && json[index + 1] == 'r' && json[index + 2] == 'u' && json[index + 3] == 'e')
				{
					index += 4;
					return 9;
				}
				if (num >= 4 && json[index] == 'n' && json[index + 1] == 'u' && json[index + 2] == 'l' && json[index + 3] == 'l')
				{
					index += 4;
					return 11;
				}
				return 0;
			}
			}
		}

		private static bool SerializeValue(IJsonSerializerStrategy jsonSerializerStrategy, object value, StringBuilder builder)
		{
			bool flag = true;
			if (value is string aString)
			{
				flag = SerializeString(aString, builder);
			}
			else if (value is IDictionary<string, object> dictionary)
			{
				flag = SerializeObject(jsonSerializerStrategy, dictionary.Keys, dictionary.Values, builder);
			}
			else if (value is IDictionary<string, string> dictionary2)
			{
				flag = SerializeObject(jsonSerializerStrategy, dictionary2.Keys, dictionary2.Values, builder);
			}
			else if (value is IEnumerable anArray)
			{
				flag = SerializeArray(jsonSerializerStrategy, anArray, builder);
			}
			else if (IsNumeric(value))
			{
				flag = SerializeNumber(value, builder);
			}
			else if (value is bool)
			{
				builder.Append(((bool)value) ? "true" : "false");
			}
			else if (value == null)
			{
				builder.Append("null");
			}
			else
			{
				flag = jsonSerializerStrategy.TrySerializeNonPrimitiveObject(value, out var output);
				if (flag)
				{
					SerializeValue(jsonSerializerStrategy, output, builder);
				}
			}
			return flag;
		}

		private static bool SerializeObject(IJsonSerializerStrategy jsonSerializerStrategy, IEnumerable keys, IEnumerable values, StringBuilder builder)
		{
			builder.Append("{");
			IEnumerator enumerator = keys.GetEnumerator();
			IEnumerator enumerator2 = values.GetEnumerator();
			bool flag = true;
			while (enumerator.MoveNext() && enumerator2.MoveNext())
			{
				object current = enumerator.Current;
				object current2 = enumerator2.Current;
				if (!flag)
				{
					builder.Append(",");
				}
				if (current is string aString)
				{
					SerializeString(aString, builder);
				}
				else if (!SerializeValue(jsonSerializerStrategy, current2, builder))
				{
					return false;
				}
				builder.Append(":");
				if (!SerializeValue(jsonSerializerStrategy, current2, builder))
				{
					return false;
				}
				flag = false;
			}
			builder.Append("}");
			return true;
		}

		private static bool SerializeArray(IJsonSerializerStrategy jsonSerializerStrategy, IEnumerable anArray, StringBuilder builder)
		{
			builder.Append("[");
			bool flag = true;
			foreach (object item in anArray)
			{
				if (!flag)
				{
					builder.Append(",");
				}
				if (!SerializeValue(jsonSerializerStrategy, item, builder))
				{
					return false;
				}
				flag = false;
			}
			builder.Append("]");
			return true;
		}

		private static bool SerializeString(string aString, StringBuilder builder)
		{
			if (aString.IndexOfAny(EscapeCharacters) == -1)
			{
				builder.Append('"');
				builder.Append(aString);
				builder.Append('"');
				return true;
			}
			builder.Append('"');
			int num = 0;
			char[] array = aString.ToCharArray();
			for (int i = 0; i < array.Length; i++)
			{
				char c = array[i];
				if (c >= EscapeTable.Length || EscapeTable[(uint)c] == '\0')
				{
					num++;
					continue;
				}
				if (num > 0)
				{
					builder.Append(array, i - num, num);
					num = 0;
				}
				builder.Append('\\');
				builder.Append(EscapeTable[(uint)c]);
			}
			if (num > 0)
			{
				builder.Append(array, array.Length - num, num);
			}
			builder.Append('"');
			return true;
		}

		private static bool SerializeNumber(object number, StringBuilder builder)
		{
			if (number is long)
			{
				builder.Append(((long)number).ToString(CultureInfo.InvariantCulture));
			}
			else if (number is ulong)
			{
				builder.Append(((ulong)number).ToString(CultureInfo.InvariantCulture));
			}
			else if (number is int)
			{
				builder.Append(((int)number).ToString(CultureInfo.InvariantCulture));
			}
			else if (number is uint)
			{
				builder.Append(((uint)number).ToString(CultureInfo.InvariantCulture));
			}
			else if (number is decimal)
			{
				builder.Append(((decimal)number).ToString(CultureInfo.InvariantCulture));
			}
			else if (number is float)
			{
				builder.Append(((float)number).ToString(CultureInfo.InvariantCulture));
			}
			else
			{
				builder.Append(Convert.ToDouble(number, CultureInfo.InvariantCulture).ToString("r", CultureInfo.InvariantCulture));
			}
			return true;
		}

		private static bool IsNumeric(object value)
		{
			if (value is sbyte)
			{
				return true;
			}
			if (value is byte)
			{
				return true;
			}
			if (value is short)
			{
				return true;
			}
			if (value is ushort)
			{
				return true;
			}
			if (value is int)
			{
				return true;
			}
			if (value is uint)
			{
				return true;
			}
			if (value is long)
			{
				return true;
			}
			if (value is ulong)
			{
				return true;
			}
			if (value is float)
			{
				return true;
			}
			if (value is double)
			{
				return true;
			}
			if (value is decimal)
			{
				return true;
			}
			return false;
		}
	}
	[GeneratedCode("simple-json", "1.0.0")]
	public interface IJsonSerializerStrategy
	{
		bool TrySerializeNonPrimitiveObject(object input, out object output);

		object DeserializeObject(object value, Type type);
	}
	[GeneratedCode("simple-json", "1.0.0")]
	public class PocoJsonSerializerStrategy : IJsonSerializerStrategy
	{
		internal IDictionary<Type, ReflectionUtils.ConstructorDelegate> ConstructorCache;

		internal IDictionary<Type, IDictionary<string, ReflectionUtils.GetDelegate>> GetCache;

		internal IDictionary<Type, IDictionary<string, KeyValuePair<Type, ReflectionUtils.SetDelegate>>> SetCache;

		internal static readonly Type[] EmptyTypes = new Type[0];

		internal static readonly Type[] ArrayConstructorParameterTypes = new Type[1] { typeof(int) };

		private static readonly string[] Iso8601Format = new string[3] { "yyyy-MM-dd\\THH:mm:ss.FFFFFFF\\Z", "yyyy-MM-dd\\THH:mm:ss\\Z", "yyyy-MM-dd\\THH:mm:ssK" };

		public PocoJsonSerializerStrategy()
		{
			ConstructorCache = new ReflectionUtils.ThreadSafeDictionary<Type, ReflectionUtils.ConstructorDelegate>(ContructorDelegateFactory);
			GetCache = new ReflectionUtils.ThreadSafeDictionary<Type, IDictionary<string, ReflectionUtils.GetDelegate>>(GetterValueFactory);
			SetCache = new ReflectionUtils.ThreadSafeDictionary<Type, IDictionary<string, KeyValuePair<Type, ReflectionUtils.SetDelegate>>>(SetterValueFactory);
		}

		protected virtual string MapClrMemberNameToJsonFieldName(string clrPropertyName)
		{
			return clrPropertyName;
		}

		internal virtual ReflectionUtils.ConstructorDelegate ContructorDelegateFactory(Type key)
		{
			return ReflectionUtils.GetContructor(key, key.IsArray ? ArrayConstructorParameterTypes : EmptyTypes);
		}

		internal virtual IDictionary<string, ReflectionUtils.GetDelegate> GetterValueFactory(Type type)
		{
			IDictionary<string, ReflectionUtils.GetDelegate> dictionary = new Dictionary<string, ReflectionUtils.GetDelegate>();
			foreach (PropertyInfo property in ReflectionUtils.GetProperties(type))
			{
				if (property.CanRead)
				{
					MethodInfo getterMethodInfo = ReflectionUtils.GetGetterMethodInfo(property);
					if (!getterMethodInfo.IsStatic && getterMethodInfo.IsPublic)
					{
						dictionary[MapClrMemberNameToJsonFieldName(property.Name)] = ReflectionUtils.GetGetMethod(property);
					}
				}
			}
			foreach (FieldInfo field in ReflectionUtils.GetFields(type))
			{
				if (!field.IsStatic && field.IsPublic)
				{
					dictionary[MapClrMemberNameToJsonFieldName(field.Name)] = ReflectionUtils.GetGetMethod(field);
				}
			}
			return dictionary;
		}

		internal virtual IDictionary<string, KeyValuePair<Type, ReflectionUtils.SetDelegate>> SetterValueFactory(Type type)
		{
			IDictionary<string, KeyValuePair<Type, ReflectionUtils.SetDelegate>> dictionary = new Dictionary<string, KeyValuePair<Type, ReflectionUtils.SetDelegate>>();
			foreach (PropertyInfo property in ReflectionUtils.GetProperties(type))
			{
				if (property.CanWrite)
				{
					MethodInfo setterMethodInfo = ReflectionUtils.GetSetterMethodInfo(property);
					if (!setterMethodInfo.IsStatic && setterMethodInfo.IsPublic)
					{
						dictionary[MapClrMemberNameToJsonFieldName(property.Name)] = new KeyValuePair<Type, ReflectionUtils.SetDelegate>(property.PropertyType, ReflectionUtils.GetSetMethod(property));
					}
				}
			}
			foreach (FieldInfo field in ReflectionUtils.GetFields(type))
			{
				if (!field.IsInitOnly && !field.IsStatic && field.IsPublic)
				{
					dictionary[MapClrMemberNameToJsonFieldName(field.Name)] = new KeyValuePair<Type, ReflectionUtils.SetDelegate>(field.FieldType, ReflectionUtils.GetSetMethod(field));
				}
			}
			return dictionary;
		}

		public virtual bool TrySerializeNonPrimitiveObject(object input, out object output)
		{
			if (!TrySerializeKnownTypes(input, out output))
			{
				return TrySerializeUnknownTypes(input, out output);
			}
			return true;
		}

		public virtual object DeserializeObject(object value, Type type)
		{
			if (type == null)
			{
				throw new ArgumentNullException("type");
			}
			string text = value as string;
			if (type == typeof(Guid) && string.IsNullOrEmpty(text))
			{
				return default(Guid);
			}
			if (value == null)
			{
				return null;
			}
			object obj = null;
			if (text != null)
			{
				if (text.Length != 0)
				{
					if (type == typeof(DateTime) || (ReflectionUtils.IsNullableType(type) && Nullable.GetUnderlyingType(type) == typeof(DateTime)))
					{
						return DateTime.ParseExact(text, Iso8601Format, CultureInfo.InvariantCulture, DateTimeStyles.AdjustToUniversal | DateTimeStyles.AssumeUniversal);
					}
					if (type == typeof(DateTimeOffset) || (ReflectionUtils.IsNullableType(type) && Nullable.GetUnderlyingType(type) == typeof(DateTimeOffset)))
					{
						return DateTimeOffset.ParseExact(text, Iso8601Format, CultureInfo.InvariantCulture, DateTimeStyles.AdjustToUniversal | DateTimeStyles.AssumeUniversal);
					}
					if (type == typeof(Guid) || (ReflectionUtils.IsNullableType(type) && Nullable.GetUnderlyingType(type) == typeof(Guid)))
					{
						return new Guid(text);
					}
					if (type == typeof(Uri))
					{
						if (Uri.IsWellFormedUriString(text, UriKind.RelativeOrAbsolute) && Uri.TryCreate(text, UriKind.RelativeOrAbsolute, out Uri result))
						{
							return result;
						}
						return null;
					}
					if (type == typeof(string))
					{
						return text;
					}
					return Convert.ChangeType(text, type, CultureInfo.InvariantCulture);
				}
				obj = ((type == typeof(Guid)) ? ((object)default(Guid)) : ((!ReflectionUtils.IsNullableType(type) || !(Nullable.GetUnderlyingType(type) == typeof(Guid))) ? text : null));
				if (!ReflectionUtils.IsNullableType(type) && Nullable.GetUnderlyingType(type) == typeof(Guid))
				{
					return text;
				}
			}
			else if (value is bool)
			{
				return value;
			}
			bool flag = value is long;
			bool flag2 = value is double;
			if ((flag && type == typeof(long)) || (flag2 && type == typeof(double)))
			{
				return value;
			}
			if ((flag2 && type != typeof(double)) || (flag && type != typeof(long)))
			{
				obj = ((type == typeof(int) || type == typeof(long) || type == typeof(double) || type == typeof(float) || type == typeof(bool) || type == typeof(decimal) || type == typeof(byte) || type == typeof(short)) ? Convert.ChangeType(value, type, CultureInfo.InvariantCulture) : value);
			}
			else
			{
				if (!(value is JsonArray) || !ReflectionUtils.IsTypeDictionary(type))
				{
					if (value is IDictionary<string, object> dictionary)
					{
						IDictionary<string, object> dictionary2 = dictionary;
						if (ReflectionUtils.IsTypeDictionary(type))
						{
							Type[] genericTypeArguments = ReflectionUtils.GetGenericTypeArguments(type);
							Type type2 = genericTypeArguments[0];
							Type type3 = genericTypeArguments[1];
							Type key = typeof(Dictionary<, >).MakeGenericType(type2, type3);
							IDictionary dictionary3 = (IDictionary)ConstructorCache[key]();
							foreach (KeyValuePair<string, object> item in dictionary2)
							{
								dictionary3.Add(item.Key, DeserializeObject(item.Value, type3));
							}
							obj = dictionary3;
						}
						else if (type == typeof(object))
						{
							obj = value;
						}
						else
						{
							ReflectionUtils.ConstructorDelegate constructorDelegate = ConstructorCache[type];
							if (constructorDelegate == null)
							{
								throw new MissingMethodException($"No default constructor found for {type}");
							}
							obj = constructorDelegate();
							foreach (KeyValuePair<string, KeyValuePair<Type, ReflectionUtils.SetDelegate>> item2 in SetCache[type])
							{
								if (dictionary2.TryGetValue(item2.Key, out var value2))
								{
									value2 = DeserializeObject(value2, item2.Value.Key);
									item2.Value.Value(obj, value2);
								}
							}
						}
					}
					else if (value is IList<object> list)
					{
						IList<object> list2 = list;
						IList list3 = null;
						if (type.IsArray)
						{
							list3 = (IList)ConstructorCache[type](list2.Count);
							int num = 0;
							foreach (object item3 in list2)
							{
								list3[num++] = DeserializeObject(item3, type.GetElementType());
							}
						}
						else if (ReflectionUtils.IsTypeGenericeCollectionInterface(type) || ReflectionUtils.IsAssignableFrom(typeof(IList), type))
						{
							Type genericListElementType = ReflectionUtils.GetGenericListElementType(type);
							list3 = (IList)(ConstructorCache[type] ?? ConstructorCache[typeof(List<>).MakeGenericType(genericListElementType)])(list2.Count);
							foreach (object item4 in list2)
							{
								list3.Add(DeserializeObject(item4, genericListElementType));
							}
						}
						obj = list3;
					}
					return obj;
				}
				JsonArray jsonArray = (JsonArray)value;
				Type[] genericTypeArguments2 = ReflectionUtils.GetGenericTypeArguments(type);
				Type type4 = genericTypeArguments2[0];
				Type type5 = genericTypeArguments2[1];
				Type key2 = typeof(Dictionary<, >).MakeGenericType(type4, type5);
				IDictionary dictionary4 = (IDictionary)ConstructorCache[key2]();
				foreach (JsonObject item5 in jsonArray)
				{
					dictionary4.Add(DeserializeObject(item5[0], type4), DeserializeObject(item5[1], type5));
				}
				obj = dictionary4;
			}
			if (ReflectionUtils.IsNullableType(type))
			{
				return ReflectionUtils.ToNullableType(obj, type);
			}
			return obj;
		}

		protected virtual object SerializeEnum(Enum p)
		{
			return Convert.ToDouble(p, CultureInfo.InvariantCulture);
		}

		protected virtual bool TrySerializeKnownTypes(object input, out object output)
		{
			bool result = true;
			if (input is DateTime)
			{
				output = ((DateTime)input).ToUniversalTime().ToString(Iso8601Format[0], CultureInfo.InvariantCulture);
			}
			else if (input is DateTimeOffset)
			{
				output = ((DateTimeOffset)input).ToUniversalTime().ToString(Iso8601Format[0], CultureInfo.InvariantCulture);
			}
			else if (input is Guid)
			{
				output = ((Guid)input).ToString("D");
			}
			else if (input is Uri)
			{
				output = input.ToString();
			}
			else if (input is Enum p)
			{
				output = SerializeEnum(p);
			}
			else
			{
				result = false;
				output = null;
			}
			return result;
		}

		protected virtual bool TrySerializeUnknownTypes(object input, out object output)
		{
			if (input == null)
			{
				throw new ArgumentNullException("input");
			}
			output = null;
			Type type = input.GetType();
			if (type.FullName == null)
			{
				return false;
			}
			IDictionary<string, object> dictionary = new JsonObject();
			IDictionary<string, ReflectionUtils.GetDelegate> dictionary2 = GetCache[type];
			foreach (KeyValuePair<string, ReflectionUtils.GetDelegate> item in dictionary2)
			{
				if (item.Value != null)
				{
					dictionary.Add(MapClrMemberNameToJsonFieldName(item.Key), item.Value(input));
				}
			}
			output = dictionary;
			return true;
		}
	}
}
namespace SimpleJson.Reflection
{
	[GeneratedCode("reflection-utils", "1.0.0")]
	internal class ReflectionUtils
	{
		public delegate object GetDelegate(object source);

		public delegate void SetDelegate(object source, object value);

		public delegate object ConstructorDelegate(params object[] args);

		public delegate TValue ThreadSafeDictionaryValueFactory<TKey, TValue>(TKey key);

		private static class Assigner<T>
		{
			public static T Assign(ref T left, T right)
			{
				return left = right;
			}
		}

		public sealed class ThreadSafeDictionary<TKey, TValue> : IDictionary<TKey, TValue>, ICollection<KeyValuePair<TKey, TValue>>, IEnumerable<KeyValuePair<TKey, TValue>>, IEnumerable
		{
			private readonly object _lock = new object();

			private readonly ThreadSafeDictionaryValueFactory<TKey, TValue> _valueFactory;

			private Dictionary<TKey, TValue> _dictionary;

			public ICollection<TKey> Keys => _dictionary.Keys;

			public ICollection<TValue> Values => _dictionary.Values;

			public TValue this[TKey key]
			{
				get
				{
					return Get(key);
				}
				set
				{
					throw new NotImplementedException();
				}
			}

			public int Count => _dictionary.Count;

			public bool IsReadOnly
			{
				get
				{
					throw new NotImplementedException();
				}
			}

			public ThreadSafeDictionary(ThreadSafeDictionaryValueFactory<TKey, TValue> valueFactory)
			{
				_valueFactory = valueFactory;
			}

			private TValue Get(TKey key)
			{
				if (_dictionary == null)
				{
					return AddValue(key);
				}
				if (!_dictionary.TryGetValue(key, out var value))
				{
					return AddValue(key);
				}
				return value;
			}

			private TValue AddValue(TKey key)
			{
				TValue val = _valueFactory(key);
				lock (_lock)
				{
					if (_dictionary == null)
					{
						_dictionary = new Dictionary<TKey, TValue>();
						_dictionary[key] = val;
					}
					else
					{
						if (_dictionary.TryGetValue(key, out var value))
						{
							return value;
						}
						Dictionary<TKey, TValue> dictionary = new Dictionary<TKey, TValue>(_dictionary);
						dictionary[key] = val;
						_dictionary = dictionary;
					}
				}
				return val;
			}

			public void Add(TKey key, TValue value)
			{
				throw new NotImplementedException();
			}

			public bool ContainsKey(TKey key)
			{
				return _dictionary.ContainsKey(key);
			}

			public bool Remove(TKey key)
			{
				throw new NotImplementedException();
			}

			public bool TryGetValue(TKey key, out TValue value)
			{
				value = this[key];
				return true;
			}

			public void Add(KeyValuePair<TKey, TValue> item)
			{
				throw new NotImplementedException();
			}

			public void Clear()
			{
				throw new NotImplementedException();
			}

			public bool Contains(KeyValuePair<TKey, TValue> item)
			{
				throw new NotImplementedException();
			}

			public void CopyTo(KeyValuePair<TKey, TValue>[] array, int arrayIndex)
			{
				throw new NotImplementedException();
			}

			public bool Remove(KeyValuePair<TKey, TValue> item)
			{
				throw new NotImplementedException();
			}

			public IEnumerator<KeyValuePair<TKey, TValue>> GetEnumerator()
			{
				return _dictionary.GetEnumerator();
			}

			IEnumerator IEnumerable.GetEnumerator()
			{
				return _dictionary.GetEnumerator();
			}
		}

		private static readonly object[] EmptyObjects = new object[0];

		public static Type GetTypeInfo(Type type)
		{
			return type;
		}

		public static Attribute GetAttribute(MemberInfo info, Type type)
		{
			if (info == null || type == null || !Attribute.IsDefined(info, type))
			{
				return null;
			}
			return Attribute.GetCustomAttribute(info, type);
		}

		public static Type GetGenericListElementType(Type type)
		{
			IEnumerable<Type> interfaces = type.GetInterfaces();
			foreach (Type item in interfaces)
			{
				if (IsTypeGeneric(item) && item.GetGenericTypeDefinition() == typeof(IList<>))
				{
					return GetGenericTypeArguments(item)[0];
				}
			}
			return GetGenericTypeArguments(type)[0];
		}

		public static Attribute GetAttribute(Type objectType, Type attributeType)
		{
			if (objectType == null || attributeType == null || !Attribute.IsDefined(objectType, attributeType))
			{
				return null;
			}
			return Attribute.GetCustomAttribute(objectType, attributeType);
		}

		public static Type[] GetGenericTypeArguments(Type type)
		{
			return type.GetGenericArguments();
		}

		public static bool IsTypeGeneric(Type type)
		{
			return GetTypeInfo(type).IsGenericType;
		}

		public static bool IsTypeGenericeCollectionInterface(Type type)
		{
			if (!IsTypeGeneric(type))
			{
				return false;
			}
			Type genericTypeDefinition = type.GetGenericTypeDefinition();
			if (!(genericTypeDefinition == typeof(IList<>)) && !(genericTypeDefinition == typeof(ICollection<>)))
			{
				return genericTypeDefinition == typeof(IEnumerable<>);
			}
			return true;
		}

		public static bool IsAssignableFrom(Type type1, Type type2)
		{
			return GetTypeInfo(type1).IsAssignableFrom(GetTypeInfo(type2));
		}

		public static bool IsTypeDictionary(Type type)
		{
			if (typeof(IDictionary).IsAssignableFrom(type))
			{
				return true;
			}
			if (!GetTypeInfo(type).IsGenericType)
			{
				return false;
			}
			Type genericTypeDefinition = type.GetGenericTypeDefinition();
			return genericTypeDefinition == typeof(IDictionary<, >);
		}

		public static bool IsNullableType(Type type)
		{
			if (GetTypeInfo(type).IsGenericType)
			{
				return type.GetGenericTypeDefinition() == typeof(Nullable<>);
			}
			return false;
		}

		public static object ToNullableType(object obj, Type nullableType)
		{
			if (obj != null)
			{
				return Convert.ChangeType(obj, Nullable.GetUnderlyingType(nullableType), CultureInfo.InvariantCulture);
			}
			return null;
		}

		public static bool IsValueType(Type type)
		{
			return GetTypeInfo(type).IsValueType;
		}

		public static IEnumerable<ConstructorInfo> GetConstructors(Type type)
		{
			return type.GetConstructors();
		}

		public static ConstructorInfo GetConstructorInfo(Type type, params Type[] argsType)
		{
			IEnumerable<ConstructorInfo> constructors = GetConstructors(type);
			foreach (ConstructorInfo item in constructors)
			{
				ParameterInfo[] parameters = item.GetParameters();
				if (argsType.Length != parameters.Length)
				{
					continue;
				}
				int num = 0;
				bool flag = true;
				ParameterInfo[] parameters2 = item.GetParameters();
				foreach (ParameterInfo parameterInfo in parameters2)
				{
					if (parameterInfo.ParameterType != argsType[num])
					{
						flag = false;
						break;
					}
				}
				if (flag)
				{
					return item;
				}
			}
			return null;
		}

		public static IEnumerable<PropertyInfo> GetProperties(Type type)
		{
			return type.GetProperties(BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
		}

		public static IEnumerable<FieldInfo> GetFields(Type type)
		{
			return type.GetFields(BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
		}

		public static MethodInfo GetGetterMethodInfo(PropertyInfo propertyInfo)
		{
			return propertyInfo.GetGetMethod(nonPublic: true);
		}

		public static MethodInfo GetSetterMethodInfo(PropertyInfo propertyInfo)
		{
			return propertyInfo.GetSetMethod(nonPublic: true);
		}

		public static ConstructorDelegate GetContructor(ConstructorInfo constructorInfo)
		{
			return GetConstructorByExpression(constructorInfo);
		}

		public static ConstructorDelegate GetContructor(Type type, params Type[] argsType)
		{
			return GetConstructorByExpression(type, argsType);
		}

		public static ConstructorDelegate GetConstructorByReflection(ConstructorInfo constructorInfo)
		{
			return (object[] args) => constructorInfo.Invoke(args);
		}

		public static ConstructorDelegate GetConstructorByReflection(Type type, params Type[] argsType)
		{
			ConstructorInfo constructorInfo = GetConstructorInfo(type, argsType);
			if (!(constructorInfo == null))
			{
				return GetConstructorByReflection(constructorInfo);
			}
			return null;
		}

		public static ConstructorDelegate GetConstructorByExpression(ConstructorInfo constructorInfo)
		{
			ParameterInfo[] parameters = constructorInfo.GetParameters();
			ParameterExpression parameterExpression = Expression.Parameter(typeof(object[]), "args");
			Expression[] array = new Expression[parameters.Length];
			for (int i = 0; i < parameters.Length; i++)
			{
				Expression index = Expression.Constant(i);
				Type parameterType = parameters[i].ParameterType;
				Expression expression = Expression.ArrayIndex(parameterExpression, index);
				Expression expression2 = Expression.Convert(expression, parameterType);
				array[i] = expression2;
			}
			NewExpression body = Expression.New(constructorInfo, array);
			Expression<Func<object[], object>> expression3 = Expression.Lambda<Func<object[], object>>(body, new ParameterExpression[1] { parameterExpression });
			Func<object[], object> compiledLambda = expression3.Compile();
			return (object[] args) => compiledLambda(args);
		}

		public static ConstructorDelegate GetConstructorByExpression(Type type, params Type[] argsType)
		{
			ConstructorInfo constructorInfo = GetConstructorInfo(type, argsType);
			if (!(constructorInfo == null))
			{
				return GetConstructorByExpression(constructorInfo);
			}
			return null;
		}

		public static GetDelegate GetGetMethod(PropertyInfo propertyInfo)
		{
			return GetGetMethodByExpression(propertyInfo);
		}

		public static GetDelegate GetGetMethod(FieldInfo fieldInfo)
		{
			return GetGetMethodByExpression(fieldInfo);
		}

		public static GetDelegate GetGetMethodByReflection(PropertyInfo propertyInfo)
		{
			MethodInfo methodInfo = GetGetterMethodInfo(propertyInfo);
			return (object source) => methodInfo.Invoke(source, EmptyObjects);
		}

		public static GetDelegate GetGetMethodByReflection(FieldInfo fieldInfo)
		{
			return (object source) => fieldInfo.GetValue(source);
		}

		public static GetDelegate GetGetMethodByExpression(PropertyInfo propertyInfo)
		{
			MethodInfo getterMethodInfo = GetGetterMethodInfo(propertyInfo);
			ParameterExpression parameterExpression = Expression.Parameter(typeof(object), "instance");
			UnaryExpression instance = ((!IsValueType(propertyInfo.DeclaringType)) ? Expression.TypeAs(parameterExpression, propertyInfo.DeclaringType) : Expression.Convert(parameterExpression, propertyInfo.DeclaringType));
			Func<object, object> compiled = Expression.Lambda<Func<object, object>>(Expression.TypeAs(Expression.Call(instance, getterMethodInfo), typeof(object)), new ParameterExpression[1] { parameterExpression }).Compile();
			return (object source) => compiled(source);
		}

		public static GetDelegate GetGetMethodByExpression(FieldInfo fieldInfo)
		{
			ParameterExpression parameterExpression = Expression.Parameter(typeof(object), "instance");
			MemberExpression expression = Expression.Field(Expression.Convert(parameterExpression, fieldInfo.DeclaringType), fieldInfo);
			GetDelegate compiled = Expression.Lambda<GetDelegate>(Expression.Convert(expression, typeof(object)), new ParameterExpression[1] { parameterExpression }).Compile();
			return (object source) => compiled(source);
		}

		public static SetDelegate GetSetMethod(PropertyInfo propertyInfo)
		{
			return GetSetMethodByExpression(propertyInfo);
		}

		public static SetDelegate GetSetMethod(FieldInfo fieldInfo)
		{
			return GetSetMethodByExpression(fieldInfo);
		}

		public static SetDelegate GetSetMethodByReflection(PropertyInfo propertyInfo)
		{
			MethodInfo methodInfo = GetSetterMethodInfo(propertyInfo);
			return delegate(object source, object value)
			{
				methodInfo.Invoke(source, new object[1] { value });
			};
		}

		public static SetDelegate GetSetMethodByReflection(FieldInfo fieldInfo)
		{
			return delegate(object source, object value)
			{
				fieldInfo.SetValue(source, value);
			};
		}

		public static SetDelegate GetSetMethodByExpression(PropertyInfo propertyInfo)
		{
			MethodInfo setterMethodInfo = GetSetterMethodInfo(propertyInfo);
			ParameterExpression parameterExpression = Expression.Parameter(typeof(object), "instance");
			ParameterExpression parameterExpression2 = Expression.Parameter(typeof(object), "value");
			UnaryExpression instance = ((!IsValueType(propertyInfo.DeclaringType)) ? Expression.TypeAs(parameterExpression, propertyInfo.DeclaringType) : Expression.Convert(parameterExpression, propertyInfo.DeclaringType));
			UnaryExpression unaryExpression = ((!IsValueType(propertyInfo.PropertyType)) ? Expression.TypeAs(parameterExpression2, propertyInfo.PropertyType) : Expression.Convert(parameterExpression2, propertyInfo.PropertyType));
			Action<object, object> compiled = Expression.Lambda<Action<object, object>>(Expression.Call(instance, setterMethodInfo, unaryExpression), new ParameterExpression[2] { parameterExpression, parameterExpression2 }).Compile();
			return delegate(object source, object val)
			{
				compiled(source, val);
			};
		}

		public static SetDelegate GetSetMethodByExpression(FieldInfo fieldInfo)
		{
			ParameterExpression parameterExpression = Expression.Parameter(typeof(object), "instance");
			ParameterExpression parameterExpression2 = Expression.Parameter(typeof(object), "value");
			Action<object, object> compiled = Expression.Lambda<Action<object, object>>(Assign(Expression.Field(Expression.Convert(parameterExpression, fieldInfo.DeclaringType), fieldInfo), Expression.Convert(parameterExpression2, fieldInfo.FieldType)), new ParameterExpression[2] { parameterExpression, parameterExpression2 }).Compile();
			return delegate(object source, object val)
			{
				compiled(source, val);
			};
		}

		public static BinaryExpression Assign(Expression left, Expression right)
		{
			MethodInfo method = typeof(Assigner<>).MakeGenericType(left.Type).GetMethod("Assign");
			return Expression.Add(left, right, method);
		}
	}
}
namespace Jotunn
{
	public static class ArrayExtensions
	{
		public static T[] Populate<T>(this T[] arr, T value)
		{
			for (int i = 0; i < arr.Length; i++)
			{
				arr[i] = value;
			}
			return arr;
		}
	}
	public static class ConfigEntryBaseExtension
	{
		public static bool IsVisible(this ConfigEntryBase configurationEntry)
		{
			ConfigurationManagerAttributes configurationManagerAttributes = new ConfigurationManagerAttributes();
			ConfigDescription description = configurationEntry.Description;
			configurationManagerAttributes.SetFromAttributes((description != null) ? description.Tags : null);
			return configurationManagerAttributes.Browsable != false;
		}

		public static bool IsSyncable(this ConfigEntryBase configurationEntry)
		{
			if (configurationEntry.Description.Tags.FirstOrDefault((object x) => x is ConfigurationManagerAttributes) is ConfigurationManagerAttributes configurationManagerAttributes)
			{
				return configurationManagerAttributes.IsAdminOnly;
			}
			return false;
		}

		public static string GetBoundButtonName(this ConfigEntryBase configurationEntry)
		{
			if (configurationEntry == null)
			{
				throw new ArgumentNullException("configurationEntry");
			}
			if (configurationEntry.SettingType != typeof(KeyCode) && configurationEntry.SettingType != typeof(KeyboardShortcut) && configurationEntry.SettingType != typeof(InputManager.GamepadButton))
			{
				return null;
			}
			if (!InputManager.ButtonToConfigDict.TryGetValue(configurationEntry, out var value))
			{
				return null;
			}
			return value.Name;
		}

		public static ButtonConfig GetButtonConfig(this ConfigEntryBase configurationEntry)
		{
			if (configurationEntry == null)
			{
				throw new ArgumentNullException("configurationEntry");
			}
			if (configurationEntry.SettingType != typeof(KeyCode) && configurationEntry.SettingType != typeof(KeyboardShortcut) && configurationEntry.SettingType != typeof(InputManager.GamepadButton))
			{
				return null;
			}
			InputManager.ButtonToConfigDict.TryGetValue(configurationEntry, out var value);
			return value;
		}

		internal static object GetLocalValue(this ConfigEntryBase configurationEntry)
		{
			if (SynchronizationManager.Instance.localValues.TryGetValue(configurationEntry, out var value))
			{
				return value;
			}
			return null;
		}

		internal static void SetLocalValue(this ConfigEntryBase configurationEntry, object value)
		{
			SynchronizationManager.Instance.localValues[configurationEntry] = value;
		}

		internal static ConfigurationManagerAttributes GetConfigurationManagerAttributes(this ConfigEntryBase configEntry)
		{
			return (ConfigurationManagerAttributes)configEntry.Description.Tags.FirstOrDefault((object x) => x is ConfigurationManagerAttributes);
		}
	}
	internal static class EventExtensions
	{
		public static void SafeInvoke(this Action events)
		{
			if (events == null)
			{
				return;
			}
			Delegate[] invocationList = events.GetInvocationList();
			for (int i = 0; i < invocationList.Length; i++)
			{
				Action action = (Action)invocationList[i];
				try
				{
					action();
				}
				catch (Exception ex)
				{
					Logger.LogWarning($"Exception thrown at event {new StackFrame(1).GetMethod().Name} in {action.Method.DeclaringType.Name}.{action.Method.Name}:\n{ex}");
				}
			}
		}

		public static void SafeInvoke<TArg1>(this Action<TArg1> events, TArg1 arg1)
		{
			if (events == null)
			{
				return;
			}
			Delegate[] invocationList = events.GetInvocationList();
			for (int i = 0; i < invocationList.Length; i++)
			{
				Action<TArg1> action = (Action<TArg1>)invocationList[i];
				try
				{
					action(arg1);
				}
				catch (Exception ex)
				{
					Logger.LogWarning($"Exception thrown at event {new StackFrame(1).GetMethod().Name} in {action.Method.DeclaringType.Name}.{action.Method.Name}:\n{ex}");
				}
			}
		}

		public static void SafeInvoke<TArg1, TArg2>(this Action<TArg1, TArg2> events, TArg1 arg1, TArg2 arg2)
		{
			if (events == null)
			{
				return;
			}
			Delegate[] invocationList = events.GetInvocationList();
			for (int i = 0; i < invocationList.Length; i++)
			{
				Action<TArg1, TArg2> action = (Action<TArg1, TArg2>)invocationList[i];
				try
				{
					action(arg1, arg2);
				}
				catch (Exception ex)
				{
					Logger.LogWarning($"Exception thrown at event {new StackFrame(1).GetMethod().Name} in {action.Method.DeclaringType.Name}.{action.Method.Name}:\n{ex}");
				}
			}
		}

		public static void SafeInvoke<TEventArg>(this EventHandler<TEventArg> events, object sender, TEventArg arg1)
		{
			if (events == null)
			{
				return;
			}
			Delegate[] invocationList = events.GetInvocationList();
			for (int i = 0; i < invocationList.Length; i++)
			{
				EventHandler<TEventArg> eventHandler = (EventHandler<TEventArg>)invocationList[i];
				try
				{
					eventHandler(sender, arg1);
				}
				catch (Exception ex)
				{
					Logger.LogWarning($"Exception thrown at event {new StackFrame(1).GetMethod().Name} in {eventHandler.Method.DeclaringType.Name}.{eventHandler.Method.Name}:\n{ex}");
				}
			}
		}
	}
	public static class ExposedGameObjectExtension
	{
		public static GameObject OrNull(this GameObject @this)
		{
			if (!Object.op_Implicit((Object)(object)@this))
			{
				return null;
			}
			return @this;
		}

		public static T OrNull<T>(this T @this) where T : Object
		{
			if (!Object.op_Implicit((Object)(object)@this))
			{
				return default(T);
			}
			return @this;
		}

		public static T GetOrAddComponent<T>(this GameObject gameObject) where T : Component
		{
			T result = default(T);
			if (!gameObject.TryGetComponent<T>(ref result))
			{
				return gameObject.AddComponent<T>();
			}
			return result;
		}

		public static Component AddComponentCopy<T>(this GameObject gameObject, T duplicate) where T : Component
		{
			Component val = gameObject.AddComponent(((object)duplicate).GetType());
			PropertyInfo[] properties = ((object)duplicate).GetType().GetProperties(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
			foreach (PropertyInfo propertyInfo in properties)
			{
				switch (propertyInfo.Name)
				{
				case "mesh":
					if (duplicate is MeshFilter)
					{
						continue;
					}
					break;
				case "material":
				case "materials":
					if (duplicate is Renderer)
					{
						continue;
					}
					break;
				case "bounds":
					if (duplicate is Renderer)
					{
						continue;
					}
					break;
				case "name":
				case "rayTracingMode":
				case "tag":
					continue;
				}
				if (propertyInfo.CanWrite && propertyInfo.GetMethod != null)
				{
					propertyInfo.SetValue(val, propertyInfo.GetValue(duplicate));
				}
			}
			FieldInfo[] fields = ((object)duplicate).GetType().GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
			foreach (FieldInfo fieldInfo in fields)
			{
				if (!(fieldInfo.Name == "rayTracingMode"))
				{
					fieldInfo.SetValue(val, fieldInfo.GetValue(duplicate));
				}
			}
			return val;
		}

		public static bool HasAnyComponent(this GameObject gameObject, params Type[] components)
		{
			foreach (Type type in components)
			{
				if (Object.op_Implicit((Object)(object)gameObject.GetComponent(type)))
				{
					return true;
				}
			}
			return false;
		}

		public static bool HasAnyComponent(this GameObject gameObject, params string[] componentNames)
		{
			foreach (string text in componentNames)
			{
				if (Object.op_Implicit((Object)(object)gameObject.GetComponent(text)))
				{
					return true;
				}
			}
			return false;
		}

		public static bool HasAllComponents(this GameObject gameObject, params string[] componentNames)
		{
			foreach (string text in componentNames)
			{
				if (!Object.op_Implicit((Object)(object)gameObject.GetComponent(text)))
				{
					return false;
				}
			}
			return true;
		}

		public static bool HasAllComponents(this GameObject gameObject, params Type[] components)
		{
			foreach (Type type in components)
			{
				if (!Object.op_Implicit((Object)(object)gameObject.GetComponent(type)))
				{
					return false;
				}
			}
			return true;
		}

		public static bool HasAnyComponentInChildren(this GameObject gameObject, bool includeInactive = false, params Type[] components)
		{
			foreach (Type type in components)
			{
				if (Object.op_Implicit((Object)(object)gameObject.GetComponentInChildren(type, includeInactive)))
				{
					return true;
				}
			}
			return false;
		}

		public static Transform FindDeepChild(this GameObject gameObject, string childName, IterativeSearchType searchType = 1)
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			return gameObject.transform.FindDeepChild(childName, searchType);
		}

		public static Transform FindDeepChild(this GameObject gameObject, IEnumerable<string> childNames, IterativeSearchType searchType = 1)
		{
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			Transform val = gameObject.transform;
			foreach (string childName in childNames)
			{
				val = val.FindDeepChild(childName, searchType);
				if (!Object.op_Implicit((Object)(object)val))
				{
					return null;
				}
			}
			return val;
		}
	}
	internal static class GameObjectGUIExtension
	{
		internal static GameObject SetToTextHeight(this GameObject go)
		{
			go.GetComponent<RectTransform>().SetSizeWithCurrentAnchors((Axis)1, go.GetComponentInChildren<Text>().preferredHeight + 3f);
			return go;
		}

		internal static GameObject SetUpperLeft(this GameObject go)
		{
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_003c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0051: Unknown result type (might be due to invalid IL or missing references)
			RectTransform component = go.GetComponent<RectTransform>();
			component.anchorMax = new Vector2(0f, 1f);
			component.anchorMin = new Vector2(0f, 1f);
			component.pivot = new Vector2(0f, 1f);
			component.anchoredPosition = new Vector2(0f, 0f);
			return go;
		}

		internal static GameObject SetMiddleLeft(this GameObject go)
		{
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_003c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0051: Unknown result type (might be due to invalid IL or missing references)
			RectTransform component = go.GetComponent<RectTransform>();
			component.anchorMax = new Vector2(0f, 0.5f);
			component.anchorMin = new Vector2(0f, 0.5f);
			component.pivot = new Vector2(0f, 0.5f);
			component.anchoredPosition = new Vector2(0f, 0f);
			return go;
		}

		internal static GameObject SetBottomLeft(this GameObject go)
		{
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_003c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0051: Unknown result type (might be due to invalid IL or missing references)
			RectTransform component = go.GetComponent<RectTransform>();
			component.anchorMax = new Vector2(0f, 0f);
			component.anchorMin = new Vector2(0f, 0f);
			component.pivot = new Vector2(0f, 0f);
			component.anchoredPosition = new Vector2(0f, 0f);
			return go;
		}

		internal static GameObject SetUpperRight(this GameObject go)
		{
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_003c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0051: Unknown result type (might be due to invalid IL or missing references)
			RectTransform component = go.GetComponent<RectTransform>();
			component.anchorMax = new Vector2(1f, 1f);
			component.anchorMin = new Vector2(1f, 1f);
			component.pivot = new Vector2(1f, 1f);
			component.anchoredPosition = new Vector2(0f, 0f);
			return go;
		}

		internal static GameObject SetMiddleRight(this GameObject go)
		{
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_003c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0051: Unknown result type (might be due to invalid IL or missing references)
			RectTransform component = go.GetComponent<RectTransform>();
			component.anchorMax = new Vector2(1f, 0.5f);
			component.anchorMin = new Vector2(1f, 0.5f);
			component.pivot = new Vector2(1f, 0.5f);
			component.anchoredPosition = new Vector2(0f, 0f);
			return go;
		}

		internal static GameObject SetBottomRight(this GameObject go)
		{
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_003c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0051: Unknown result type (might be due to invalid IL or missing references)
			RectTransform component = go.GetComponent<RectTransform>();
			component.anchorMax = new Vector2(1f, 0f);
			component.anchorMin = new Vector2(1f, 0f);
			component.pivot = new Vector2(1f, 0f);
			component.anchoredPosition = new Vector2(0f, 0f);
			return go;
		}

		internal static GameObject SetUpperCenter(this GameObject go)
		{
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_003c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0051: Unknown result type (might be due to invalid IL or missing references)
			RectTransform component = go.GetComponent<RectTransform>();
			component.anchorMax = new Vector2(0.5f, 1f);
			component.anchorMin = new Vector2(0.5f, 1f);
			component.pivot = new Vector2(0.5f, 1f);
			component.anchoredPosition = new Vector2(0f, 0f);
			return go;
		}

		internal static GameObject SetMiddleCenter(this GameObject go)
		{
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_003c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0051: Unknown result type (might be due to invalid IL or missing references)
			RectTransform component = go.GetComponent<RectTransform>();
			component.anchorMax = new Vector2(0.5f, 0.5f);
			component.anchorMin = new Vector2(0.5f, 0.5f);
			component.pivot = new Vector2(0.5f, 0.5f);
			component.anchoredPosition = new Vector2(0f, 0f);
			return go;
		}

		internal static GameObject SetBottomCenter(this GameObject go)
		{
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_003c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0051: Unknown result type (might be due to invalid IL or missing references)
			RectTransform component = go.GetComponent<RectTransform>();
			component.anchorMax = new Vector2(0.5f, 0f);
			component.anchorMin = new Vector2(0.5f, 0f);
			component.pivot = new Vector2(0.5f, 0f);
			component.anchoredPosition = new Vector2(0f, 0f);
			return go;
		}

		internal static GameObject SetSize(this GameObject go, float width, float height)
		{
			RectTransform component = go.GetComponent<RectTransform>();
			component.SetSizeWithCurrentAnchors((Axis)0, width);
			component.SetSizeWithCurrentAnchors((Axis)1, height);
			return go;
		}

		internal static GameObject SetWidth(this GameObject go, float width)
		{
			RectTransform component = go.GetComponent<RectTransform>();
			component.SetSizeWithCurrentAnchors((Axis)0, width);
			return go;
		}

		internal static GameObject SetHeight(this GameObject go, float height)
		{
			RectTransform component = go.GetComponent<RectTransform>();
			component.SetSizeWithCurrentAnchors((Axis)1, height);
			return go;
		}

		internal static float GetWidth(this GameObject go)
		{
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			RectTransform component = go.GetComponent<RectTransform>();
			Rect rect = component.rect;
			return ((Rect)(ref rect)).width;
		}

		internal static float GetHeight(this GameObject go)
		{
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			RectTransform component = go.GetComponent<RectTransform>();
			Rect rect = component.rect;
			return ((Rect)(ref rect)).height;
		}

		internal static float GetTextHeight(this GameObject go)
		{
			return go.GetComponent<Text>().preferredHeight;
		}

		internal static GameObject SetText(this GameObject go, string text)
		{
			Text component = go.GetComponent<Text>();
			if ((Object)(object)component != (Object)null)
			{
				component.text = text;
			}
			TMP_Text component2 = go.GetComponent<TMP_Text>();
			if ((Object)(object)component2 != (Object)null)
			{
				component2.text = text;
			}
			return go;
		}
	}
	public static class GameObjectExtension
	{
		public static bool IsValid(this GameObject self)
		{
			string text = ((Object)self).name;
			if (text.IndexOf('(') > 0)
			{
				text = text.Substring(((Object)self).name.IndexOf('(')).Trim();
			}
			if (string.IsNullOrEmpty(text))
			{
				Logger.LogError("GameObject must have a name!");
				return false;
			}
			if (Object.op_Implicit((Object)(object)self.GetComponent<ZNetView>()) && ((Object)self).name.IndexOfAny(new char[2] { ')', ' ' }) > 0)
			{
				Logger.LogError("GameObject name '" + ((Object)self).name + "' must not contain parenthesis or spaces!");
				return false;
			}
			return true;
		}
	}
	public static class ItemDropExtension
	{
		public static string TokenName(this ItemDrop self)
		{
			return self.m_itemData.m_shared.m_name;
		}
	}
	public static class ItemDataExtension
	{
		public static string TokenName(this ItemData self)
		{
			return self.m_shared.m_name;
		}
	}
	public static class RecipeExtension
	{
		public static bool IsValid(this Recipe self)
		{
			try
			{
				string text = ((Object)self).name;
				if (text.IndexOf('(') > 0)
				{
					text = text.Substring(((Object)self).name.IndexOf('(')).Trim();
				}
				if (string.IsNullOrEmpty(text))
				{
					throw new Exception("Recipe must have a name !");
				}
				return true;
			}
			catch (Exception data)
			{
				Logger.LogError(data);
				return false;
			}
		}
	}
	public static class PieceExtension
	{
		public static string TokenName(this Piece self)
		{
			return self.m_name;
		}
	}
	public static class StatusEffectExtension
	{
		public static string TokenName(this StatusEffect self)
		{
			return self.m_name;
		}

		public static bool IsValid(this StatusEffect self)
		{
			try
			{
				string text = ((Object)self).name;
				if (text.IndexOf('(') > 0)
				{
					text = text.Substring(((Object)self).name.IndexOf('(')).Trim();
				}
				if (string.IsNullOrEmpty(text))
				{
					throw new Exception("StatusEffect must have a name !");
				}
				return true;
			}
			catch (Exception data)
			{
				Logger.LogError(data);
				return false;
			}
		}
	}
	public static class PrefabExtension
	{
		public static void FixReferences(this object objectToFix)
		{
			MockManager.FixReferences(objectToFix, 0);
		}

		public static void FixReferences(this GameObject gameObject)
		{
			gameObject.FixReferences(recursive: false);
		}

		public static void FixReferences(this GameObject gameObject, bool recursive)
		{
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			//IL_004f: Expected O, but got Unknown
			Component[] components = gameObject.GetComponents<Component>();
			foreach (Component val in components)
			{
				if (!(val is Transform))
				{
					MockManager.FixReferences(val, 0);
				}
			}
			if (!recursive)
			{
				return;
			}
			List<Tuple<Transform, GameObject>> list = new List<Tuple<Transform, GameObject>>();
			foreach (Transform item in gameObject.transform)
			{
				Transform val2 = item;
				GameObject realPrefabFromMock = MockManager.GetRealPrefabFromMock<GameObject>((Object)(object)((Component)val2).gameObject);
				if (Object.op_Implicit((Object)(object)realPrefabFromMock))
				{
					list.Add(new Tuple<Transform, GameObject>(val2, realPrefabFromMock));
				}
				else
				{
					((Component)val2).gameObject.FixReferences(recursive: true);
				}
			}
			foreach (Tuple<Transform, GameObject> item2 in list)
			{
				MockManager.ReplaceMockGameObject(item2.Item1, item2.Item2, gameObject);
			}
		}

		public static void CloneFields(this GameObject gameObject, GameObject objectToClone)
		{
			Dictionary<FieldInfo, object> dictionary = new Dictionary<FieldInfo, object>();
			Component[] componentsInChildren = objectToClone.GetComponentsInChildren<Component>();
			Component[] array = componentsInChildren;
			foreach (Component val in array)
			{
				FieldInfo[] fields = ((object)val).GetType().GetFields((BindingFlags)(-1));
				foreach (FieldInfo fieldInfo in fields)
				{
					if (!fieldInfo.IsLiteral && !fieldInfo.IsInitOnly)
					{
						dictionary.Add(fieldInfo, fieldInfo.GetValue(val));
					}
				}
				if (!Object.op_Implicit((Object)(object)gameObject.GetComponent(((object)val).GetType())))
				{
					gameObject.AddComponent(((object)val).GetType());
				}
			}
			Component[] componentsInChildren2 = gameObject.GetComponentsInChildren<Component>();
			Component[] array2 = componentsInChildren2;
			foreach (Component val2 in array2)
			{
				FieldInfo[] fields2 = ((object)val2).GetType().GetFields((BindingFlags)(-1));
				foreach (FieldInfo fieldInfo2 in fields2)
				{
					if (dictionary.TryGetValue(fieldInfo2, out var value))
					{
						fieldInfo2.SetValue(val2, value);
					}
				}
			}
		}
	}
	internal static class ObjectExtension
	{
		public static string GetObjectString(this object obj)
		{
			if (obj == null)
			{
				return "null";
			}
			string text = $"{obj}";
			Type type = obj.GetType();
			IEnumerable<FieldInfo> enumerable = from f in type.GetFields()
				where f.IsPublic
				select f;
			foreach (FieldInfo item in enumerable)
			{
				object value = item.GetValue(obj);
				string text2 = ((value == null) ? "null" : value.ToString());
				text = text + "\n " + item.Name + ": " + text2;
			}
			PropertyInfo[] properties = type.GetProperties();
			PropertyInfo[] array = properties;
			foreach (PropertyInfo propertyInfo in array)
			{
				object value2 = propertyInfo.GetValue(obj, null);
				string text3 = ((value2 == null) ? "null" : value2.ToString());
				text = text + "\n " + propertyInfo.Name + ": " + text3;
			}
			return text;
		}
	}
	public static class RectTransformExtensions
	{
		public static bool Overlaps(this RectTransform a, RectTransform b)
		{
			//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_000a: Unknown result type (might be due to invalid IL or missing references)
			Rect val = a.WorldRect();
			return ((Rect)(ref val)).Overlaps(b.WorldRect());
		}

		public static bool Overlaps(this RectTransform a, RectTransform b, bool allowInverse)
		{
			//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_000a: Unknown result type (might be due to invalid IL or missing references)
			Rect val = a.WorldRect();
			return ((Rect)(ref val)).Overlaps(b.WorldRect(), allowInverse);
		}

		public static Rect WorldRect(this RectTransform rectTransform)
		{
			//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_0007: 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_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			//IL_0042: Unknown result type (might be due to invalid IL or missing references)
			//IL_0052: Unknown result type (might be due to invalid IL or missing references)
			Vector2 sizeDelta = rectTransform.sizeDelta;
			float num = sizeDelta.x * ((Transform)rectTransform).lossyScale.x;
			float num2 = sizeDelta.y * ((Transform)rectTransform).lossyScale.y;
			Vector3 position = ((Transform)rectTransform).position;
			return new Rect(position.x - num / 2f, position.y - num2 / 2f, num, num2);
		}
	}
	public static class ZNetExtension
	{
		public enum ZNetInstanceType
		{
			Local,
			Client,
			Server
		}

		public static bool IsLocalInstance(this ZNet znet)
		{
			if (znet.IsServer())
			{
				return !znet.IsDedicated();
			}
			return false;
		}

		public static bool IsClientInstance(this ZNet znet)
		{
			if (!znet.IsServer())
			{
				return !znet.IsDedicated();
			}
			return false;
		}

		public static bool IsServerInstance(this ZNet znet)
		{
			if (znet.IsServer())
			{
				return znet.IsDedicated();
			}
			return false;
		}

		public static ZNetInstanceType GetInstanceType(this ZNet znet)
		{
			if (znet.IsLocalInstance())
			{
				return ZNetInstanceType.Local;
			}
			if (znet.IsClientInstance())
			{
				return ZNetInstanceType.Client;
			}
			return ZNetInstanceType.Server;
		}

		public static bool IsAdmin(this ZNet znet, long uid)
		{
			if (!Object.op_Implicit((Object)(object)znet))
			{
				Logger.LogWarning("IsAdmin check failed: ZNet is null");
				return false;
			}
			if (znet.m_adminList == null)
			{
				Logger.LogWarning("IsAdmin check failed: admin list is only available on the server");
				return false;
			}
			ZNetPeer peer = znet.GetPeer(uid);
			if (peer == null)
			{
				Logger.LogWarning($"IsAdmin check failed: peer not found with id {uid}");
				return false;
			}
			string hostName = peer.m_socket.GetHostName();
			if (!string.IsNullOrEmpty(hostName))
			{
				return znet.ListContainsId(znet.m_adminList, hostName);
			}
			return false;
		}
	}
	internal interface IManager
	{
		void Init();
	}
	public class Logger
	{
		public static bool ShowDate = false;

		private static Logger instance = new Logger();

		private readonly Dictionary<string, ManualLogSource> logger = new Dictionary<string, ManualLogSource>();

		internal static void Destroy()
		{
			LogDebug("Destroying Logger");
			foreach (KeyValuePair<string, ManualLogSource> item in instance.logger)
			{
				Logger.Sources.Remove((ILogSource)(object)item.Value);
			}
			instance.logger.Clear();
		}

		private ManualLogSource GetLogger()
		{
			Type declaringType = new StackFrame(3).GetMethod().DeclaringType;
			if (!logger.TryGetValue(declaringType.FullName, out var value))
			{
				value = Logger.CreateLogSource(declaringType.FullName);
				logger.Add(declaringType.FullName, value);
			}
			return value;
		}

		private static void Log(LogLevel level, BepInPlugin sourceMod, object data)
		{
			//IL_0054: Unknown result type (might be due to invalid IL or missing references)
			string text = string.Empty;
			if (ShowDate)
			{
				text = text + "[" + DateTime.Now.ToString(DateTimeFormatInfo.InvariantInfo) + "] ";
			}
			if (sourceMod != null)
			{
				text = text + "[" + sourceMod.Name + "] ";
			}
			instance.GetLogger().Log(level, (object)$"{text}{data}");
		}

		public static void LogFatal(object data)
		{
			Log((LogLevel)1, null, data);
		}

		public static void LogFatal(BepInPlugin sourceMod, object data)
		{
			Log((LogLevel)1, sourceMod, data);
		}

		public static void LogError(object data)
		{
			Log((LogLevel)2, null, data);
		}

		public static void LogError(BepInPlugin sourceMod, object data)
		{
			Log((LogLevel)2, sourceMod, data);
		}

		public static void LogWarning(object data)
		{
			Log((LogLevel)4, null, data);
		}

		public static void LogWarning(BepInPlugin sourceMod, object data)
		{
			Log((LogLevel)4, sourceMod, data);
		}

		public static void LogMessage(object data)
		{
			Log((LogLevel)8, null, data);
		}

		public static void LogMessage(BepInPlugin sourceMod, object data)
		{
			Log((LogLevel)8, sourceMod, data);
		}

		public static void LogInfo(object data)
		{
			Log((LogLevel)16, null, data);
		}

		public static void LogInfo(BepInPlugin sourceMod, object data)
		{
			Log((LogLevel)16, sourceMod, data);
		}

		public static void LogDebug(object data)
		{
			Log((LogLevel)32, null, data);
		}

		public static void LogDebug(BepInPlugin sourceMod, object data)
		{
			Log((LogLevel)32, sourceMod, data);
		}
	}
	[BepInPlugin("com.jotunn.jotunn", "Jotunn", "2.21.2")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[NetworkCompatibility(CompatibilityLevel.VersionCheckOnly, VersionStrictness.Patch)]
	public class Main : BaseUnityPlugin
	{
		public const string Version = "2.21.2";

		public const string ModName = "Jotunn";

		public const string ModGuid = "com.jotunn.jotunn";

		internal static Main Instance;

		internal static Harmony Harmony = new Harmony("com.jotunn.jotunn");

		private static GameObject rootObject;

		internal static GameObject RootObject => GetRootObject();

		private void Awake()
		{
			Instance = this;
			GetRootObject();
			ModCompatibility.Init();
			((IManager)SynchronizationManager.Instance).Init();
			Runtime.MakeAllAssetsLoadable();
			Game.isModded = true;
		}

		private void Start()
		{
			PatchInit.InitializePatches();
			AutomaticLocalizationsLoading.Init();
		}

		private void OnApplicationQuit()
		{
			AssetBundle.UnloadAllAssetBundles(false);
		}

		private static GameObject GetRootObject()
		{
			//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)rootObject))
			{
				return rootObject;
			}
			rootObject = new GameObject("_JotunnRoot");
			Object.DontDestroyOnLoad((Object)(object)rootObject);
			return rootObject;
		}

		internal static void LogInit(string module)
		{
			Logger.LogInfo("Initializing " + module);
			if (!Object.op_Implicit((Object)(object)Instance))
			{
				string data = module + " was accessed before Jotunn Awake, this can cause unexpected behaviour. Please make sure to add `[BepInDependency(Jotunn.Main.ModGuid)]` next to your BaseUnityPlugin";
				Logger.LogWarning(BepInExUtils.GetSourceModMetadata(), data);
			}
		}
	}
	internal class ClassMember
	{
		private static readonly Dictionary<Type, ClassMember> CachedClassMembers = new Dictionary<Type, ClassMember>();

		public List<MemberBase> Members { get; private set; } = new List<MemberBase>();


		public Type Type { get; private set; }

		private ClassMember(Type type, IEnumerable<FieldInfo> fieldInfos, IEnumerable<PropertyInfo> propertyInfos)
		{
			Type = type;
			foreach (FieldInfo fieldInfo in fieldInfos)
			{
				AddMember(new FieldMember(fieldInfo));
			}
			foreach (PropertyInfo propertyInfo in propertyInfos)
			{
				AddMember(new PropertyMember(propertyInfo));
			}
		}

		private void AddMember(MemberBase member)
		{
			if (member.IsClass && !(member.MemberType == typeof(string)) && (!(member.EnumeratedType != null) || (member.IsEnumeratedClass && !(member.EnumeratedType == typeof(string)))) && !member.HasCustomAttribute<NonSerializedAttribute>())
			{
				Members.Add(member);
			}
		}

		private static T[] GetMembersFromType<T>(Type type, Func<Type, T[]> getMembers)
		{
			T[] array = getMembers(type);
			Type baseType = type.BaseType;
			while (baseType != null)
			{
				T[] second = getMembers(baseType);
				array = array.Union(second).ToArray();
				baseType = baseType.BaseType;
			}
			return array;
		}

		public static ClassMember GetClassMember(Type type)
		{
			if (CachedClassMembers.TryGetValue(type, out var value))
			{
				return value;
			}
			FieldInfo[] membersFromType = GetMembersFromType(type, (Type t) => t.GetFields(~BindingFlags.Static));
			PropertyInfo[] membersFromType2 = GetMembersFromType(type, (Type t) => t.GetProperties(~BindingFlags.Static));
			value = new ClassMember(type, membersFromType, membersFromType2);
			CachedClassMembers[type] = value;
			return value;
		}
	}
	internal class FieldMember : MemberBase
	{
		private readonly FieldInfo fieldInfo;

		public FieldMember(FieldInfo fieldInfo)
		{
			this.fieldInfo = fieldInfo;
			base.MemberType = fieldInfo.FieldType;
			base.IsUnityObject = base.MemberType.IsSameOrSubclass(typeof(Object));
			base.IsClass = base.MemberType.IsClass;
			base.HasGetMethod = true;
			base.EnumeratedType = base.MemberType.GetEnumeratedType();
			base.IsEnumerableOfUnityObjects = base.EnumeratedType?.IsSameOrSubclass(typeof(Object)) ?? false;
			base.IsEnumeratedClass = base.EnumeratedType?.IsClass ?? false;
		}

		public override object GetValue(object obj)
		{
			try
			{
				return fieldInfo.GetValue(obj);
			}
			catch
			{
				return null;
			}
		}

		public override void SetValue(object obj, object value)
		{
			fieldInfo.SetValue(obj, value);
		}

		public override bool HasCustomAttribute<T>()
		{
			return fieldInfo.GetCustomAttribute<T>() != null;
		}
	}
	internal abstract class MemberBase
	{
		public bool HasGetMethod { get; protected set; }

		public Type MemberType { get; protected set; }

		public Type EnumeratedType { get; protected set; }

		public bool IsUnityObject { get; protected set; }

		public bool IsClass { get; protected set; }

		public bool IsEnumerableOfUnityObjects { get; protected set; }

		public bool IsEnumeratedClass { get; protected set; }

		public abstract object GetValue(object obj);

		public abstract void SetValue(object obj, object value);

		public abstract bool HasCustomAttribute<T>() where T : Attribute;
	}
	internal class PropertyMember : MemberBase
	{
		private readonly PropertyInfo propertyInfo;

		public PropertyMember(PropertyInfo propertyInfo)
		{
			this.propertyInfo = propertyInfo;
			base.MemberType = propertyInfo.PropertyType;
			base.IsUnityObject = base.MemberType.IsSameOrSubclass(typeof(Object));
			base.IsClass = base.MemberType.IsClass;
			base.HasGetMethod = propertyInfo.GetIndexParameters().Length == 0 && propertyInfo.GetMethod != null;
			base.EnumeratedType = base.MemberType.GetEnumeratedType();
			base.IsEnumerableOfUnityObjects = base.EnumeratedType?.IsSameOrSubclass(typeof(Object)) ?? false;
			base.IsEnumeratedClass = base.EnumeratedType?.IsClass ?? false;
		}

		public override object GetValue(object obj)
		{
			try
			{
				return propertyInfo.GetValue(obj);
			}
			catch
			{
				return null;
			}
		}

		public override void SetValue(object obj, object value)
		{
			propertyInfo.SetValue(obj, value);
		}

		public override bool HasCustomAttribute<T>()
		{
			return propertyInfo.GetCustomAttribute<T>() != null;
		}
	}
}
namespace Jotunn.Utils
{
	public static class AssetUtils
	{
		public const char AssetBundlePathSeparator = '$';

		public static Texture2D LoadTexture(string texturePath, bool relativePath = true)
		{
			//IL_0049: Unknown result type (might be due to invalid IL or missing references)
			//IL_004f: Expected O, but got Unknown
			string text = texturePath;
			if (relativePath)
			{
				text = Path.Combine(Paths.PluginPath, texturePath);
			}
			if (!File.Exists(text))
			{
				return null;
			}
			if (!text.EndsWith(".png") && !text.EndsWith(".jpg"))
			{
				throw new Exception("LoadTexture can only load png or jpg textures");
			}
			byte[] array = File.ReadAllBytes(text);
			Texture2D val = new Texture2D(2, 2);
			ImageConversion.LoadImage(val, array);
			return val;
		}

		public static Sprite LoadSpriteFromFile(string spritePath)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			return LoadSpriteFromFile(spritePath, Vector2.zero);
		}

		public static Sprite LoadSpriteFromFile(string spritePath, Vector2 pivot)
		{
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			Texture2D val = LoadTexture(spritePath);
			if ((Object)(object)val != (Object)null)
			{
				return Sprite.Create(val, new Rect(0f, 0f, (float)((Texture)val).width, (float)((Texture)val).height), pivot);
			}
			return null;
		}

		public static Mesh LoadMesh(string meshPath)
		{
			string text = Path.Combine(Paths.PluginPath, meshPath);
			if (!File.Exists(text))
			{
				return null;
			}
			return ObjImporter.ImportFile(text);
		}

		public static AssetBundle LoadAssetBundle(string bundlePath)
		{
			string text = Path.Combine(Paths.PluginPath, bundlePath);
			if (!File.Exists(text))
			{
				return null;
			}
			return AssetBundle.LoadFromFile(text);
		}

		public static AssetBundle LoadAssetBundleFromResources(string bundleName, Assembly resourceAssembly)
		{
			if (resourceAssembly == null)
			{
				throw new ArgumentNullException("Parameter resourceAssembly can not be null.");
			}
			string text = null;
			try
			{
				text = resourceAssembly.GetManifestResourceNames().Single((string str) => str.EndsWith(bundleName));
			}
			catch (Exception)
			{
			}
			if (text == null)
			{
				Logger.LogError("AssetBundle " + bundleName + " not found in assembly manifest");
				return null;
			}
			using Stream stream = resourceAssembly.GetManifestResourceStream(text);
			return AssetBundle.LoadFromStream(stream);
		}

		public static AssetBundle LoadAssetBundleFromResources(string bundleName)
		{
			return LoadAssetBundleFromResources(bundleName, ReflectionHelper.GetCallingAssembly());
		}

		public static string LoadTextFromResources(string fileName, Assembly resourceAssembly)
		{
			if (resourceAssembly == null)
			{
				throw new ArgumentNullException("Parameter resourceAssembly can not be null.");
			}
			string text = null;
			try
			{
				text = resourceAssembly.GetManifestResourceNames().Single((string str) => str.EndsWith(fileName));
			}
			catch (Exception)
			{
			}
			if (text == null)
			{
				Logger.LogError("File " + fileName + " not found in assembly manifest");
				return null;
			}
			using Stream stream = resourceAssembly.GetManifestResourceStream(text);
			using StreamReader streamReader = new StreamReader(stream);
			return streamReader.ReadToEnd();
		}

		public static string LoadTextFromResources(string fileName)
		{
			return LoadTextFromResources(fileName, ReflectionHelper.GetCallingAssembly());
		}

		public static string LoadText(string path)
		{
			string text = Path.Combine(Paths.PluginPath, path);
			if (!File.Exists(text))
			{
				Logger.LogError("Error, failed to load contents from non-existant path: $" + text);
				return null;
			}
			return File.ReadAllText(text);
		}

		public static Sprite LoadSprite(string assetPath)
		{
			//IL_008e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0093: Unknown result type (might be due to invalid IL or missing references)
			string text = Path.Combine(Paths.PluginPath, assetPath);
			if (!File