Decompiled source of ShieldBash v1.3.0

BepInEx/plugins/Jotunn.dll

Decompiled a day 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.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.27.1.0")]
[assembly: AssemblyInformationalVersion("2.27.1+c2d97e2e047b9464a17d0db7546ccb4383334cbe")]
[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.27.1.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 = true;

	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_0022: Unknown result type (might be due to invalid IL or missing references)
		//IL_002d: 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)
		{
			MockResolveFailure.MockResolveFailures.Clear();
			MockManager.FixReferences(objectToFix, 0);
			Object val = (Object)((objectToFix is Object) ? objectToFix : null);
			string prefabName = (Object.op_Implicit(val) ? val.name : objectToFix.ToString());
			MockResolveFailure.PrintMockResolveFailures(prefabName);
		}

		public static void FixReferences(this GameObject gameObject)
		{
			MockResolveFailure.MockResolveFailures.Clear();
			gameObject.FixReferencesInternal(recursive: false);
			string prefabName = (Object.op_Implicit((Object)(object)gameObject) ? ((Object)gameObject).name : string.Empty);
			MockResolveFailure.PrintMockResolveFailures(prefabName);
		}

		public static void FixReferences(this GameObject gameObject, bool recursive)
		{
			MockResolveFailure.MockResolveFailures.Clear();
			gameObject.FixReferencesInternal(recursive);
			string prefabName = (Object.op_Implicit((Object)(object)gameObject) ? ((Object)gameObject).name : string.Empty);
			MockResolveFailure.PrintMockResolveFailures(prefabName);
		}

		private static void FixReferencesInternal(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.FixReferencesInternal(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.27.1")]
	[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.27.1";

		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;
	}
	public class MockResolveFailure
	{
		public static List<MockResolveFailure> MockResolveFailures { get; } = new List<MockResolveFailure>();


		public string Message { get; private set; }

		public string FailedMockName { get; private set; }

		public string FailedMockPath { get; private set; }

		public Type MockType { get; private set; }

		public MockResolveFailure(string message, string failedMockName, string failedMockPath, Type mockType)
		{
			Message = message;
			FailedMockName = failedMockName;
			FailedMockPath = failedMockPath;
			MockType = mockType;
		}

		public MockResolveFailure(string message, string failedMockName, IEnumerable<string> failedMockPath, Type mockType)
		{
			Message = message;
			FailedMockName = failedMockName;
			FailedMockPath = string.Join<string>("->", failedMockPath);
			MockType = mockType;
		}

		private string ConstructMessage()
		{
			if (string.IsNullOrEmpty(FailedMockPath))
			{
				return ("Mock '" + FailedMockName + "' " + MockType.Name + " could not be resolved. " + Message).Trim();
			}
			return ("Mock " + MockType.Name + " at '" + FailedMockName + "' with child path '" + FailedMockPath + "' could not be resolved. " + Message).Trim();
		}

		public static void PrintMockResolveFailures(string prefabName)
		{
			if (MockResolveFailures.Count == 0)
			{
				return;
			}
			BepInPlugin sourceMod = ModQuery.GetPrefab(prefabName)?.SourceMod;
			int num = Math.Min(5, MockResolveFailures.Count);
			string arg = (string.IsNullOrEmpty(prefabName) ? "" : ("for '" + prefabName + "'"));
			string arg2 = ((MockResolveFailures.Count > num) ? $"(logging first {num} issues)" : "");
			Logger.LogWarning(sourceMod, $"{MockResolveFailures.Count} mocks {arg} could not be resolved. {arg2}".Replace("  ", " ").Trim());
			foreach (MockResolveFailure item in MockResolveFailures.GetRange(0, num))
			{
				Logger.LogWarning(sourceMod, item.ConstructMessage());
			}
		}
	}
	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 = '$';

		private static MethodInfo LoadImageMethod { get; } = AccessTools.Method(typeof(ImageConversion), "LoadImage", new Type[2]
		{
			typeof(Texture2D),
			typeof(byte[])
		}, (Type[])null);


		public static Texture2D LoadTexture(string texturePath, bool relativePath = true)
		{
			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[] data = File.ReadAllBytes(text);
			return LoadImage(data);
		}

		public static Texture2D LoadImage(byte[] data)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: Expected O, but got Unknown
			Texture2D val = new Texture2D(2, 2);
			if (!LoadImage(val, data))
			{
				return null;
			}
			return val;
		}

		public static bool LoadImage(Texture2D texture, byte[] data)
		{
			return (bool)LoadImageMethod.Invoke(null, new object[2] { texture, data });
		}

		public static Texture2D DuplicateTexture(Texture2D texture, Rect textureRect)
		{
			//IL_005c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0063: Expec

BepInEx/plugins/ShieldBash/ShieldBash.dll

Decompiled a day ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Configuration;
using HarmonyLib;
using Jotunn.Configs;
using Jotunn.Managers;
using UnityEngine;
using UnityEngine.Animations;
using UnityEngine.Playables;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: AssemblyTitle("ShieldBash")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("ShieldBash")]
[assembly: AssemblyCopyright("Copyright ©  2026")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("be1580d5-2dda-4cf4-b5c8-d4f902314e67")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: TargetFramework(".NETFramework,Version=v4.8.1", FrameworkDisplayName = ".NET Framework 4.8.1")]
[assembly: AssemblyVersion("1.0.0.0")]
namespace ShieldBashMod;

[BepInPlugin("alexbez.valheim.shieldbash", "ShieldBash", "1.3.0")]
[BepInDependency(/*Could not decode attribute arguments.*/)]
public sealed class ShieldBashPlugin : BaseUnityPlugin
{
	[HarmonyPatch]
	private static class ShieldTooltipPatch
	{
		[CompilerGenerated]
		private sealed class <TargetMethods>d__0 : IEnumerable<MethodBase>, IEnumerable, IEnumerator<MethodBase>, IDisposable, IEnumerator
		{
			private int <>1__state;

			private MethodBase <>2__current;

			private int <>l__initialThreadId;

			private MethodInfo[] <methods>5__1;

			private int <i>5__2;

			private MethodInfo <m>5__3;

			MethodBase IEnumerator<MethodBase>.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			object IEnumerator.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			[DebuggerHidden]
			public <TargetMethods>d__0(int <>1__state)
			{
				this.<>1__state = <>1__state;
				<>l__initialThreadId = Environment.CurrentManagedThreadId;
			}

			[DebuggerHidden]
			void IDisposable.Dispose()
			{
				<methods>5__1 = null;
				<m>5__3 = null;
				<>1__state = -2;
			}

			private bool MoveNext()
			{
				int num = <>1__state;
				if (num != 0)
				{
					if (num != 1)
					{
						return false;
					}
					<>1__state = -1;
					<m>5__3 = null;
					goto IL_00ce;
				}
				<>1__state = -1;
				<methods>5__1 = typeof(ItemData).GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
				<i>5__2 = 0;
				goto IL_00e0;
				IL_00ce:
				<i>5__2++;
				goto IL_00e0;
				IL_00e0:
				if (<i>5__2 < <methods>5__1.Length)
				{
					<m>5__3 = <methods>5__1[<i>5__2];
					if (<m>5__3 == null || <m>5__3.Name != "GetTooltip" || <m>5__3.ReturnType != typeof(string))
					{
						goto IL_00ce;
					}
					<>2__current = <m>5__3;
					<>1__state = 1;
					return true;
				}
				return false;
			}

			bool IEnumerator.MoveNext()
			{
				//ILSpy generated this explicit interface implementation from .override directive in MoveNext
				return this.MoveNext();
			}

			[DebuggerHidden]
			void IEnumerator.Reset()
			{
				throw new NotSupportedException();
			}

			[DebuggerHidden]
			IEnumerator<MethodBase> IEnumerable<MethodBase>.GetEnumerator()
			{
				if (<>1__state == -2 && <>l__initialThreadId == Environment.CurrentManagedThreadId)
				{
					<>1__state = 0;
					return this;
				}
				return new <TargetMethods>d__0(0);
			}

			[DebuggerHidden]
			IEnumerator IEnumerable.GetEnumerator()
			{
				return ((IEnumerable<MethodBase>)this).GetEnumerator();
			}
		}

		[IteratorStateMachine(typeof(<TargetMethods>d__0))]
		private static IEnumerable<MethodBase> TargetMethods()
		{
			//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
			return new <TargetMethods>d__0(-2);
		}

		private static void Postfix(ItemData __instance, ref string __result)
		{
			//IL_005e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0064: Invalid comparison between Unknown and I4
			try
			{
				ShieldBashPlugin instance = Instance;
				if ((Object)(object)instance == (Object)null || !instance.ShowShieldBashInTooltip.Value || __instance == null || __instance.m_shared == null || (int)__instance.m_shared.m_itemType != 5)
				{
					return;
				}
				string text = instance.BuildTooltipLineForShield(__instance);
				if (!string.IsNullOrEmpty(text))
				{
					string text2 = __result;
					if (string.IsNullOrEmpty(text2) || (text2.IndexOf("Shield Bash:", StringComparison.Ordinal) < 0 && text2.IndexOf("Удар щитом:", StringComparison.Ordinal) < 0))
					{
						__result = text2 + text;
					}
				}
			}
			catch
			{
			}
		}
	}

	[CompilerGenerated]
	private sealed class <AntiSlideRoutine>d__78 : IEnumerator<object>, IDisposable, IEnumerator
	{
		private int <>1__state;

		private object <>2__current;

		public Player player;

		public float duration;

		public ShieldBashPlugin <>4__this;

		private Rigidbody <body>5__1;

		private float <t>5__2;

		private Vector3 <v>5__3;

		object IEnumerator<object>.Current
		{
			[DebuggerHidden]
			get
			{
				return <>2__current;
			}
		}

		object IEnumerator.Current
		{
			[DebuggerHidden]
			get
			{
				return <>2__current;
			}
		}

		[DebuggerHidden]
		public <AntiSlideRoutine>d__78(int <>1__state)
		{
			this.<>1__state = <>1__state;
		}

		[DebuggerHidden]
		void IDisposable.Dispose()
		{
			<body>5__1 = null;
			<>1__state = -2;
		}

		private bool MoveNext()
		{
			//IL_0099: Unknown result type (might be due to invalid IL or missing references)
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0054: Expected O, but got Unknown
			//IL_00d9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00de: Unknown result type (might be due to invalid IL or missing references)
			//IL_010a: Unknown result type (might be due to invalid IL or missing references)
			switch (<>1__state)
			{
			default:
				return false;
			case 0:
				<>1__state = -1;
				if ((Object)(object)player == (Object)null)
				{
					return false;
				}
				<body>5__1 = null;
				try
				{
					<body>5__1 = CharacterBody.Invoke((Character)player);
				}
				catch
				{
					<body>5__1 = null;
				}
				if ((Object)(object)<body>5__1 == (Object)null)
				{
					return false;
				}
				<t>5__2 = 0f;
				SetMoveDirZero(player);
				<body>5__1.linearVelocity = Vector3.zero;
				break;
			case 1:
				<>1__state = -1;
				break;
			}
			if (<t>5__2 < duration)
			{
				if ((Object)(object)player == (Object)null)
				{
					return false;
				}
				if ((Object)(object)<body>5__1 == (Object)null)
				{
					return false;
				}
				<v>5__3 = <body>5__1.linearVelocity;
				<v>5__3.x = 0f;
				<v>5__3.z = 0f;
				<body>5__1.linearVelocity = <v>5__3;
				SetMoveDirZero(player);
				<t>5__2 += Time.deltaTime;
				<>2__current = null;
				<>1__state = 1;
				return true;
			}
			return false;
		}

		bool IEnumerator.MoveNext()
		{
			//ILSpy generated this explicit interface implementation from .override directive in MoveNext
			return this.MoveNext();
		}

		[DebuggerHidden]
		void IEnumerator.Reset()
		{
			throw new NotSupportedException();
		}
	}

	[CompilerGenerated]
	private sealed class <DoBash>d__77 : IEnumerator<object>, IDisposable, IEnumerator
	{
		private int <>1__state;

		private object <>2__current;

		public Player player;

		public Animator animator;

		public AnimationClip clip;

		public ShieldBashPlugin <>4__this;

		private bool <prevRootMotion>5__1;

		private PlayableGraph <graph>5__2;

		private AnimatorControllerPlayable <controllerPlayable>5__3;

		private AnimationClipPlayable <clipPlayable>5__4;

		private AnimationLayerMixerPlayable <mixer>5__5;

		private AnimationPlayableOutput <output>5__6;

		private float <hitAt>5__7;

		private float <remain>5__8;

		object IEnumerator<object>.Current
		{
			[DebuggerHidden]
			get
			{
				return <>2__current;
			}
		}

		object IEnumerator.Current
		{
			[DebuggerHidden]
			get
			{
				return <>2__current;
			}
		}

		[DebuggerHidden]
		public <DoBash>d__77(int <>1__state)
		{
			this.<>1__state = <>1__state;
		}

		[DebuggerHidden]
		void IDisposable.Dispose()
		{
			int num = <>1__state;
			if (num == -3 || (uint)(num - 1) <= 1u)
			{
				try
				{
				}
				finally
				{
					<>m__Finally1();
				}
			}
			<>1__state = -2;
		}

		private bool MoveNext()
		{
			//IL_023c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0246: Expected O, but got Unknown
			//IL_00a4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ce: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e5: Unknown result type (might be due to invalid IL or missing references)
			//IL_0106: Unknown result type (might be due to invalid IL or missing references)
			//IL_010c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0111: Unknown result type (might be due to invalid IL or missing references)
			//IL_011d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0124: Unknown result type (might be due to invalid IL or missing references)
			//IL_0137: Unknown result type (might be due to invalid IL or missing references)
			//IL_013e: Unknown result type (might be due to invalid IL or missing references)
			//IL_014b: Unknown result type (might be due to invalid IL or missing references)
			//IL_015d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0170: Unknown result type (might be due to invalid IL or missing references)
			//IL_0180: Unknown result type (might be due to invalid IL or missing references)
			//IL_0185: Unknown result type (might be due to invalid IL or missing references)
			//IL_018b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0191: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e4: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ee: Expected O, but got Unknown
			try
			{
				switch (<>1__state)
				{
				default:
					return false;
				case 0:
					<>1__state = -1;
					if (<>4__this.AntiSlideTime.Value > 0.0001f)
					{
						((MonoBehaviour)<>4__this).StartCoroutine(<>4__this.AntiSlideRoutine(player, <>4__this.AntiSlideTime.Value));
					}
					<prevRootMotion>5__1 = animator.applyRootMotion;
					animator.applyRootMotion = false;
					<graph>5__2 = PlayableGraph.Create("ShieldBashGraph");
					<>1__state = -3;
					<controllerPlayable>5__3 = AnimatorControllerPlayable.Create(<graph>5__2, animator.runtimeAnimatorController);
					<clipPlayable>5__4 = AnimationClipPlayable.Create(<graph>5__2, clip);
					((AnimationClipPlayable)(ref <clipPlayable>5__4)).SetApplyFootIK(false);
					((AnimationClipPlayable)(ref <clipPlayable>5__4)).SetApplyPlayableIK(false);
					<mixer>5__5 = AnimationLayerMixerPlayable.Create(<graph>5__2, 2);
					((PlayableGraph)(ref <graph>5__2)).Connect<AnimatorControllerPlayable, AnimationLayerMixerPlayable>(<controllerPlayable>5__3, 0, <mixer>5__5, 0);
					((PlayableGraph)(ref <graph>5__2)).Connect<AnimationClipPlayable, AnimationLayerMixerPlayable>(<clipPlayable>5__4, 0, <mixer>5__5, 1);
					PlayableExtensions.SetInputWeight<AnimationLayerMixerPlayable>(<mixer>5__5, 0, 0f);
					PlayableExtensions.SetInputWeight<AnimationLayerMixerPlayable>(<mixer>5__5, 1, 1f);
					<output>5__6 = AnimationPlayableOutput.Create(<graph>5__2, "ShieldBashOutput", animator);
					PlayableOutputExtensions.SetSourcePlayable<AnimationPlayableOutput, AnimationLayerMixerPlayable>(<output>5__6, <mixer>5__5);
					((PlayableGraph)(ref <graph>5__2)).Play();
					<hitAt>5__7 = Mathf.Clamp(<>4__this.HitDelay.Value, 0.01f, Mathf.Max(0.01f, clip.length));
					<>2__current = (object)new WaitForSeconds(<hitAt>5__7);
					<>1__state = 1;
					return true;
				case 1:
					<>1__state = -3;
					<>4__this.ApplyBashDamageAndSfx(player);
					<remain>5__8 = Mathf.Max(0.01f, clip.length - <hitAt>5__7);
					<>2__current = (object)new WaitForSeconds(<remain>5__8);
					<>1__state = 2;
					return true;
				case 2:
					<>1__state = -3;
					<>m__Finally1();
					return false;
				}
			}
			catch
			{
				//try-fault
				((IDisposable)this).Dispose();
				throw;
			}
		}

		bool IEnumerator.MoveNext()
		{
			//ILSpy generated this explicit interface implementation from .override directive in MoveNext
			return this.MoveNext();
		}

		private void <>m__Finally1()
		{
			<>1__state = -1;
			if (((PlayableGraph)(ref <graph>5__2)).IsValid())
			{
				((PlayableGraph)(ref <graph>5__2)).Destroy();
			}
			animator.applyRootMotion = <prevRootMotion>5__1;
		}

		[DebuggerHidden]
		void IEnumerator.Reset()
		{
			throw new NotSupportedException();
		}
	}

	public const string PluginGUID = "alexbez.valheim.shieldbash";

	public const string PluginName = "ShieldBash";

	public const string PluginVersion = "1.3.0";

	internal static ShieldBashPlugin Instance;

	internal ConfigEntry<KeyCode> BashKey;

	internal ConfigEntry<float> Cooldown;

	internal ConfigEntry<bool> RequireShield;

	internal ConfigEntry<float> StaminaCost;

	internal ConfigEntry<float> AntiSlideTime;

	internal ConfigEntry<float> BaseDamage;

	internal ConfigEntry<float> BlockPowerScale;

	internal ConfigEntry<float> QualityBonusPerLevel;

	internal ConfigEntry<float> MinDamage;

	internal ConfigEntry<float> MaxDamage;

	internal ConfigEntry<float> BlockingSkillMultiplier;

	internal ConfigEntry<float> DamageRandomMin;

	internal ConfigEntry<float> DamageRandomMax;

	internal ConfigEntry<float> CenterHitBonusMax;

	internal ConfigEntry<float> HitDelay;

	internal ConfigEntry<bool> DamageWorldObjects;

	internal ConfigEntry<float> WorldDamageScale;

	internal ConfigEntry<bool> WorldDamageUseRandom;

	internal ConfigEntry<float> Range;

	internal ConfigEntry<float> Radius;

	internal ConfigEntry<float> PushForce;

	internal ConfigEntry<float> Angle;

	internal ConfigEntry<bool> LineOfSightCheck;

	internal ConfigEntry<int> MaxLoSRaycastsPerBash;

	internal ConfigEntry<bool> HitTamed;

	internal ConfigEntry<bool> HitPlayers;

	internal ConfigEntry<int> OverlapBufferSize;

	internal ConfigEntry<bool> ShowShieldBashInTooltip;

	internal ConfigEntry<bool> DebugLog;

	internal ConfigEntry<bool> DebugLogDamageAfterArmor;

	internal ConfigEntry<string> HitClipName;

	internal ConfigEntry<string> MissClipName;

	internal ConfigEntry<bool> PlayHitSfxPerTarget;

	internal ConfigEntry<float> HitSfxVolumeMin;

	internal ConfigEntry<float> HitSfxVolumeMax;

	internal ConfigEntry<float> MissSfxVolume;

	internal ConfigEntry<float> RandomVolJitterMin;

	internal ConfigEntry<float> RandomVolJitterMax;

	internal ConfigEntry<float> RandomPitchJitterMin;

	internal ConfigEntry<float> RandomPitchJitterMax;

	internal ConfigEntry<float> MetalVolumeMul;

	internal ConfigEntry<float> WoodVolumeMul;

	internal ConfigEntry<float> MetalPitchMul;

	internal ConfigEntry<float> WoodPitchMul;

	internal ConfigEntry<float> MultiHitBonusMin;

	internal ConfigEntry<float> MultiHitBonusMax;

	internal ConfigEntry<float> LocalClipVolumeMul;

	private ButtonConfig _bashButton;

	private Harmony _harmony;

	private AnimationClip _bashClip;

	private AudioClip _hitClip;

	private AudioClip _missClip;

	private float _nextUseTime;

	private Collider[] _overlapCols;

	private int[] _hitOnceIds;

	private int _hitOnceCount;

	private int _overlapMask = -1;

	private int _losWorldMask = -1;

	private float _cachedAngle = -999f;

	private float _cachedCosHalf = -2f;

	private AudioSource _localSfxSource;

	private static bool _locRefReady;

	private static Type _locType;

	private static PropertyInfo _locInstanceProp;

	private static MethodInfo _locGetSelectedLanguage;

	private static readonly FieldRef<Character, Animator> CharacterAnimator = AccessTools.FieldRefAccess<Character, Animator>("m_animator");

	private static readonly FieldRef<Character, Rigidbody> CharacterBody = AccessTools.FieldRefAccess<Character, Rigidbody>("m_body");

	private static readonly FieldRef<Character, Vector3> CharacterMoveDir = AccessTools.FieldRefAccess<Character, Vector3>("m_moveDir");

	private static readonly FieldRef<Humanoid, ItemData> HumanoidLeftItem = AccessTools.FieldRefAccess<Humanoid, ItemData>("m_leftItem");

	private void Awake()
	{
		//IL_06a1: Unknown result type (might be due to invalid IL or missing references)
		//IL_06ab: Expected O, but got Unknown
		//IL_06c8: Unknown result type (might be due to invalid IL or missing references)
		//IL_0707: Unknown result type (might be due to invalid IL or missing references)
		//IL_0711: Expected O, but got Unknown
		Instance = this;
		BashKey = ((BaseUnityPlugin)this).Config.Bind<KeyCode>("Input", "BashKey", (KeyCode)102, "Key for Shield Bash");
		Cooldown = ((BaseUnityPlugin)this).Config.Bind<float>("Balance", "Cooldown", 0.9f, "Cooldown seconds");
		RequireShield = ((BaseUnityPlugin)this).Config.Bind<bool>("Balance", "RequireShield", true, "Require shield in left hand");
		StaminaCost = ((BaseUnityPlugin)this).Config.Bind<float>("Balance", "StaminaCost", 18f, "Stamina cost per bash (no message if insufficient)");
		AntiSlideTime = ((BaseUnityPlugin)this).Config.Bind<float>("Feel", "AntiSlideTime", 0.2f, "Anti-slide duration seconds (0 = off)");
		BaseDamage = ((BaseUnityPlugin)this).Config.Bind<float>("Damage", "BaseDamage", 10f, "Flat blunt damage added to bash");
		BlockPowerScale = ((BaseUnityPlugin)this).Config.Bind<float>("Damage", "BlockPowerScale", 0.6f, "Damage per 1 shield block power");
		QualityBonusPerLevel = ((BaseUnityPlugin)this).Config.Bind<float>("Damage", "QualityBonusPerLevel", 0.8f, "Soft bonus damage per shield upgrade level (quality-1)");
		MinDamage = ((BaseUnityPlugin)this).Config.Bind<float>("Damage", "MinDamage", 6f, "Minimum final damage (after multipliers)");
		MaxDamage = ((BaseUnityPlugin)this).Config.Bind<float>("Damage", "MaxDamage", 45f, "Maximum final damage cap (after multipliers)");
		BlockingSkillMultiplier = ((BaseUnityPlugin)this).Config.Bind<float>("Damage", "BlockingSkillMultiplier", 0.35f, "damage *= 1 + skillFactor(0..1) * value");
		DamageRandomMin = ((BaseUnityPlugin)this).Config.Bind<float>("Damage", "DamageRandomMin", 0.92f, "Per-bash random damage multiplier min.");
		DamageRandomMax = ((BaseUnityPlugin)this).Config.Bind<float>("Damage", "DamageRandomMax", 1.08f, "Per-bash random damage multiplier max.");
		CenterHitBonusMax = ((BaseUnityPlugin)this).Config.Bind<float>("Damage", "CenterHitBonusMax", 0.12f, "Up to +X% damage when target is centered in cone.");
		HitDelay = ((BaseUnityPlugin)this).Config.Bind<float>("Damage", "HitDelay", 0.12f, "Seconds after animation start when damage is applied");
		DamageWorldObjects = ((BaseUnityPlugin)this).Config.Bind<bool>("WorldDamage", "DamageWorldObjects", true, "Allow Shield Bash to damage trees/rocks/buildings.");
		WorldDamageScale = ((BaseUnityPlugin)this).Config.Bind<float>("WorldDamage", "WorldDamageScale", 0.85f, "Multiplier for world-object damage.");
		WorldDamageUseRandom = ((BaseUnityPlugin)this).Config.Bind<bool>("WorldDamage", "WorldDamageUseRandom", false, "If true: world damage uses per-bash random multiplier.");
		Range = ((BaseUnityPlugin)this).Config.Bind<float>("Hitbox", "Range", 1.6f, "Forward distance of hit center");
		Radius = ((BaseUnityPlugin)this).Config.Bind<float>("Hitbox", "Radius", 0.9f, "Hit radius");
		PushForce = ((BaseUnityPlugin)this).Config.Bind<float>("Hitbox", "PushForce", 20f, "Push force applied to Characters");
		Angle = ((BaseUnityPlugin)this).Config.Bind<float>("Hitbox", "AngleDegrees", 110f, "Cone angle filter (degrees). 180 = no cone.");
		LineOfSightCheck = ((BaseUnityPlugin)this).Config.Bind<bool>("Hitbox", "LineOfSightCheck", true, "Raycast visibility check (avoid hitting through walls)");
		MaxLoSRaycastsPerBash = ((BaseUnityPlugin)this).Config.Bind<int>("Hitbox", "MaxLoSRaycastsPerBash", 6, "Max LoS raycasts per bash (CPU saver).");
		HitTamed = ((BaseUnityPlugin)this).Config.Bind<bool>("Targets", "HitTamed", false, "Hit tamed creatures");
		HitPlayers = ((BaseUnityPlugin)this).Config.Bind<bool>("Targets", "HitPlayers", false, "Hit other players (PvP)");
		OverlapBufferSize = ((BaseUnityPlugin)this).Config.Bind<int>("Performance", "OverlapBufferSize", 64, "NonAlloc overlap collider buffer size (64/96/128)");
		ShowShieldBashInTooltip = ((BaseUnityPlugin)this).Config.Bind<bool>("UI", "ShowShieldBashInTooltip", true, "Add Shield Bash damage line to shield tooltip (RU/EN)");
		DebugLog = ((BaseUnityPlugin)this).Config.Bind<bool>("Debug", "Log", false, "General debug logging");
		DebugLogDamageAfterArmor = ((BaseUnityPlugin)this).Config.Bind<bool>("Debug", "LogDamageAfterArmor", false, "Log dealt damage per hit target");
		HitClipName = ((BaseUnityPlugin)this).Config.Bind<string>("SFX", "HitClipName", "shield_bash_hit", "AudioClip.name inside AssetBundle for HIT sound.");
		MissClipName = ((BaseUnityPlugin)this).Config.Bind<string>("SFX", "MissClipName", "shield_bash_miss", "AudioClip.name inside AssetBundle for MISS sound.");
		PlayHitSfxPerTarget = ((BaseUnityPlugin)this).Config.Bind<bool>("SFX", "PlayHitSfxPerTarget", false, "If true: play hit sound for each target.");
		HitSfxVolumeMin = ((BaseUnityPlugin)this).Config.Bind<float>("SFX", "HitSfxVolumeMin", 0.6f, "Min hit volume at MinDamage.");
		HitSfxVolumeMax = ((BaseUnityPlugin)this).Config.Bind<float>("SFX", "HitSfxVolumeMax", 1.1f, "Max hit volume at MaxDamage.");
		MissSfxVolume = ((BaseUnityPlugin)this).Config.Bind<float>("SFX", "MissSfxVolume", 0.7f, "Base miss whoosh volume.");
		RandomVolJitterMin = ((BaseUnityPlugin)this).Config.Bind<float>("SFX", "RandomVolJitterMin", 0.95f, "Random volume multiplier min.");
		RandomVolJitterMax = ((BaseUnityPlugin)this).Config.Bind<float>("SFX", "RandomVolJitterMax", 1.05f, "Random volume multiplier max.");
		RandomPitchJitterMin = ((BaseUnityPlugin)this).Config.Bind<float>("SFX", "RandomPitchJitterMin", 0.97f, "Random pitch multiplier min.");
		RandomPitchJitterMax = ((BaseUnityPlugin)this).Config.Bind<float>("SFX", "RandomPitchJitterMax", 1.03f, "Random pitch multiplier max.");
		MetalVolumeMul = ((BaseUnityPlugin)this).Config.Bind<float>("SFX", "MetalVolumeMul", 1.07f, "Volume multiplier for metal shields.");
		WoodVolumeMul = ((BaseUnityPlugin)this).Config.Bind<float>("SFX", "WoodVolumeMul", 0.92f, "Volume multiplier for wood shields.");
		MetalPitchMul = ((BaseUnityPlugin)this).Config.Bind<float>("SFX", "MetalPitchMul", 1.02f, "Pitch multiplier for metal shields.");
		WoodPitchMul = ((BaseUnityPlugin)this).Config.Bind<float>("SFX", "WoodPitchMul", 0.96f, "Pitch multiplier for wood shields.");
		MultiHitBonusMin = ((BaseUnityPlugin)this).Config.Bind<float>("SFX", "MultiHitBonusMin", 0.05f, "Bonus volume add when hits>1, min.");
		MultiHitBonusMax = ((BaseUnityPlugin)this).Config.Bind<float>("SFX", "MultiHitBonusMax", 0.1f, "Bonus volume add when hits>1, max.");
		LocalClipVolumeMul = ((BaseUnityPlugin)this).Config.Bind<float>("SFX", "LocalClipVolumeMul", 1f, "Multiplier for local AudioClips.");
		_bashButton = new ButtonConfig();
		_bashButton.Name = "ShieldBash";
		_bashButton.Key = BashKey.Value;
		_bashButton.HintToken = "Shield Bash";
		InputManager.Instance.AddButton("alexbez.valheim.shieldbash", _bashButton);
		EnsureBuffers();
		_harmony = new Harmony("alexbez.valheim.shieldbash");
		_harmony.PatchAll();
		bool flag = LoadAssetsFromBundle();
		((BaseUnityPlugin)this).Logger.LogInfo((object)string.Format("[{0}] Assets loaded: {1} (anim={2}, hit={3}, miss={4})", "ShieldBash", flag, ((Object)(object)_bashClip != (Object)null) ? ((Object)_bashClip).name : "null", ((Object)(object)_hitClip != (Object)null) ? ((Object)_hitClip).name : "null", ((Object)(object)_missClip != (Object)null) ? ((Object)_missClip).name : "null"));
	}

	private void OnDestroy()
	{
		try
		{
			if (_harmony != null)
			{
				_harmony.UnpatchSelf();
			}
		}
		catch
		{
		}
		try
		{
			if ((Object)(object)_localSfxSource != (Object)null && (Object)(object)((Component)_localSfxSource).gameObject != (Object)null)
			{
				Object.Destroy((Object)(object)((Component)_localSfxSource).gameObject);
			}
		}
		catch
		{
		}
	}

	private void EnsureBuffers()
	{
		int num = Mathf.Clamp(OverlapBufferSize.Value, 16, 256);
		if (_overlapCols == null)
		{
			_overlapCols = (Collider[])(object)new Collider[num];
		}
		else if (_overlapCols.Length != num)
		{
			_overlapCols = (Collider[])(object)new Collider[num];
		}
		int num2 = Mathf.Clamp(num * 2, 32, 1024);
		if (_hitOnceIds == null)
		{
			_hitOnceIds = new int[num2];
		}
		else if (_hitOnceIds.Length != num2)
		{
			_hitOnceIds = new int[num2];
		}
		_hitOnceCount = 0;
	}

	private void Update()
	{
		//IL_000e: 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)
		//IL_00ce: Expected O, but got Unknown
		EnsureBuffers();
		if (!Input.GetKeyDown(BashKey.Value))
		{
			return;
		}
		Player localPlayer = Player.m_localPlayer;
		if ((Object)(object)localPlayer == (Object)null || Time.time < _nextUseTime)
		{
			return;
		}
		if ((Object)(object)_bashClip == (Object)null)
		{
			((BaseUnityPlugin)this).Logger.LogWarning((object)"[ShieldBash] Bash clip is null. Bundle/clip not loaded.");
		}
		else if ((!RequireShield.Value || HasShieldInLeftHand(localPlayer)) && TryUseStaminaNoMessage(localPlayer, StaminaCost.Value))
		{
			Animator animator = GetAnimator((Character)localPlayer);
			if (!((Object)(object)animator == (Object)null))
			{
				_nextUseTime = Time.time + Cooldown.Value;
				((MonoBehaviour)this).StartCoroutine(DoBash(localPlayer, animator, _bashClip));
			}
		}
	}

	[IteratorStateMachine(typeof(<DoBash>d__77))]
	private IEnumerator DoBash(Player player, Animator animator, AnimationClip clip)
	{
		//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
		return new <DoBash>d__77(0)
		{
			<>4__this = this,
			player = player,
			animator = animator,
			clip = clip
		};
	}

	[IteratorStateMachine(typeof(<AntiSlideRoutine>d__78))]
	private IEnumerator AntiSlideRoutine(Player player, float duration)
	{
		//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
		return new <AntiSlideRoutine>d__78(0)
		{
			<>4__this = this,
			player = player,
			duration = duration
		};
	}

	private static void SetMoveDirZero(Player player)
	{
		//IL_0017: Unknown result type (might be due to invalid IL or missing references)
		//IL_0021: Expected O, but got Unknown
		//IL_0023: Unknown result type (might be due to invalid IL or missing references)
		//IL_0028: Unknown result type (might be due to invalid IL or missing references)
		if ((Object)(object)player == (Object)null)
		{
			return;
		}
		try
		{
			CharacterMoveDir.Invoke((Character)player) = Vector3.zero;
		}
		catch
		{
		}
	}

	private bool TryUseStaminaNoMessage(Player player, float cost)
	{
		if (cost <= 0f)
		{
			return true;
		}
		if (player.GetStamina() + 0.001f < cost)
		{
			return false;
		}
		((Character)player).UseStamina(cost);
		return true;
	}

	internal float ComputeShieldBaseDamage(ItemData shield)
	{
		int num = 1;
		float num2 = 0f;
		if (shield != null && shield.m_shared != null)
		{
			num = Mathf.Max(1, shield.m_quality);
			num2 = shield.m_shared.m_blockPower + shield.m_shared.m_blockPowerPerLevel * (float)(num - 1);
		}
		return BaseDamage.Value + num2 * BlockPowerScale.Value + (float)Mathf.Max(0, num - 1) * Mathf.Max(0f, QualityBonusPerLevel.Value);
	}

	private float GetBlockingSkillFactor(Player player)
	{
		if ((Object)(object)player == (Object)null)
		{
			return 0f;
		}
		try
		{
			return Mathf.Clamp01(((Character)player).GetSkillFactor((SkillType)6));
		}
		catch
		{
			return 0f;
		}
	}

	private float ApplySkillAndRandom(float baseDamage, float skillFactor, float randMul)
	{
		float num = Mathf.Max(0f, BlockingSkillMultiplier.Value);
		float num2 = baseDamage * (1f + skillFactor * num);
		num2 *= randMul;
		return Mathf.Clamp(num2, MinDamage.Value, MaxDamage.Value);
	}

	private float GetCenterBonus01(float dotForward, float cosHalf)
	{
		if (dotForward <= cosHalf)
		{
			return 0f;
		}
		if (cosHalf >= 0.9999f)
		{
			return 1f;
		}
		return Mathf.Clamp01((dotForward - cosHalf) / (1f - cosHalf));
	}

	private int GetOverlapMask()
	{
		if (_overlapMask != -1)
		{
			return _overlapMask;
		}
		_overlapMask = LayerMask.GetMask(new string[7] { "character", "character_net", "Default", "static_solid", "piece", "Hitbox", "hitbox" });
		if (_overlapMask == 0)
		{
			_overlapMask = -1;
		}
		return _overlapMask;
	}

	private int GetWorldLosMask()
	{
		if (_losWorldMask != -1)
		{
			return _losWorldMask;
		}
		_losWorldMask = LayerMask.GetMask(new string[7] { "Default", "static_solid", "piece", "Hitbox", "hitbox", "character", "character_net" });
		if (_losWorldMask == 0)
		{
			_losWorldMask = -1;
		}
		return _losWorldMask;
	}

	private float GetCosHalfAngle()
	{
		float num = Mathf.Clamp(Angle.Value, 1f, 180f);
		if (Mathf.Abs(num - _cachedAngle) < 0.001f && _cachedCosHalf > -1f)
		{
			return _cachedCosHalf;
		}
		_cachedAngle = num;
		_cachedCosHalf = Mathf.Cos(num * ((float)Math.PI / 180f) * 0.5f);
		return _cachedCosHalf;
	}

	private void HitOnceReset()
	{
		_hitOnceCount = 0;
	}

	private bool HitOnceTryAdd(int id)
	{
		for (int i = 0; i < _hitOnceCount; i++)
		{
			if (_hitOnceIds[i] == id)
			{
				return false;
			}
		}
		if (_hitOnceCount >= _hitOnceIds.Length)
		{
			return false;
		}
		_hitOnceIds[_hitOnceCount] = id;
		_hitOnceCount++;
		return true;
	}

	private static Vector3 GetSafeHitPoint(Collider col, Vector3 nearPoint, Vector3 fallback)
	{
		//IL_0012: Unknown result type (might be due to invalid IL or missing references)
		//IL_0013: Unknown result type (might be due to invalid IL or missing references)
		//IL_0018: Unknown result type (might be due to invalid IL or missing references)
		//IL_0019: 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)
		//IL_000e: Unknown result type (might be due to invalid IL or missing references)
		//IL_002d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0029: Unknown result type (might be due to invalid IL or missing references)
		//IL_002a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0047: Unknown result type (might be due to invalid IL or missing references)
		//IL_0043: Unknown result type (might be due to invalid IL or missing references)
		//IL_0044: Unknown result type (might be due to invalid IL or missing references)
		//IL_003f: 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)
		if ((Object)(object)col == (Object)null)
		{
			return fallback;
		}
		Vector3 val = col.ClosestPointOnBounds(nearPoint);
		if (float.IsNaN(val.x))
		{
			return fallback;
		}
		if (float.IsInfinity(val.x))
		{
			return fallback;
		}
		return val;
	}

	private void ApplyBashDamageAndSfx(Player player)
	{
		//IL_001d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0027: Expected O, but got Unknown
		//IL_01ab: Unknown result type (might be due to invalid IL or missing references)
		//IL_01b0: Unknown result type (might be due to invalid IL or missing references)
		//IL_01b8: Unknown result type (might be due to invalid IL or missing references)
		//IL_01bd: Unknown result type (might be due to invalid IL or missing references)
		//IL_01c7: Unknown result type (might be due to invalid IL or missing references)
		//IL_01cc: Unknown result type (might be due to invalid IL or missing references)
		//IL_01d1: Unknown result type (might be due to invalid IL or missing references)
		//IL_01d9: Unknown result type (might be due to invalid IL or missing references)
		//IL_01de: Unknown result type (might be due to invalid IL or missing references)
		//IL_01eb: Unknown result type (might be due to invalid IL or missing references)
		//IL_01f0: Unknown result type (might be due to invalid IL or missing references)
		//IL_01f5: Unknown result type (might be due to invalid IL or missing references)
		//IL_01f7: Unknown result type (might be due to invalid IL or missing references)
		//IL_01f9: Unknown result type (might be due to invalid IL or missing references)
		//IL_0203: Unknown result type (might be due to invalid IL or missing references)
		//IL_0208: Unknown result type (might be due to invalid IL or missing references)
		//IL_020d: Unknown result type (might be due to invalid IL or missing references)
		//IL_020f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0211: Unknown result type (might be due to invalid IL or missing references)
		//IL_021b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0220: Unknown result type (might be due to invalid IL or missing references)
		//IL_0225: Unknown result type (might be due to invalid IL or missing references)
		//IL_0237: Unknown result type (might be due to invalid IL or missing references)
		//IL_0239: Unknown result type (might be due to invalid IL or missing references)
		//IL_0259: Unknown result type (might be due to invalid IL or missing references)
		//IL_025b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0297: Unknown result type (might be due to invalid IL or missing references)
		//IL_029c: Unknown result type (might be due to invalid IL or missing references)
		//IL_02a3: Unknown result type (might be due to invalid IL or missing references)
		//IL_02a8: Unknown result type (might be due to invalid IL or missing references)
		//IL_02ad: Unknown result type (might be due to invalid IL or missing references)
		//IL_0802: Unknown result type (might be due to invalid IL or missing references)
		//IL_080d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0817: Unknown result type (might be due to invalid IL or missing references)
		//IL_081c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0821: Unknown result type (might be due to invalid IL or missing references)
		//IL_082b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0830: Unknown result type (might be due to invalid IL or missing references)
		//IL_0835: Unknown result type (might be due to invalid IL or missing references)
		//IL_0864: Unknown result type (might be due to invalid IL or missing references)
		//IL_06ab: Unknown result type (might be due to invalid IL or missing references)
		//IL_06ad: Unknown result type (might be due to invalid IL or missing references)
		//IL_06b3: Unknown result type (might be due to invalid IL or missing references)
		//IL_06b5: Unknown result type (might be due to invalid IL or missing references)
		//IL_06bf: Unknown result type (might be due to invalid IL or missing references)
		//IL_07ec: Unknown result type (might be due to invalid IL or missing references)
		//IL_06e5: Unknown result type (might be due to invalid IL or missing references)
		//IL_06e7: Unknown result type (might be due to invalid IL or missing references)
		//IL_0723: Unknown result type (might be due to invalid IL or missing references)
		//IL_0392: Unknown result type (might be due to invalid IL or missing references)
		//IL_0397: Unknown result type (might be due to invalid IL or missing references)
		//IL_03a1: Unknown result type (might be due to invalid IL or missing references)
		//IL_03a6: Unknown result type (might be due to invalid IL or missing references)
		//IL_03ab: Unknown result type (might be due to invalid IL or missing references)
		//IL_03ad: Unknown result type (might be due to invalid IL or missing references)
		//IL_03af: Unknown result type (might be due to invalid IL or missing references)
		//IL_03b1: 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_03d6: Unknown result type (might be due to invalid IL or missing references)
		//IL_03da: Unknown result type (might be due to invalid IL or missing references)
		//IL_03df: Unknown result type (might be due to invalid IL or missing references)
		//IL_03e1: Unknown result type (might be due to invalid IL or missing references)
		//IL_03e3: Unknown result type (might be due to invalid IL or missing references)
		//IL_04fa: Unknown result type (might be due to invalid IL or missing references)
		//IL_04fc: Unknown result type (might be due to invalid IL or missing references)
		//IL_04fe: Unknown result type (might be due to invalid IL or missing references)
		//IL_0503: Unknown result type (might be due to invalid IL or missing references)
		//IL_0528: Unknown result type (might be due to invalid IL or missing references)
		//IL_052f: Expected O, but got Unknown
		//IL_0532: Unknown result type (might be due to invalid IL or missing references)
		//IL_0537: Unknown result type (might be due to invalid IL or missing references)
		//IL_053e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0540: Unknown result type (might be due to invalid IL or missing references)
		//IL_054e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0559: Unknown result type (might be due to invalid IL or missing references)
		//IL_055e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0563: Unknown result type (might be due to invalid IL or missing references)
		//IL_0567: Unknown result type (might be due to invalid IL or missing references)
		//IL_056c: Unknown result type (might be due to invalid IL or missing references)
		//IL_043c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0442: Unknown result type (might be due to invalid IL or missing references)
		//IL_0444: Unknown result type (might be due to invalid IL or missing references)
		//IL_0646: Unknown result type (might be due to invalid IL or missing references)
		//IL_0648: Unknown result type (might be due to invalid IL or missing references)
		//IL_0684: Unknown result type (might be due to invalid IL or missing references)
		if ((Object)(object)player == (Object)null)
		{
			return;
		}
		HitOnceReset();
		ItemData leftItem = GetLeftItem((Humanoid)player);
		float num = ComputeShieldBaseDamage(leftItem);
		float num2 = DamageRandomMin.Value;
		float num3 = DamageRandomMax.Value;
		if (num2 > num3)
		{
			float num4 = num2;
			num2 = num3;
			num3 = num4;
		}
		float num5 = Random.Range(num2, num3);
		float blockingSkillFactor = GetBlockingSkillFactor(player);
		float num6 = ApplySkillAndRandom(num, blockingSkillFactor, num5);
		float randMul = ((!WorldDamageUseRandom.Value) ? 1f : num5);
		float num7 = ApplySkillAndRandom(num, blockingSkillFactor, randMul) * Mathf.Clamp(WorldDamageScale.Value, 0f, 5f);
		float num8 = Mathf.Clamp01(Mathf.InverseLerp(MinDamage.Value, MaxDamage.Value, num6));
		float num9 = Mathf.Lerp(HitSfxVolumeMin.Value, HitSfxVolumeMax.Value, num8);
		float num10 = Mathf.Max(0f, MissSfxVolume.Value);
		GetMaterialMix(leftItem, out var volMul, out var pitchMul);
		float num11 = Random.Range(Mathf.Min(RandomVolJitterMin.Value, RandomVolJitterMax.Value), Mathf.Max(RandomVolJitterMin.Value, RandomVolJitterMax.Value));
		float num12 = Random.Range(Mathf.Min(RandomPitchJitterMin.Value, RandomPitchJitterMax.Value), Mathf.Max(RandomPitchJitterMin.Value, RandomPitchJitterMax.Value));
		Vector3 forward = ((Component)player).transform.forward;
		Vector3 val = ((Component)player).transform.position + Vector3.up * 1.3f;
		Vector3 val2 = ((Component)player).transform.position + forward * Range.Value;
		Vector3 val3 = val2 + Vector3.up * 0.6f;
		Vector3 val4 = val2 + Vector3.up * 1.6f;
		int overlapMask = GetOverlapMask();
		float cosHalfAngle = GetCosHalfAngle();
		int num13 = Physics.OverlapCapsuleNonAlloc(val3, val4, Radius.Value, _overlapCols, overlapMask, (QueryTriggerInteraction)2);
		int num14 = 0;
		Vector3 pos = val;
		int losChecks = 0;
		int num15 = Mathf.Clamp(MaxLoSRaycastsPerBash.Value, 0, 64);
		float num16 = Mathf.Clamp(CenterHitBonusMax.Value, 0f, 1f);
		Vector3 nearPoint = ((Component)player).transform.position + forward * 0.5f;
		for (int i = 0; i < num13; i++)
		{
			Collider val5 = _overlapCols[i];
			if ((Object)(object)val5 == (Object)null)
			{
				continue;
			}
			Character componentInParent = ((Component)val5).GetComponentInParent<Character>();
			if ((Object)(object)componentInParent != (Object)null)
			{
				if (componentInParent == player || componentInParent.IsDead())
				{
					continue;
				}
				if (!HitTamed.Value)
				{
					Tameable component = ((Component)componentInParent).GetComponent<Tameable>();
					if ((Object)(object)component != (Object)null && component.IsTamed())
					{
						continue;
					}
				}
				if (!HitPlayers.Value)
				{
					Player val6 = (Player)(object)((componentInParent is Player) ? componentInParent : null);
					if ((Object)(object)val6 != (Object)null)
					{
						continue;
					}
				}
				Vector3 val7 = ((Component)componentInParent).transform.position + Vector3.up * 1.1f;
				Vector3 val8 = val7 - val;
				float magnitude = ((Vector3)(ref val8)).magnitude;
				if (magnitude < 0.001f)
				{
					continue;
				}
				Vector3 val9 = val8 / magnitude;
				float num17 = Vector3.Dot(forward, val9);
				if (num17 < cosHalfAngle)
				{
					continue;
				}
				if (LineOfSightCheck.Value && num15 > 0 && losChecks < num15)
				{
					losChecks++;
					int worldLosMask = GetWorldLosMask();
					RaycastHit val10 = default(RaycastHit);
					if (Physics.Raycast(val, val9, ref val10, magnitude, worldLosMask, (QueryTriggerInteraction)1))
					{
						Character val11 = null;
						if ((Object)(object)((RaycastHit)(ref val10)).collider != (Object)null)
						{
							val11 = ((Component)((RaycastHit)(ref val10)).collider).GetComponentInParent<Character>();
						}
						if (val11 != componentInParent)
						{
							continue;
						}
					}
				}
				if (HitOnceTryAdd(((Object)((Component)componentInParent).gameObject).GetInstanceID()))
				{
					float centerBonus = GetCenterBonus01(num17, cosHalfAngle);
					float num18 = 1f + centerBonus * num16;
					float blunt = Mathf.Clamp(num6 * num18, MinDamage.Value, MaxDamage.Value);
					Vector3 safeHitPoint = GetSafeHitPoint(val5, nearPoint, val7);
					float num19 = 0f;
					if (DebugLogDamageAfterArmor.Value)
					{
						num19 = componentInParent.GetHealth();
					}
					HitData val12 = new HitData();
					val12.m_attacker = ((Character)player).GetZDOID();
					val12.m_point = safeHitPoint;
					Vector3 val13 = ((Component)componentInParent).transform.position - ((Component)player).transform.position;
					val12.m_dir = ((Vector3)(ref val13)).normalized;
					val12.m_pushForce = PushForce.Value;
					val12.m_backstabBonus = 1f;
					val12.m_damage.m_blunt = blunt;
					componentInParent.Damage(val12);
					if (DebugLogDamageAfterArmor.Value)
					{
						float health = componentInParent.GetHealth();
						float num20 = Mathf.Max(0f, num19 - health);
						((BaseUnityPlugin)this).Logger.LogInfo((object)string.Format("[{0}] DEALT '{1}': {2:0.0} (base={3:0.0}, centerMul={4:0.00}) hp {5:0.0}->{6:0.0}", "ShieldBash", ((Object)componentInParent).name, num20, num6, num18, num19, health));
					}
					num14++;
					if (num14 == 1)
					{
						pos = safeHitPoint;
					}
					if (PlayHitSfxPerTarget.Value)
					{
						float volumeMul = Mathf.Max(0f, num9 * volMul * num11);
						float pitchMul2 = Mathf.Max(0.01f, pitchMul * num12);
						PlayLocalHitAt(player, safeHitPoint, volumeMul, pitchMul2);
					}
				}
			}
			else
			{
				if (!DamageWorldObjects.Value)
				{
					continue;
				}
				Vector3 hitPoint = val;
				if (TryDamageWorldObject(val5, player, val, forward, cosHalfAngle, ref losChecks, num15, num7, nearPoint, out hitPoint))
				{
					num14++;
					if (num14 == 1)
					{
						pos = hitPoint;
					}
					if (PlayHitSfxPerTarget.Value)
					{
						float volumeMul2 = Mathf.Max(0f, num9 * volMul * num11);
						float pitchMul3 = Mathf.Max(0.01f, pitchMul * num12);
						PlayLocalHitAt(player, hitPoint, volumeMul2, pitchMul3);
					}
				}
			}
		}
		if (!PlayHitSfxPerTarget.Value)
		{
			if (num14 > 0)
			{
				float num21 = 0f;
				if (num14 > 1)
				{
					float num22 = MultiHitBonusMin.Value;
					float num23 = MultiHitBonusMax.Value;
					if (num22 > num23)
					{
						float num24 = num22;
						num22 = num23;
						num23 = num24;
					}
					num21 = Random.Range(num22, num23);
				}
				float volumeMul3 = Mathf.Max(0f, (num9 + num21) * volMul * num11);
				float pitchMul4 = Mathf.Max(0.01f, pitchMul * num12);
				PlayLocalHitAt(player, pos, volumeMul3, pitchMul4);
			}
			else
			{
				Vector3 pos2 = ((Component)player).transform.position + ((Component)player).transform.forward * 0.6f + Vector3.up * 1f;
				float volumeMul4 = Mathf.Max(0f, num10 * volMul * num11);
				float pitchMul5 = Mathf.Max(0.01f, 1.02f * pitchMul * num12);
				PlayLocalMissAt(player, pos2, volumeMul4, pitchMul5);
			}
		}
		if (DebugLog.Value)
		{
			((BaseUnityPlugin)this).Logger.LogInfo((object)string.Format("[{0}] Bash: shieldBase={1:0.0}, sf={2:0.00}, rand={3:0.00}, char={4:0.0}, world={5:0.0}, hits={6}, LoS={7}/{8}, overlap={9}", "ShieldBash", num, blockingSkillFactor, num5, num6, num7, num14, losChecks, num15, num13));
		}
	}

	private bool TryDamageWorldObject(Collider col, Player player, Vector3 origin, Vector3 forward, float cosHalf, ref int losChecks, int maxLos, float worldDamage, Vector3 nearPoint, out Vector3 hitPoint)
	{
		//IL_0003: Unknown result type (might be due to invalid IL or missing references)
		//IL_0004: Unknown result type (might be due to invalid IL or missing references)
		//IL_011a: Unknown result type (might be due to invalid IL or missing references)
		//IL_011f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0123: Unknown result type (might be due to invalid IL or missing references)
		//IL_0128: Unknown result type (might be due to invalid IL or missing references)
		//IL_012a: Unknown result type (might be due to invalid IL or missing references)
		//IL_012c: Unknown result type (might be due to invalid IL or missing references)
		//IL_012d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0132: Unknown result type (might be due to invalid IL or missing references)
		//IL_0155: Unknown result type (might be due to invalid IL or missing references)
		//IL_0159: Unknown result type (might be due to invalid IL or missing references)
		//IL_015e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0160: Unknown result type (might be due to invalid IL or missing references)
		//IL_0162: Unknown result type (might be due to invalid IL or missing references)
		//IL_0306: Unknown result type (might be due to invalid IL or missing references)
		//IL_0308: Unknown result type (might be due to invalid IL or missing references)
		//IL_030a: Unknown result type (might be due to invalid IL or missing references)
		//IL_030f: Unknown result type (might be due to invalid IL or missing references)
		//IL_01c3: Unknown result type (might be due to invalid IL or missing references)
		//IL_01c9: Unknown result type (might be due to invalid IL or missing references)
		//IL_01ca: Unknown result type (might be due to invalid IL or missing references)
		//IL_0362: Unknown result type (might be due to invalid IL or missing references)
		//IL_0369: Expected O, but got Unknown
		//IL_036c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0371: Unknown result type (might be due to invalid IL or missing references)
		//IL_037a: Unknown result type (might be due to invalid IL or missing references)
		//IL_037f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0386: Unknown result type (might be due to invalid IL or missing references)
		//IL_0388: Unknown result type (might be due to invalid IL or missing references)
		hitPoint = origin;
		if ((Object)(object)col == (Object)null)
		{
			return false;
		}
		if ((Object)(object)player == (Object)null)
		{
			return false;
		}
		TreeBase componentInParent = ((Component)col).GetComponentInParent<TreeBase>();
		TreeLog componentInParent2 = ((Component)col).GetComponentInParent<TreeLog>();
		MineRock componentInParent3 = ((Component)col).GetComponentInParent<MineRock>();
		MineRock5 componentInParent4 = ((Component)col).GetComponentInParent<MineRock5>();
		Destructible componentInParent5 = ((Component)col).GetComponentInParent<Destructible>();
		WearNTear componentInParent6 = ((Component)col).GetComponentInParent<WearNTear>();
		Component val = null;
		if ((Object)(object)componentInParent != (Object)null)
		{
			val = (Component)(object)componentInParent;
		}
		else if ((Object)(object)componentInParent2 != (Object)null)
		{
			val = (Component)(object)componentInParent2;
		}
		else if ((Object)(object)componentInParent3 != (Object)null)
		{
			val = (Component)(object)componentInParent3;
		}
		else if ((Object)(object)componentInParent4 != (Object)null)
		{
			val = (Component)(object)componentInParent4;
		}
		else if ((Object)(object)componentInParent5 != (Object)null)
		{
			val = (Component)(object)componentInParent5;
		}
		else if ((Object)(object)componentInParent6 != (Object)null)
		{
			val = (Component)(object)componentInParent6;
		}
		if ((Object)(object)val == (Object)null)
		{
			return false;
		}
		if (!HitOnceTryAdd(((Object)val.gameObject).GetInstanceID()))
		{
			return false;
		}
		Bounds bounds = col.bounds;
		Vector3 center = ((Bounds)(ref bounds)).center;
		Vector3 val2 = center - origin;
		float magnitude = ((Vector3)(ref val2)).magnitude;
		if (magnitude < 0.001f)
		{
			return false;
		}
		Vector3 val3 = val2 / magnitude;
		if (Vector3.Dot(forward, val3) < cosHalf)
		{
			return false;
		}
		if (LineOfSightCheck.Value && maxLos > 0 && losChecks < maxLos)
		{
			losChecks++;
			int worldLosMask = GetWorldLosMask();
			RaycastHit val4 = default(RaycastHit);
			if (Physics.Raycast(origin, val3, ref val4, magnitude, worldLosMask, (QueryTriggerInteraction)1))
			{
				Component val5 = null;
				if ((Object)(object)((RaycastHit)(ref val4)).collider != (Object)null)
				{
					TreeBase componentInParent7 = ((Component)((RaycastHit)(ref val4)).collider).GetComponentInParent<TreeBase>();
					if ((Object)(object)componentInParent7 != (Object)null)
					{
						val5 = (Component)(object)componentInParent7;
					}
					else
					{
						TreeLog componentInParent8 = ((Component)((RaycastHit)(ref val4)).collider).GetComponentInParent<TreeLog>();
						if ((Object)(object)componentInParent8 != (Object)null)
						{
							val5 = (Component)(object)componentInParent8;
						}
						else
						{
							MineRock componentInParent9 = ((Component)((RaycastHit)(ref val4)).collider).GetComponentInParent<MineRock>();
							if ((Object)(object)componentInParent9 != (Object)null)
							{
								val5 = (Component)(object)componentInParent9;
							}
							else
							{
								MineRock5 componentInParent10 = ((Component)((RaycastHit)(ref val4)).collider).GetComponentInParent<MineRock5>();
								if ((Object)(object)componentInParent10 != (Object)null)
								{
									val5 = (Component)(object)componentInParent10;
								}
								else
								{
									Destructible componentInParent11 = ((Component)((RaycastHit)(ref val4)).collider).GetComponentInParent<Destructible>();
									if ((Object)(object)componentInParent11 != (Object)null)
									{
										val5 = (Component)(object)componentInParent11;
									}
									else
									{
										WearNTear componentInParent12 = ((Component)((RaycastHit)(ref val4)).collider).GetComponentInParent<WearNTear>();
										if ((Object)(object)componentInParent12 != (Object)null)
										{
											val5 = (Component)(object)componentInParent12;
										}
									}
								}
							}
						}
					}
				}
				if (val5 != val)
				{
					return false;
				}
			}
		}
		hitPoint = GetSafeHitPoint(col, nearPoint, center);
		bool flag = false;
		if ((Object)(object)componentInParent != (Object)null)
		{
			flag = true;
		}
		if ((Object)(object)componentInParent2 != (Object)null)
		{
			flag = true;
		}
		bool flag2 = false;
		if ((Object)(object)componentInParent3 != (Object)null)
		{
			flag2 = true;
		}
		if ((Object)(object)componentInParent4 != (Object)null)
		{
			flag2 = true;
		}
		HitData val6 = new HitData();
		val6.m_attacker = ((Character)player).GetZDOID();
		val6.m_point = hitPoint;
		val6.m_dir = val3;
		val6.m_pushForce = 0f;
		float num = Mathf.Max(0f, worldDamage);
		if (flag)
		{
			val6.m_damage.m_chop = num;
		}
		else if (flag2)
		{
			val6.m_damage.m_pickaxe = num;
		}
		else
		{
			val6.m_damage.m_blunt = num;
		}
		if ((Object)(object)componentInParent != (Object)null)
		{
			componentInParent.Damage(val6);
		}
		else if ((Object)(object)componentInParent2 != (Object)null)
		{
			componentInParent2.Damage(val6);
		}
		else if ((Object)(object)componentInParent3 != (Object)null)
		{
			componentInParent3.Damage(val6);
		}
		else if ((Object)(object)componentInParent4 != (Object)null)
		{
			componentInParent4.Damage(val6);
		}
		else if ((Object)(object)componentInParent5 != (Object)null)
		{
			componentInParent5.Damage(val6);
		}
		else
		{
			if (!((Object)(object)componentInParent6 != (Object)null))
			{
				return false;
			}
			componentInParent6.Damage(val6);
		}
		return true;
	}

	private void GetMaterialMix(ItemData shield, out float volMul, out float pitchMul)
	{
		volMul = 1f;
		pitchMul = 1f;
		string text = "";
		text = ((shield == null) ? "" : ((shield.m_shared == null) ? "" : ((shield.m_shared.m_name != null) ? shield.m_shared.m_name : "")));
		string text2 = text.ToLowerInvariant();
		bool flag = text2.Contains("iron") || text2.Contains("blackmetal") || text2.Contains("silver") || text2.Contains("bronze") || text2.Contains("metal");
		bool flag2 = false;
		if (!flag)
		{
			flag2 = text2.Contains("wood") || text2.Contains("tower");
		}
		if (flag)
		{
			volMul *= Mathf.Max(0.01f, MetalVolumeMul.Value);
			pitchMul *= Mathf.Max(0.01f, MetalPitchMul.Value);
		}
		else if (flag2)
		{
			volMul *= Mathf.Max(0.01f, WoodVolumeMul.Value);
			pitchMul *= Mathf.Max(0.01f, WoodPitchMul.Value);
		}
	}

	private AudioSource GetOrCreateLocalSfxSource(Player player)
	{
		//IL_00cb: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d1: Expected O, but got Unknown
		if ((Object)(object)player == (Object)null)
		{
			return null;
		}
		if ((Object)(object)_localSfxSource != (Object)null && (Object)(object)((Component)_localSfxSource).gameObject != (Object)null)
		{
			Transform transform = ((Component)_localSfxSource).transform;
			if ((Object)(object)transform != (Object)null && transform.IsChildOf(((Component)player).transform))
			{
				return _localSfxSource;
			}
		}
		try
		{
			if ((Object)(object)_localSfxSource != (Object)null && (Object)(object)((Component)_localSfxSource).gameObject != (Object)null)
			{
				Object.Destroy((Object)(object)((Component)_localSfxSource).gameObject);
			}
		}
		catch
		{
		}
		GameObject val = new GameObject("ShieldBash_LocalSFX_Source");
		val.transform.SetParent(((Component)player).transform, false);
		AudioSource val2 = val.AddComponent<AudioSource>();
		val2.spatialBlend = 1f;
		val2.rolloffMode = (AudioRolloffMode)0;
		val2.minDistance = 1f;
		val2.maxDistance = 35f;
		val2.playOnAwake = false;
		val2.loop = false;
		val2.dopplerLevel = 0f;
		_localSfxSource = val2;
		return _localSfxSource;
	}

	private void PlayLocalHitAt(Player player, Vector3 pos, float volumeMul, float pitchMul)
	{
		//IL_0009: Unknown result type (might be due to invalid IL or missing references)
		PlayLocalAt(player, _hitClip, pos, volumeMul, pitchMul);
	}

	private void PlayLocalMissAt(Player player, Vector3 pos, float volumeMul, float pitchMul)
	{
		//IL_0009: Unknown result type (might be due to invalid IL or missing references)
		PlayLocalAt(player, _missClip, pos, volumeMul, pitchMul);
	}

	private void PlayLocalAt(Player player, AudioClip clip, Vector3 pos, float volumeMul, float pitchMul)
	{
		//IL_003b: Unknown result type (might be due to invalid IL or missing references)
		if (!((Object)(object)player == (Object)null) && !((Object)(object)clip == (Object)null))
		{
			AudioSource orCreateLocalSfxSource = GetOrCreateLocalSfxSource(player);
			if (!((Object)(object)orCreateLocalSfxSource == (Object)null))
			{
				((Component)orCreateLocalSfxSource).transform.position = pos;
				orCreateLocalSfxSource.pitch = Mathf.Clamp(pitchMul, 0.5f, 2f);
				float num = Mathf.Clamp01(volumeMul) * Mathf.Clamp(LocalClipVolumeMul.Value, 0f, 3f);
				orCreateLocalSfxSource.PlayOneShot(clip, num);
			}
		}
	}

	private bool LoadAssetsFromBundle()
	{
		string text = null;
		try
		{
			text = Path.GetDirectoryName(((BaseUnityPlugin)this).Info.Location);
		}
		catch
		{
			text = null;
		}
		string text2 = Path.Combine(Paths.PluginPath, "ShieldBash", "Assets", "shieldbashbundle");
		string text3 = null;
		if (!string.IsNullOrEmpty(text))
		{
			text3 = Path.Combine(text, "Assets", "shieldbashbundle");
		}
		string text4 = text2 + ".bundle";
		string text5 = null;
		if (text3 != null)
		{
			text5 = text3 + ".bundle";
		}
		string text6 = null;
		if (File.Exists(text2))
		{
			text6 = text2;
		}
		else if (text3 != null && File.Exists(text3))
		{
			text6 = text3;
		}
		else if (File.Exists(text4))
		{
			text6 = text4;
		}
		else if (text5 != null && File.Exists(text5))
		{
			text6 = text5;
		}
		if (text6 == null && !string.IsNullOrEmpty(text) && Directory.Exists(text))
		{
			try
			{
				string[] files = Directory.GetFiles(text, "shieldbashbundle*", SearchOption.AllDirectories);
				if (files != null && files.Length != 0)
				{
					text6 = files[0];
				}
			}
			catch
			{
				text6 = null;
			}
		}
		((BaseUnityPlugin)this).Logger.LogInfo((object)"[ShieldBash] Bundle search:");
		((BaseUnityPlugin)this).Logger.LogInfo((object)(" - expected: " + text2));
		if (text3 != null)
		{
			((BaseUnityPlugin)this).Logger.LogInfo((object)(" - nearDll: " + text3));
		}
		((BaseUnityPlugin)this).Logger.LogInfo((object)(" - chosen: " + (text6 ?? "null")));
		if (text6 == null)
		{
			((BaseUnityPlugin)this).Logger.LogError((object)"[ShieldBash] AssetBundle not found (searched multiple locations).");
			return false;
		}
		if (!File.Exists(text6))
		{
			((BaseUnityPlugin)this).Logger.LogError((object)"[ShieldBash] AssetBundle not found (searched multiple locations).");
			return false;
		}
		AssetBundle val = AssetBundle.LoadFromFile(text6);
		if ((Object)(object)val == (Object)null)
		{
			((BaseUnityPlugin)this).Logger.LogError((object)"[ShieldBash] Failed to load AssetBundle (null). Wrong Unity version or corrupted file.");
			return false;
		}
		try
		{
			_bashClip = val.LoadAsset<AnimationClip>("AttackShield01");
			if ((Object)(object)_bashClip == (Object)null)
			{
				AnimationClip[] array = val.LoadAllAssets<AnimationClip>();
				if (array != null && array.Length != 0)
				{
					foreach (AnimationClip val2 in array)
					{
						if ((Object)(object)val2 != (Object)null && ((Object)val2).name == "AttackShield01")
						{
							_bashClip = val2;
							break;
						}
					}
					if ((Object)(object)_bashClip == (Object)null)
					{
						_bashClip = array[0];
					}
					((BaseUnityPlugin)this).Logger.LogInfo((object)("[ShieldBash] Loaded embedded clip: " + (((Object)(object)_bashClip != (Object)null) ? ((Object)_bashClip).name : "null")));
				}
			}
			if ((Object)(object)_bashClip == (Object)null)
			{
				((BaseUnityPlugin)this).Logger.LogError((object)"[ShieldBash] No AnimationClip found in bundle.");
				((BaseUnityPlugin)this).Logger.LogError((object)("[ShieldBash] Assets inside bundle:\n - " + string.Join("\n - ", val.GetAllAssetNames())));
				return false;
			}
			_hitClip = null;
			_missClip = null;
			string text7 = (HitClipName.Value ?? "").Trim();
			string text8 = (MissClipName.Value ?? "").Trim();
			AudioClip[] array2 = val.LoadAllAssets<AudioClip>();
			if (array2 != null)
			{
				foreach (AudioClip val3 in array2)
				{
					if (!((Object)(object)val3 == (Object)null))
					{
						if ((Object)(object)_hitClip == (Object)null && ((Object)val3).name.Equals(text7, StringComparison.OrdinalIgnoreCase))
						{
							_hitClip = val3;
						}
						else if ((Object)(object)_missClip == (Object)null && ((Object)val3).name.Equals(text8, StringComparison.OrdinalIgnoreCase))
						{
							_missClip = val3;
						}
					}
				}
			}
			if ((Object)(object)_hitClip == (Object)null)
			{
				((BaseUnityPlugin)this).Logger.LogWarning((object)("[ShieldBash] HIT clip not found. Expected AudioClip name: '" + text7 + "'"));
			}
			if ((Object)(object)_missClip == (Object)null)
			{
				((BaseUnityPlugin)this).Logger.LogWarning((object)("[ShieldBash] MISS clip not found. Expected AudioClip name: '" + text8 + "'"));
			}
			return true;
		}
		finally
		{
			val.Unload(false);
		}
	}

	private Animator GetAnimator(Character character)
	{
		try
		{
			return CharacterAnimator.Invoke(character);
		}
		catch
		{
			((BaseUnityPlugin)this).Logger.LogError((object)"[ShieldBash] Cannot access field 'm_animator' on Character.");
			return null;
		}
	}

	private ItemData GetLeftItem(Humanoid humanoid)
	{
		try
		{
			return HumanoidLeftItem.Invoke(humanoid);
		}
		catch
		{
			((BaseUnityPlugin)this).Logger.LogError((object)"[ShieldBash] Cannot access field 'm_leftItem' on Humanoid.");
			return null;
		}
	}

	private bool HasShieldInLeftHand(Player player)
	{
		//IL_0003: Unknown result type (might be due to invalid IL or missing references)
		//IL_000d: Expected O, but got Unknown
		//IL_0033: Unknown result type (might be due to invalid IL or missing references)
		//IL_0039: Invalid comparison between Unknown and I4
		ItemData leftItem = GetLeftItem((Humanoid)player);
		if (leftItem == null)
		{
			return false;
		}
		if (leftItem.m_shared == null)
		{
			return false;
		}
		return (int)leftItem.m_shared.m_itemType == 5;
	}

	private static void EnsureLocalizationReflection()
	{
		if (_locRefReady)
		{
			return;
		}
		_locRefReady = true;
		try
		{
			_locType = AccessTools.TypeByName("Localization");
			if (!(_locType == null))
			{
				_locInstanceProp = _locType.GetProperty("instance", BindingFlags.Static | BindingFlags.Public);
				_locGetSelectedLanguage = _locType.GetMethod("GetSelectedLanguage", BindingFlags.Instance | BindingFlags.Public);
			}
		}
		catch
		{
			_locType = null;
			_locInstanceProp = null;
			_locGetSelectedLanguage = null;
		}
	}

	private static string GetGameLanguage()
	{
		EnsureLocalizationReflection();
		if (_locType == null)
		{
			return null;
		}
		if (_locInstanceProp == null)
		{
			return null;
		}
		if (_locGetSelectedLanguage == null)
		{
			return null;
		}
		object obj = null;
		try
		{
			obj = _locInstanceProp.GetValue(null, null);
		}
		catch
		{
			return null;
		}
		if (obj == null)
		{
			return null;
		}
		try
		{
			return _locGetSelectedLanguage.Invoke(obj, null) as string;
		}
		catch
		{
			return null;
		}
	}

	private static bool IsRussianUi()
	{
		string gameLanguage = GetGameLanguage();
		if (string.IsNullOrEmpty(gameLanguage))
		{
			return false;
		}
		gameLanguage = gameLanguage.ToLowerInvariant();
		if (gameLanguage.Contains("russian"))
		{
			return true;
		}
		if (gameLanguage.StartsWith("ru"))
		{
			return true;
		}
		return false;
	}

	internal string BuildTooltipLineForShield(ItemData item)
	{
		//IL_0032: Unknown result type (might be due to invalid IL or missing references)
		//IL_0038: Invalid comparison between Unknown and I4
		if (item == null)
		{
			return null;
		}
		if (item.m_shared == null)
		{
			return null;
		}
		if ((int)item.m_shared.m_itemType != 5)
		{
			return null;
		}
		float blockingSkillFactor = GetBlockingSkillFactor(Player.m_localPlayer);
		float baseDamage = ComputeShieldBaseDamage(item);
		float num = DamageRandomMin.Value;
		float num2 = DamageRandomMax.Value;
		if (num > num2)
		{
			float num3 = num;
			num = num2;
			num2 = num3;
		}
		float num4 = ApplySkillAndRandom(baseDamage, blockingSkillFactor, num);
		float num5 = ApplySkillAndRandom(baseDamage, blockingSkillFactor, num2);
		float num6 = Mathf.Clamp(CenterHitBonusMax.Value, 0f, 1f);
		if (IsRussianUi())
		{
			if (num6 > 0.0001f)
			{
				return $"\nУдар щитом: {num4:0}–{num5:0} (дробящий), центр +{num6 * 100f:0}%\n";
			}
			return $"\nУдар щитом: {num4:0}–{num5:0} (дробящий)\n";
		}
		if (num6 > 0.0001f)
		{
			return $"\nShield Bash: {num4:0}–{num5:0} (blunt), center +{num6 * 100f:0}%\n";
		}
		return $"\nShield Bash: {num4:0}–{num5:0} (blunt)\n";
	}
}