Decompiled source of MarkYourGear v1.1.0

BepInEx/plugins/MarkYourGear/MarkYourGear.dll

Decompiled 3 days ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Text;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using Unity.Collections;
using UnityEngine;
using UnityEngine.Rendering;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyFileVersion("0.4.7.0")]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyVersion("0.4.7.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace MarkYourGear
{
	internal static class CapeReference
	{
		internal static Mesh MeshOf(Renderer renderer)
		{
			if (!Object.op_Implicit((Object)(object)renderer))
			{
				return null;
			}
			SkinnedMeshRenderer val = (SkinnedMeshRenderer)(object)((renderer is SkinnedMeshRenderer) ? renderer : null);
			if (Object.op_Implicit((Object)(object)val))
			{
				return val.sharedMesh;
			}
			MeshFilter component = ((Component)renderer).GetComponent<MeshFilter>();
			if (!Object.op_Implicit((Object)(object)component))
			{
				return null;
			}
			return component.sharedMesh;
		}

		internal static string SourceName(string name)
		{
			if (name == null || !name.EndsWith("(Clone)", StringComparison.Ordinal))
			{
				return name;
			}
			return name.Substring(0, name.Length - "(Clone)".Length);
		}

		internal static Renderer Resolve(Renderer live, List<GameObject> attachments, GameObject prefab)
		{
			if (!Object.op_Implicit((Object)(object)prefab))
			{
				throw new Exception("Original cape item prefab is unavailable.");
			}
			Transform val = null;
			if (attachments != null)
			{
				foreach (GameObject attachment in attachments)
				{
					if (Object.op_Implicit((Object)(object)attachment) && ((Object)(object)((Component)live).transform == (Object)(object)attachment.transform || ((Component)live).transform.IsChildOf(attachment.transform)))
					{
						val = attachment.transform;
						break;
					}
				}
			}
			if (!Object.op_Implicit((Object)(object)val))
			{
				throw new Exception("Cape renderer is outside its attachment hierarchy.");
			}
			Transform val2 = null;
			string text = SourceName(((Object)val).name);
			for (int i = 0; i < prefab.transform.childCount; i++)
			{
				Transform child = prefab.transform.GetChild(i);
				if (!(((Object)child).name != text))
				{
					if (Object.op_Implicit((Object)(object)val2))
					{
						throw new Exception("Ambiguous original cape attachment: " + text);
					}
					val2 = child;
				}
			}
			if (!Object.op_Implicit((Object)(object)val2))
			{
				throw new Exception("Original cape attachment not found: " + text);
			}
			List<Transform> list = new List<Transform>();
			Transform val3 = ((Component)live).transform;
			while ((Object)(object)val3 != (Object)(object)val)
			{
				list.Add(val3);
				val3 = val3.parent;
			}
			for (int num = list.Count - 1; num >= 0; num--)
			{
				Transform val4 = list[num];
				string name = ((Object)val4).name;
				int num2 = 0;
				for (int j = 0; j < val4.parent.childCount; j++)
				{
					Transform child2 = val4.parent.GetChild(j);
					if ((Object)(object)child2 == (Object)(object)val4)
					{
						break;
					}
					if (((Object)child2).name == name)
					{
						num2++;
					}
				}
				Transform val5 = null;
				for (int k = 0; k < val2.childCount; k++)
				{
					Transform child3 = val2.GetChild(k);
					if (((Object)child3).name == name && num2-- == 0)
					{
						val5 = child3;
						break;
					}
				}
				if (!Object.op_Implicit((Object)(object)val5))
				{
					throw new Exception("Original cape renderer path not found: " + name);
				}
				val2 = val5;
			}
			int num3 = 0;
			Renderer[] components = ((Component)live).GetComponents<Renderer>();
			foreach (Renderer val6 in components)
			{
				if ((Object)(object)val6 == (Object)(object)live)
				{
					break;
				}
				if (((object)val6).GetType() == ((object)live).GetType())
				{
					num3++;
				}
			}
			Renderer val7 = null;
			components = ((Component)val2).GetComponents<Renderer>();
			foreach (Renderer val8 in components)
			{
				if (((object)val8).GetType() == ((object)live).GetType() && num3-- == 0)
				{
					val7 = val8;
					break;
				}
			}
			Mesh val9 = MeshOf(live);
			Mesh val10 = MeshOf(val7);
			if (!Object.op_Implicit((Object)(object)val9) || !Object.op_Implicit((Object)(object)val10) || val9.vertexCount != val10.vertexCount || val9.subMeshCount != val10.subMeshCount)
			{
				throw new Exception("Original cape geometry does not match the equipped renderer: " + ((Object)live).name);
			}
			return val7;
		}
	}
	internal static class ChestGeometry
	{
		internal static List<CapeSurface> FindAll(VisEquipment equipment, MarkData data, bool front = false)
		{
			List<string> list = new List<string>();
			List<CapeSurface> list2 = new List<CapeSurface>();
			try
			{
				CapeSurface.Find(Gear.ChestAttachments(equipment), equipment, data, list, front, list2);
				object? value = Gear.Body.GetValue(equipment);
				SkinnedMeshRenderer val = (SkinnedMeshRenderer)((value is SkinnedMeshRenderer) ? value : null);
				int num = (int)Gear.ChestHash.GetValue(equipment);
				GameObject val2 = (Object.op_Implicit((Object)(object)ObjectDB.instance) ? ObjectDB.instance.GetItemPrefab(num) : null);
				Material val3 = (Object.op_Implicit((Object)(object)val2) ? val2.GetComponent<ItemDrop>() : null)?.m_itemData?.m_shared?.m_armorMaterial;
				if (!Object.op_Implicit((Object)(object)val) || !Object.op_Implicit((Object)(object)val3) || !val3.HasProperty("_ChestTex") || !Object.op_Implicit((Object)(object)val3.GetTexture("_ChestTex")))
				{
					if (list2.Count > 0)
					{
						return list2;
					}
					throw new Exception("No printable chest texture. " + string.Join("; ", list));
				}
				Material[] sharedMaterials = ((Renderer)val).sharedMaterials;
				for (int i = 0; i < sharedMaterials.Length; i++)
				{
					if (!Object.op_Implicit((Object)(object)sharedMaterials[i]) || !sharedMaterials[i].HasProperty("_ChestTex"))
					{
						continue;
					}
					CapeSurface capeSurface = null;
					try
					{
						capeSurface = new CapeSurface((Renderer)(object)val, i, equipment, "_ChestTex", front);
						if (capeSurface.Probe(data, envelope: true))
						{
							list2.Add(capeSurface);
							continue;
						}
						throw new Exception("No usable chest texture");
					}
					catch (Exception ex)
					{
						capeSurface?.Dispose();
						list.Add(((Object)val).name + "[" + i + "]: " + ex.Message);
					}
				}
				if (list2.Count > 0)
				{
					return list2;
				}
				throw new Exception("No visible chest stamp surface. " + string.Join("; ", list));
			}
			catch
			{
				foreach (CapeSurface item in list2)
				{
					item.Dispose();
				}
				throw;
			}
		}

		internal static bool TryNeutral(Renderer renderer, VisEquipment equipment, out Matrix4x4 toPlayer, out Transform[] bones, out Vector3[] anchors)
		{
			//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_0105: 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)
			//IL_0201: Unknown result type (might be due to invalid IL or missing references)
			//IL_020c: 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_0216: Unknown result type (might be due to invalid IL or missing references)
			//IL_0219: 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_021d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0222: Unknown result type (might be due to invalid IL or missing references)
			//IL_0248: Unknown result type (might be due to invalid IL or missing references)
			//IL_024d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0251: Unknown result type (might be due to invalid IL or missing references)
			//IL_0256: 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_0260: Unknown result type (might be due to invalid IL or missing references)
			//IL_0143: 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_0150: 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_01a9: 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_01b5: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c5: 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)
			toPlayer = Matrix4x4.identity;
			bones = null;
			anchors = null;
			SkinnedMeshRenderer val = (SkinnedMeshRenderer)(object)((renderer is SkinnedMeshRenderer) ? renderer : null);
			object? value = Gear.Body.GetValue(equipment);
			SkinnedMeshRenderer val2 = (SkinnedMeshRenderer)((value is SkinnedMeshRenderer) ? value : null);
			if (!Object.op_Implicit((Object)(object)val2) || !Object.op_Implicit((Object)(object)val2.sharedMesh) || (Object.op_Implicit((Object)(object)val) && !Object.op_Implicit((Object)(object)val.sharedMesh)))
			{
				return false;
			}
			Matrix4x4[] array = (Matrix4x4[])(Object.op_Implicit((Object)(object)val) ? ((Array)val.sharedMesh.bindposes) : ((Array)new Matrix4x4[0]));
			Transform[] array2 = (Transform[])(Object.op_Implicit((Object)(object)val) ? ((Array)val.bones) : ((Array)new Transform[0]));
			Matrix4x4[] bindposes = val2.sharedMesh.bindposes;
			bones = val2.bones;
			if (bindposes.Length != bones.Length || array.Length != array2.Length)
			{
				return false;
			}
			string[] array3 = new string[bones.Length];
			for (int i = 0; i < bones.Length; i++)
			{
				array3[i] = (Object.op_Implicit((Object)(object)bones[i]) ? ((Object)bones[i]).name : "");
			}
			if (!ChestSkeleton.Resolve(array3, out var _, out var _, out var _, out var _))
			{
				return false;
			}
			Matrix4x4 val3 = Matrix4x4.identity;
			bool flag = (Object)(object)val == (Object)(object)val2;
			for (int j = 0; j < array2.Length; j++)
			{
				if (flag)
				{
					break;
				}
				for (int k = 0; k < bones.Length; k++)
				{
					if (Object.op_Implicit((Object)(object)array2[j]) && (Object)(object)array2[j] == (Object)(object)bones[k])
					{
						val3 = ((Matrix4x4)(ref bindposes[k])).inverse * array[j];
						flag = true;
						break;
					}
				}
			}
			if (!Object.op_Implicit((Object)(object)val))
			{
				Transform val4 = ((Component)renderer).transform;
				while (Object.op_Implicit((Object)(object)val4) && !flag)
				{
					for (int l = 0; l < bones.Length; l++)
					{
						if ((Object)(object)val4 == (Object)(object)bones[l])
						{
							val3 = ((Matrix4x4)(ref bindposes[l])).inverse * val4.worldToLocalMatrix * ((Component)renderer).transform.localToWorldMatrix;
							flag = true;
							break;
						}
					}
					val4 = val4.parent;
				}
			}
			if (!flag)
			{
				return false;
			}
			Matrix4x4 val5 = ((Component)equipment).transform.worldToLocalMatrix * ((Component)val2).transform.localToWorldMatrix;
			toPlayer = val5 * val3;
			anchors = (Vector3[])(object)new Vector3[bones.Length];
			for (int m = 0; m < bones.Length; m++)
			{
				Vector3[] obj = anchors;
				int num = m;
				Matrix4x4 inverse = ((Matrix4x4)(ref bindposes[m])).inverse;
				obj[num] = ((Matrix4x4)(ref val5)).MultiplyPoint3x4(((Matrix4x4)(ref inverse)).MultiplyPoint3x4(Vector3.zero));
			}
			return true;
		}

		internal unsafe static void Build(Renderer renderer, Mesh mesh, Vector3[] vertices, ref int[] triangles, VisEquipment equipment, bool baked, out Vector2[] projected, out float width, out float height, bool front = false)
		{
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ac: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ba: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c5: 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_00ce: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d7: Unknown result type (might be due to invalid IL or missing references)
			//IL_0100: Unknown result type (might be due to invalid IL or missing references)
			//IL_011c: Unknown result type (might be due to invalid IL or missing references)
			//IL_011e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0120: Unknown result type (might be due to invalid IL or missing references)
			//IL_0122: 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_012b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0130: Unknown result type (might be due to invalid IL or missing references)
			//IL_0135: Unknown result type (might be due to invalid IL or missing references)
			//IL_0139: 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_010a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0112: Unknown result type (might be due to invalid IL or missing references)
			//IL_0117: Unknown result type (might be due to invalid IL or missing references)
			//IL_0165: Unknown result type (might be due to invalid IL or missing references)
			//IL_0167: Unknown result type (might be due to invalid IL or missing references)
			//IL_0169: Unknown result type (might be due to invalid IL or missing references)
			//IL_016e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0172: Unknown result type (might be due to invalid IL or missing references)
			//IL_0177: Unknown result type (might be due to invalid IL or missing references)
			//IL_0179: Unknown result type (might be due to invalid IL or missing references)
			//IL_017b: Unknown result type (might be due to invalid IL or missing references)
			//IL_014e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0150: 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_015a: 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_0163: Unknown result type (might be due to invalid IL or missing references)
			//IL_018c: Unknown result type (might be due to invalid IL or missing references)
			//IL_018e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0193: Unknown result type (might be due to invalid IL or missing references)
			//IL_0195: Unknown result type (might be due to invalid IL or missing references)
			//IL_0197: Unknown result type (might be due to invalid IL or missing references)
			//IL_019c: 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_01c0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c5: 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_0217: Unknown result type (might be due to invalid IL or missing references)
			//IL_021c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0221: Unknown result type (might be due to invalid IL or missing references)
			//IL_022a: Unknown result type (might be due to invalid IL or missing references)
			//IL_022f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0231: Unknown result type (might be due to invalid IL or missing references)
			//IL_0236: Unknown result type (might be due to invalid IL or missing references)
			//IL_0238: Unknown result type (might be due to invalid IL or missing references)
			//IL_023a: Unknown result type (might be due to invalid IL or missing references)
			//IL_029e: 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_02a7: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ac: Unknown result type (might be due to invalid IL or missing references)
			//IL_0262: Unknown result type (might be due to invalid IL or missing references)
			//IL_0264: Unknown result type (might be due to invalid IL or missing references)
			//IL_026f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0274: Unknown result type (might be due to invalid IL or missing references)
			//IL_02d3: Unknown result type (might be due to invalid IL or missing references)
			//IL_02dc: Unknown result type (might be due to invalid IL or missing references)
			//IL_02e1: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ea: Unknown result type (might be due to invalid IL or missing references)
			//IL_02f3: Unknown result type (might be due to invalid IL or missing references)
			//IL_02f8: Unknown result type (might be due to invalid IL or missing references)
			//IL_02fd: Unknown result type (might be due to invalid IL or missing references)
			//IL_0302: Unknown result type (might be due to invalid IL or missing references)
			//IL_033d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0342: Unknown result type (might be due to invalid IL or missing references)
			//IL_0313: Unknown result type (might be due to invalid IL or missing references)
			//IL_031c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0321: Unknown result type (might be due to invalid IL or missing references)
			//IL_032a: Unknown result type (might be due to invalid IL or missing references)
			//IL_032f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0334: Unknown result type (might be due to invalid IL or missing references)
			//IL_0339: Unknown result type (might be due to invalid IL or missing references)
			//IL_0431: Unknown result type (might be due to invalid IL or missing references)
			//IL_0436: Unknown result type (might be due to invalid IL or missing references)
			object? value = Gear.Body.GetValue(equipment);
			if (!Object.op_Implicit((Object)((value is SkinnedMeshRenderer) ? value : null)))
			{
				throw new Exception("Chest stamp needs a humanoid body model.");
			}
			Transform[] bones = null;
			Vector3[] anchors = null;
			Matrix4x4 toPlayer = Matrix4x4.identity;
			if (baked || !TryNeutral(renderer, equipment, out toPlayer, out bones, out anchors))
			{
				throw new Exception("Chest mesh has no compatible neutral bind pose; refusing animation-dependent stamp placement.");
			}
			string[] array = new string[bones.Length];
			for (int i = 0; i < bones.Length; i++)
			{
				array[i] = (Object.op_Implicit((Object)(object)bones[i]) ? ((Object)bones[i]).name : "");
			}
			if (!ChestSkeleton.Resolve(array, out var hips, out var neck, out var left, out var right))
			{
				throw new Exception("Chest stamp could not identify the character torso bones.");
			}
			Vector3 val = anchors[hips];
			Vector3 val2 = anchors[neck];
			Vector3 val3 = val2 - val;
			Vector3 normalized = ((Vector3)(ref val3)).normalized;
			val3 = val2 - val;
			height = ((Vector3)(ref val3)).magnitude;
			if (height < 0.001f)
			{
				throw new Exception("Chest stamp torso anchors overlap.");
			}
			Vector3 val4 = ((left >= 0 && right >= 0) ? (anchors[right] - anchors[left]) : Vector3.right);
			val3 = val4 - normalized * Vector3.Dot(val4, normalized);
			Vector3 val5 = ((Vector3)(ref val3)).normalized;
			if (((Vector3)(ref val5)).sqrMagnitude < 0.5f)
			{
				val3 = Vector3.Cross(normalized, Vector3.forward);
				val5 = ((Vector3)(ref val3)).normalized;
			}
			val3 = Vector3.Cross(val5, normalized);
			Vector3 val6 = ((Vector3)(ref val3)).normalized;
			if (Vector3.Dot(val6, Vector3.forward) < 0f)
			{
				val5 = -val5;
				val6 = -val6;
			}
			width = ((left >= 0 && right >= 0) ? Mathf.Abs(Vector3.Dot(anchors[right] - anchors[left], val5)) : (height * 0.85f));
			width = Mathf.Clamp(width, height * 0.45f, height * 1.3f);
			projected = (Vector2[])(object)new Vector2[vertices.Length];
			Vector3[] array2 = (Vector3[])(object)new Vector3[vertices.Length];
			for (int j = 0; j < vertices.Length; j++)
			{
				array2[j] = ((Matrix4x4)(ref toPlayer)).MultiplyPoint3x4(vertices[j]);
				Vector3 val7 = array2[j] - val;
				float num = Vector3.Dot(val7, val5) / width + 0.5f;
				projected[j] = new Vector2(front ? (1f - num) : num, Vector3.Dot(val7, normalized) / height);
			}
			List<int> list = new List<int>();
			float num2 = 0f;
			Vector3[] normals = mesh.normals;
			Matrix4x4 inverse = ((Matrix4x4)(ref toPlayer)).inverse;
			Matrix4x4 transpose = ((Matrix4x4)(ref inverse)).transpose;
			for (int k = 0; k + 2 < triangles.Length; k += 3)
			{
				int num3 = triangles[k];
				int num4 = triangles[k + 1];
				int num5 = triangles[k + 2];
				Vector3 val8 = Vector3.Cross(array2[num4] - array2[num3], array2[num5] - array2[num3]);
				if (normals.Length == vertices.Length)
				{
					val8 = ((Matrix4x4)(ref transpose)).MultiplyVector(normals[num3] + normals[num4] + normals[num5]);
				}
				if (ChestRegion.Facing(Vector3.Dot(((Vector3)(ref val8)).normalized, val6), front))
				{
					float num6 = ChestRegion.ClippedArea(projected[num3].x, projected[num3].y, projected[num4].x, projected[num4].y, projected[num5].x, projected[num5].y);
					if (!(num6 < 1E-06f))
					{
						list.Add(num3);
						list.Add(num4);
						list.Add(num5);
						num2 += num6 * width * height;
					}
				}
			}
			if (list.Count < 3 || num2 < width * height * 0.001f)
			{
				string[] obj = new string[9] { "No usable torso surface on this mesh (scale=", null, null, null, null, null, null, null, null };
				val3 = ((Component)renderer).transform.lossyScale;
				obj[1] = ((object)(*(Vector3*)(&val3))/*cast due to .constrained prefix*/).ToString();
				obj[2] = ", vertices=";
				obj[3] = vertices.Length.ToString();
				obj[4] = ", retained=";
				obj[5] = (list.Count / 3).ToString();
				obj[6] = ", clippedArea=";
				obj[7] = num2.ToString();
				obj[8] = ").";
				throw new Exception(string.Concat(obj));
			}
			triangles = list.ToArray();
		}
	}
	internal sealed class ChestMonitor : MonoBehaviour
	{
		private VisEquipment equipment;

		private Player player;

		private ZNetView view;

		private ChestMarks surface;

		private bool hadBack;

		private bool hadFront;

		private List<GameObject> lastObjects;

		private SkinnedMeshRenderer lastBody;

		private Mesh lastMesh;

		private int lastHash;

		private int lastAttachments;

		private float next;

		private string failed = "";

		private void Awake()
		{
			equipment = ((Component)this).GetComponent<VisEquipment>();
			player = ((Component)this).GetComponent<Player>();
			view = ((Component)this).GetComponent<ZNetView>();
		}

		private static bool SupportedHash(int hash)
		{
			if (hash == 0 || !Object.op_Implicit((Object)(object)ObjectDB.instance))
			{
				return false;
			}
			GameObject itemPrefab = ObjectDB.instance.GetItemPrefab(hash);
			ItemDrop val = (Object.op_Implicit((Object)(object)itemPrefab) ? itemPrefab.GetComponent<ItemDrop>() : null);
			if (Object.op_Implicit((Object)(object)val))
			{
				return Gear.IsChest(val.m_itemData);
			}
			return false;
		}

		private void LateUpdate()
		{
			if (Time.unscaledTime < next)
			{
				return;
			}
			next = Time.unscaledTime + 0.25f;
			try
			{
				if (!Object.op_Implicit((Object)(object)equipment))
				{
					return;
				}
				if ((Object)(object)player == (Object)(object)Player.m_localPlayer)
				{
					Gear.Sync(player);
				}
				int num = (int)Gear.ChestHash.GetValue(equipment);
				string text = "";
				string text2 = "";
				if ((!Object.op_Implicit((Object)(object)view) || !view.IsValid() || view.IsOwner()) && Object.op_Implicit((Object)(object)player))
				{
					ItemData val = Gear.Equipped(player, chest: true);
					if (Object.op_Implicit((Object)(object)val?.m_dropPrefab) && StringExtensionMethods.GetStableHashCode(((Object)val.m_dropPrefab).name) == num)
					{
						text = Gear.Read(val);
						text2 = Gear.Read(val, front: true);
					}
				}
				else if (Object.op_Implicit((Object)(object)view) && view.IsValid())
				{
					ZDO zDO = view.GetZDO();
					int num2 = zDO.GetInt("MYG.ChestItem", 0);
					if (num2 == num && SupportedHash(num2))
					{
						text = zDO.GetString("MYG.Chest", "");
						text2 = zDO.GetString("MYG.ChestFront", "");
					}
				}
				MarkData data;
				bool flag = MarkData.TryParse(text, out data);
				MarkData data2;
				bool flag2 = MarkData.TryParse(text2, out data2);
				if (!flag && !flag2)
				{
					Clear();
					failed = "";
					return;
				}
				List<GameObject> list = Gear.ChestAttachments(equipment);
				object? value = Gear.Body.GetValue(equipment);
				SkinnedMeshRenderer val2 = (SkinnedMeshRenderer)((value is SkinnedMeshRenderer) ? value : null);
				Mesh val3 = (Object.op_Implicit((Object)(object)val2) ? val2.sharedMesh : null);
				int num3 = Gear.AttachmentSignature(list);
				if (surface == null || !surface.Valid || hadBack != flag || hadFront != flag2 || num != lastHash || num3 != lastAttachments || list != lastObjects || (Object)(object)val2 != (Object)(object)lastBody || (Object)(object)val3 != (Object)(object)lastMesh)
				{
					Clear();
					lastHash = num;
					lastAttachments = num3;
					lastObjects = list;
					lastBody = val2;
					lastMesh = val3;
					surface = ChestMarks.Create(equipment, data, data2);
					hadBack = flag;
					hadFront = flag2;
				}
				if (surface != null && surface.Apply(data, data2))
				{
					return;
				}
				throw new Exception("No printable chest armor surface found.");
			}
			catch (Exception ex)
			{
				Clear();
				if (failed != ex.Message)
				{
					failed = ex.Message;
					Plugin.Warn("Chest emblem: " + ex.Message);
				}
				next = Time.unscaledTime + 3f;
			}
		}

		private void Clear()
		{
			surface?.Dispose();
			surface = null;
			lastObjects = null;
			lastBody = null;
			lastMesh = null;
			lastHash = 0;
		}

		private void OnDestroy()
		{
			Clear();
		}

		private void OnDisable()
		{
			Clear();
		}
	}
	internal sealed class ChestMarks : IDisposable
	{
		private static readonly HashSet<ChestMarks> active = new HashSet<ChestMarks>();

		private readonly List<ChestStampSurface> back = new List<ChestStampSurface>();

		private readonly List<ChestStampSurface> front = new List<ChestStampSurface>();

		private readonly Dictionary<ChestStampSurface, bool> captured = new Dictionary<ChestStampSurface, bool>();

		private VisEquipment equipment;

		private bool preview;

		private bool capturing;

		internal bool Valid
		{
			get
			{
				foreach (ChestStampSurface item in back)
				{
					if (!item.Valid)
					{
						return false;
					}
				}
				foreach (ChestStampSurface item2 in front)
				{
					if (!item2.Valid)
					{
						return false;
					}
				}
				return true;
			}
		}

		internal static ChestMarks Create(VisEquipment eq, MarkData backData, MarkData frontData, bool preview = false)
		{
			ChestMarks chestMarks = new ChestMarks
			{
				equipment = eq,
				preview = preview
			};
			try
			{
				if (backData != null)
				{
					chestMarks.back.AddRange(ChestStampSurface.FindAll(eq, front: false));
				}
				if (frontData != null)
				{
					chestMarks.front.AddRange(ChestStampSurface.FindAll(eq, front: true));
				}
				active.Add(chestMarks);
				return chestMarks;
			}
			catch
			{
				chestMarks.Dispose();
				throw;
			}
		}

		internal void Capture()
		{
			if (!preview || capturing)
			{
				return;
			}
			capturing = true;
			captured.Clear();
			foreach (ChestMarks item in active)
			{
				if (item == this || !((Object)(object)item.equipment == (Object)(object)equipment))
				{
					continue;
				}
				foreach (ChestStampSurface item2 in item.back)
				{
					captured[item2] = item2.Visible;
					item2.Visible = false;
				}
				foreach (ChestStampSurface item3 in item.front)
				{
					captured[item3] = item3.Visible;
					item3.Visible = false;
				}
			}
		}

		internal void Restore()
		{
			if (!preview)
			{
				return;
			}
			foreach (ChestStampSurface item in back)
			{
				item.Visible = false;
			}
			foreach (ChestStampSurface item2 in front)
			{
				item2.Visible = false;
			}
			foreach (KeyValuePair<ChestStampSurface, bool> item3 in captured)
			{
				item3.Key.Visible = item3.Value;
			}
			captured.Clear();
			capturing = false;
		}

		private static bool ApplySide(List<ChestStampSurface> surfaces, MarkData data)
		{
			bool flag = false;
			foreach (ChestStampSurface surface in surfaces)
			{
				if (data == null)
				{
					surface.Visible = false;
				}
				else if (surface.Apply(data))
				{
					flag = true;
				}
			}
			return data == null || flag;
		}

		internal bool Apply(MarkData backData, MarkData frontData)
		{
			bool num = ApplySide(back, backData);
			bool flag = ApplySide(front, frontData);
			return num && flag;
		}

		internal void ReleasePreview()
		{
			Dispose();
		}

		public void Dispose()
		{
			Restore();
			active.Remove(this);
			foreach (ChestStampSurface item in back)
			{
				item.Dispose();
			}
			foreach (ChestStampSurface item2 in front)
			{
				item2.Dispose();
			}
			back.Clear();
			front.Clear();
		}
	}
	internal static class ChestRegion
	{
		private readonly struct Point
		{
			internal readonly float X;

			internal readonly float Y;

			internal Point(float x, float y)
			{
				X = x;
				Y = y;
			}
		}

		internal static bool Contains(float x, float y)
		{
			if (x >= 0.08f && x <= 0.92f && y >= 0.25f)
			{
				return y <= 0.96f;
			}
			return false;
		}

		internal static bool Facing(float normalZ, bool front)
		{
			if (!front)
			{
				return normalZ < -0.25f;
			}
			return normalZ > 0.25f;
		}

		internal static bool Accept(float x, float y, float normalZ, bool front = false)
		{
			if (Contains(x, y))
			{
				return Facing(normalZ, front);
			}
			return false;
		}

		internal static float ClippedArea(float ax, float ay, float bx, float by, float cx, float cy)
		{
			List<Point> list = new List<Point>
			{
				new Point(ax, ay),
				new Point(bx, by),
				new Point(cx, cy)
			};
			for (int i = 0; i < 4; i++)
			{
				if (list.Count <= 0)
				{
					break;
				}
				List<Point> list2 = new List<Point>();
				Point p = list[list.Count - 1];
				float num = Distance(p, i);
				foreach (Point item in list)
				{
					float num2 = Distance(item, i);
					if (num2 >= 0f != num >= 0f)
					{
						float num3 = num / (num - num2);
						list2.Add(new Point(p.X + (item.X - p.X) * num3, p.Y + (item.Y - p.Y) * num3));
					}
					if (num2 >= 0f)
					{
						list2.Add(item);
					}
					p = item;
					num = num2;
				}
				list = list2;
			}
			float num4 = 0f;
			for (int j = 0; j < list.Count; j++)
			{
				Point point = list[j];
				Point point2 = list[(j + 1) % list.Count];
				num4 += point.X * point2.Y - point2.X * point.Y;
			}
			return Math.Abs(num4) * 0.5f;
		}

		private static float Distance(Point p, int edge)
		{
			return edge switch
			{
				2 => p.Y - 0.25f, 
				1 => 0.92f - p.X, 
				0 => p.X - 0.08f, 
				_ => 0.96f - p.Y, 
			};
		}
	}
	internal static class ChestSkeleton
	{
		internal static bool Resolve(string[] names, out int hips, out int neck, out int left, out int right)
		{
			hips = (neck = (left = (right = -1)));
			for (int i = 0; i < names.Length; i++)
			{
				string text = (names[i] ?? "").ToLowerInvariant().Replace("_", "").Replace(" ", "");
				if (text.Contains("hips") || text.Contains("pelvis"))
				{
					hips = i;
				}
				if (text.Contains("neck"))
				{
					neck = i;
				}
				if (text.Contains("upperarm") || text.EndsWith("leftarm") || text.EndsWith("rightarm"))
				{
					if (text.Contains("left") || text.EndsWith(".l"))
					{
						left = i;
					}
					if (text.Contains("right") || text.EndsWith(".r"))
					{
						right = i;
					}
				}
			}
			if (hips >= 0)
			{
				return neck >= 0;
			}
			return false;
		}
	}
	internal static class ChestStampLayout
	{
		internal const int Padding = 2;

		internal static void UV(float x, float y, float width, float height, MarkData mark, out float u, out float v)
		{
			ProjectionMath.EmblemUV(x, y, width, height, mark, out u, out v);
		}

		internal static float Padded(float uv, int size)
		{
			return (uv * (float)size + 2f) / (float)(size + 4);
		}

		internal static bool InsideTorso(float u, float v, float width, float height, MarkData mark)
		{
			return ChestRegion.Contains((u - 0.5f) * mark.Width + 0.5f, (v - 0.5f) * mark.Width * width / height + mark.CenterY);
		}

		internal static bool HasInk(float[] xs, float[] ys, int[] triangles, float width, float height, MarkData mark, byte[] alpha, int sw, int sh)
		{
			int num = 0;
			for (int i = 0; i + 2 < triangles.Length; i += 3)
			{
				int num2 = triangles[i];
				int num3 = triangles[i + 1];
				int num4 = triangles[i + 2];
				UV(xs[num2], ys[num2], width, height, mark, out var u, out var v);
				UV(xs[num3], ys[num3], width, height, mark, out var u2, out var v2);
				UV(xs[num4], ys[num4], width, height, mark, out var u3, out var v3);
				int num5 = Math.Max(0, (int)Math.Floor(Math.Min(u, Math.Min(u2, u3)) * (float)sw));
				int num6 = Math.Max(0, (int)Math.Floor(Math.Min(v, Math.Min(v2, v3)) * (float)sh));
				int num7 = Math.Min(sw - 1, (int)Math.Ceiling(Math.Max(u, Math.Max(u2, u3)) * (float)sw));
				int num8 = Math.Min(sh - 1, (int)Math.Ceiling(Math.Max(v, Math.Max(v2, v3)) * (float)sh));
				for (int j = num6; j <= num8; j++)
				{
					for (int k = num5; k <= num7; k++)
					{
						float num9 = ((float)k + 0.5f) / (float)sw;
						float num10 = ((float)j + 0.5f) / (float)sh;
						if (alpha[j * sw + k] > 12 && InsideTorso(num9, num10, width, height, mark) && ProjectionMath.Barycentric(num9, num10, u, v, u2, v2, u3, v3, out var _, out var _, out var _) && ++num >= 20)
						{
							return true;
						}
					}
				}
			}
			return false;
		}
	}
	internal sealed class ChestStampSurface : IDisposable
	{
		internal static readonly HashSet<Material> InkMaterials = new HashSet<Material>();

		private Renderer source;

		private Renderer overlay;

		private Mesh sourceMesh;

		private Mesh mesh;

		private GameObject holder;

		private Material material;

		private Texture2D texture;

		private ChestStampFollower follower;

		private LODGroup lod;

		private string applied;

		private bool hasInk;

		private Vector2[] projected;

		private float[] xs;

		private float[] ys;

		private int[] triangles;

		private float width;

		private float height;

		internal bool Valid
		{
			get
			{
				if (Object.op_Implicit((Object)(object)source) && Object.op_Implicit((Object)(object)overlay) && Object.op_Implicit((Object)(object)sourceMesh))
				{
					return (Object)(object)CapeReference.MeshOf(source) == (Object)(object)sourceMesh;
				}
				return false;
			}
		}

		internal bool Visible
		{
			get
			{
				if (Object.op_Implicit((Object)(object)follower))
				{
					return follower.Requested;
				}
				return false;
			}
			set
			{
				if (Object.op_Implicit((Object)(object)follower))
				{
					follower.Requested = value;
					follower.Sync();
				}
			}
		}

		internal static List<ChestStampSurface> FindAll(VisEquipment eq, bool front)
		{
			List<ChestStampSurface> list = new List<ChestStampSurface>();
			List<string> list2 = new List<string>();
			HashSet<Renderer> hashSet = new HashSet<Renderer>();
			List<GameObject> list3 = Gear.ChestAttachments(eq);
			if (list3 != null)
			{
				foreach (GameObject item in list3)
				{
					if (!Object.op_Implicit((Object)(object)item))
					{
						continue;
					}
					Renderer[] componentsInChildren = item.GetComponentsInChildren<Renderer>(true);
					foreach (Renderer val in componentsInChildren)
					{
						if (Object.op_Implicit((Object)(object)((Component)val).GetComponent<ChestStampFollower>()) || !hashSet.Add(val))
						{
							continue;
						}
						Material[] sharedMaterials = val.sharedMaterials;
						for (int j = 0; j < sharedMaterials.Length; j++)
						{
							if (Object.op_Implicit((Object)(object)sharedMaterials[j]) && (sharedMaterials[j].HasProperty("_MainTex") || sharedMaterials[j].HasProperty("_BaseMap")))
							{
								TryAdd(list, list2, val, j, eq, front);
							}
						}
					}
				}
			}
			object? value = Gear.Body.GetValue(eq);
			SkinnedMeshRenderer val2 = (SkinnedMeshRenderer)((value is SkinnedMeshRenderer) ? value : null);
			int num = (int)Gear.ChestHash.GetValue(eq);
			GameObject val3 = (Object.op_Implicit((Object)(object)ObjectDB.instance) ? ObjectDB.instance.GetItemPrefab(num) : null);
			Material val4 = (Object.op_Implicit((Object)(object)val3) ? val3.GetComponent<ItemDrop>() : null)?.m_itemData?.m_shared?.m_armorMaterial;
			if (Object.op_Implicit((Object)(object)val2) && Object.op_Implicit((Object)(object)val4) && val4.HasProperty("_ChestTex") && Object.op_Implicit((Object)(object)val4.GetTexture("_ChestTex")))
			{
				Material[] sharedMaterials2 = ((Renderer)val2).sharedMaterials;
				for (int k = 0; k < sharedMaterials2.Length; k++)
				{
					if (Object.op_Implicit((Object)(object)sharedMaterials2[k]) && sharedMaterials2[k].HasProperty("_ChestTex"))
					{
						TryAdd(list, list2, (Renderer)(object)val2, k, eq, front);
					}
				}
			}
			if (list.Count == 0)
			{
				throw new Exception("No printable chest surface: " + string.Join("; ", list2));
			}
			return list;
		}

		private static void TryAdd(List<ChestStampSurface> result, List<string> failures, Renderer r, int slot, VisEquipment eq, bool front)
		{
			ChestStampSurface chestStampSurface = new ChestStampSurface();
			try
			{
				chestStampSurface.Build(r, slot, eq, front);
				chestStampSurface.overlay.sortingOrder = result.Count;
				result.Add(chestStampSurface);
			}
			catch (Exception ex)
			{
				chestStampSurface.Dispose();
				failures.Add(((Object)r).name + "[" + slot + "]: " + ex.Message);
			}
		}

		private void Build(Renderer r, int slot, VisEquipment eq, bool front)
		{
			//IL_0142: Unknown result type (might be due to invalid IL or missing references)
			//IL_0147: Unknown result type (might be due to invalid IL or missing references)
			//IL_0152: Unknown result type (might be due to invalid IL or missing references)
			//IL_0157: Unknown result type (might be due to invalid IL or missing references)
			//IL_0169: Unknown result type (might be due to invalid IL or missing references)
			//IL_016b: 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_017f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0184: Unknown result type (might be due to invalid IL or missing references)
			//IL_0189: Unknown result type (might be due to invalid IL or missing references)
			//IL_019c: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b1: Expected O, but got Unknown
			//IL_01b8: Unknown result type (might be due to invalid IL or missing references)
			//IL_0213: Unknown result type (might be due to invalid IL or missing references)
			//IL_0218: 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_024d: Unknown result type (might be due to invalid IL or missing references)
			//IL_024f: Unknown result type (might be due to invalid IL or missing references)
			//IL_033c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0341: Unknown result type (might be due to invalid IL or missing references)
			//IL_034c: Unknown result type (might be due to invalid IL or missing references)
			//IL_035c: Expected O, but got Unknown
			//IL_0362: Unknown result type (might be due to invalid IL or missing references)
			//IL_037d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0387: Expected O, but got Unknown
			//IL_0403: Unknown result type (might be due to invalid IL or missing references)
			//IL_040e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0413: Unknown result type (might be due to invalid IL or missing references)
			//IL_0427: Unknown result type (might be due to invalid IL or missing references)
			//IL_042c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0448: Unknown result type (might be due to invalid IL or missing references)
			source = r;
			sourceMesh = CapeReference.MeshOf(r);
			if (!Object.op_Implicit((Object)(object)sourceMesh) || slot >= sourceMesh.subMeshCount)
			{
				throw new Exception("Missing chest mesh/submesh");
			}
			Mesh val = sourceMesh;
			bool flag = false;
			try
			{
				SkinnedMeshRenderer val2 = (SkinnedMeshRenderer)(object)((r is SkinnedMeshRenderer) ? r : null);
				if (!val.isReadable)
				{
					if (!Object.op_Implicit((Object)(object)val2))
					{
						throw new Exception("Unreadable rigid armor mesh");
					}
					val = NeutralMesh.Bake(val2);
					flag = true;
				}
				Vector3[] vertices = val.vertices;
				Vector3[] normals = val.normals;
				triangles = val.GetTriangles(slot);
				ChestGeometry.Build(r, val, vertices, ref triangles, eq, baked: false, out projected, out width, out height, front);
				xs = new float[projected.Length];
				ys = new float[projected.Length];
				for (int i = 0; i < projected.Length; i++)
				{
					xs[i] = projected[i].x;
					ys[i] = projected[i].y;
				}
				if (normals.Length != vertices.Length)
				{
					throw new Exception("Chest mesh has no normals");
				}
				Vector3 val4;
				for (int j = 0; j < vertices.Length; j++)
				{
					Vector3 normalized = ((Vector3)(ref normals[j])).normalized;
					ref Vector3 reference = ref vertices[j];
					Vector3 val3 = reference;
					val4 = ((Component)r).transform.TransformVector(normalized);
					reference = val3 + normalized * (0.004f / Mathf.Max(1E-06f, ((Vector3)(ref val4)).magnitude));
				}
				mesh = new Mesh
				{
					name = "MYG_ChestDecal"
				};
				mesh.indexFormat = val.indexFormat;
				mesh.vertices = vertices;
				mesh.normals = normals;
				mesh.triangles = triangles;
				if (Object.op_Implicit((Object)(object)val2))
				{
					mesh.bindposes = sourceMesh.bindposes;
					NativeArray<BoneWeight1> allBoneWeights = sourceMesh.GetAllBoneWeights();
					NativeArray<byte> bonesPerVertex = sourceMesh.GetBonesPerVertex();
					if (bonesPerVertex.Length != vertices.Length || allBoneWeights.Length == 0)
					{
						throw new Exception("Chest skin has no usable bone weights");
					}
					mesh.SetBoneWeights(bonesPerVertex, allBoneWeights);
					for (int k = 0; k < sourceMesh.blendShapeCount; k++)
					{
						for (int l = 0; l < sourceMesh.GetBlendShapeFrameCount(k); l++)
						{
							Vector3[] array = (Vector3[])(object)new Vector3[vertices.Length];
							Vector3[] array2 = (Vector3[])(object)new Vector3[vertices.Length];
							Vector3[] array3 = (Vector3[])(object)new Vector3[vertices.Length];
							sourceMesh.GetBlendShapeFrameVertices(k, l, array, array2, array3);
							mesh.AddBlendShapeFrame(sourceMesh.GetBlendShapeName(k), sourceMesh.GetBlendShapeFrameWeight(k, l), array, array2, array3);
						}
					}
				}
				Shader val5 = Shader.Find("Legacy Shaders/Transparent/Diffuse");
				if (!Object.op_Implicit((Object)(object)val5) || !val5.isSupported)
				{
					val5 = Shader.Find("Sprites/Default");
				}
				if (!Object.op_Implicit((Object)(object)val5) || !val5.isSupported)
				{
					throw new Exception("Transparent stamp shader unavailable");
				}
				material = new Material(val5)
				{
					name = "MYG_ChestInk",
					renderQueue = 3001
				};
				material.color = Color.white;
				holder = new GameObject(front ? "MYG_ChestFront" : "MYG_ChestBack");
				((Object)holder).hideFlags = (HideFlags)52;
				holder.layer = ((Component)r).gameObject.layer;
				holder.transform.SetParent(((Component)r).transform, false);
				if (Object.op_Implicit((Object)(object)val2))
				{
					SkinnedMeshRenderer val6 = holder.AddComponent<SkinnedMeshRenderer>();
					val6.sharedMesh = mesh;
					val6.bones = val2.bones;
					val6.rootBone = val2.rootBone;
					val6.quality = val2.quality;
					Bounds localBounds = ((Renderer)val2).localBounds;
					val4 = ((Component)r).transform.lossyScale;
					((Bounds)(ref localBounds)).Expand(0.012f / Mathf.Max(1E-06f, ((Vector3)(ref val4)).magnitude / 1.7320508f));
					((Renderer)val6).localBounds = localBounds;
					val6.updateWhenOffscreen = true;
					overlay = (Renderer)(object)val6;
				}
				else
				{
					holder.AddComponent<MeshFilter>().sharedMesh = mesh;
					overlay = (Renderer)(object)holder.AddComponent<MeshRenderer>();
					mesh.RecalculateBounds();
				}
				overlay.sharedMaterial = material;
				Material val7 = material;
				material = overlay.material;
				if ((Object)(object)material != (Object)(object)val7)
				{
					Object.Destroy((Object)(object)val7);
				}
				InkMaterials.Add(material);
				overlay.shadowCastingMode = (ShadowCastingMode)0;
				overlay.receiveShadows = false;
				overlay.forceRenderingOff = true;
				overlay.enabled = r.enabled;
				follower = holder.AddComponent<ChestStampFollower>();
				follower.Source = r;
				follower.Target = overlay;
				lod = ((Component)r).GetComponentInParent<LODGroup>();
				if (!Object.op_Implicit((Object)(object)lod))
				{
					return;
				}
				LOD[] lODs = lod.GetLODs();
				bool flag2 = false;
				for (int m = 0; m < lODs.Length; m++)
				{
					if (Array.IndexOf(lODs[m].renderers, r) >= 0)
					{
						List<Renderer> list = new List<Renderer>(lODs[m].renderers);
						list.Add(overlay);
						lODs[m].renderers = list.ToArray();
						flag2 = true;
					}
				}
				if (flag2)
				{
					lod.SetLODs(lODs);
				}
			}
			finally
			{
				if (flag && Object.op_Implicit((Object)(object)val))
				{
					Object.Destroy((Object)(object)val);
				}
			}
		}

		internal bool Apply(MarkData data)
		{
			//IL_00d4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d9: 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_012f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0134: Unknown result type (might be due to invalid IL or missing references)
			//IL_013f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0146: Unknown result type (might be due to invalid IL or missing references)
			//IL_014d: 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_015a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0229: Unknown result type (might be due to invalid IL or missing references)
			//IL_022e: 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_0240: Unknown result type (might be due to invalid IL or missing references)
			//IL_0247: Unknown result type (might be due to invalid IL or missing references)
			//IL_0253: Expected O, but got Unknown
			//IL_01bd: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c4: Unknown result type (might be due to invalid IL or missing references)
			//IL_01cb: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e5: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ea: Unknown result type (might be due to invalid IL or missing references)
			if (!Valid)
			{
				Visible = false;
				return false;
			}
			string text = data.Encode();
			if (applied != text)
			{
				Assets.PatternAsset patternAsset = Assets.Pattern(data.Pattern);
				hasInk = ChestStampLayout.HasInk(xs, ys, triangles, width, height, data, patternAsset.Alpha, patternAsset.Width, patternAsset.Height);
				if (hasInk)
				{
					Vector2[] array = (Vector2[])(object)new Vector2[projected.Length];
					for (int i = 0; i < array.Length; i++)
					{
						ChestStampLayout.UV(xs[i], ys[i], width, height, data, out var u, out var v);
						array[i] = new Vector2(ChestStampLayout.Padded(u, patternAsset.Width), ChestStampLayout.Padded(v, patternAsset.Height));
					}
					mesh.uv = array;
					int num = patternAsset.Width + 4;
					int num2 = patternAsset.Height + 4;
					Color32[] array2 = (Color32[])(object)new Color32[num * num2];
					Color val = default(Color);
					ColorUtility.TryParseHtmlString("#" + data.ColorHex, ref val);
					Color32 val2 = Color32.op_Implicit(val);
					for (int j = 0; j < array2.Length; j++)
					{
						array2[j] = new Color32(val2.r, val2.g, val2.b, (byte)0);
					}
					for (int k = 0; k < patternAsset.Height; k++)
					{
						for (int l = 0; l < patternAsset.Width; l++)
						{
							if (ChestStampLayout.InsideTorso(((float)l + 0.5f) / (float)patternAsset.Width, ((float)k + 0.5f) / (float)patternAsset.Height, width, height, data))
							{
								array2[(k + 2) * num + l + 2] = new Color32(val2.r, val2.g, val2.b, patternAsset.Alpha[k * patternAsset.Width + l]);
							}
						}
					}
					if (!Object.op_Implicit((Object)(object)texture))
					{
						texture = new Texture2D(num, num2, (TextureFormat)4, true, false)
						{
							name = "MYG_ChestInk",
							wrapMode = (TextureWrapMode)1,
							filterMode = (FilterMode)2,
							anisoLevel = 4
						};
					}
					texture.SetPixels32(array2);
					texture.Apply(true, false);
					material.mainTexture = (Texture)(object)texture;
				}
				applied = text;
			}
			Visible = hasInk;
			return hasInk;
		}

		public void Dispose()
		{
			Visible = false;
			if (Object.op_Implicit((Object)(object)lod) && Object.op_Implicit((Object)(object)overlay))
			{
				LOD[] lODs = lod.GetLODs();
				for (int i = 0; i < lODs.Length; i++)
				{
					List<Renderer> list = new List<Renderer>(lODs[i].renderers);
					list.Remove(overlay);
					lODs[i].renderers = list.ToArray();
				}
				lod.SetLODs(lODs);
			}
			if (Object.op_Implicit((Object)(object)holder))
			{
				holder.SetActive(false);
				Object.Destroy((Object)(object)holder);
			}
			if (Object.op_Implicit((Object)(object)mesh))
			{
				Object.Destroy((Object)(object)mesh);
			}
			if (Object.op_Implicit((Object)(object)material))
			{
				InkMaterials.Remove(material);
				Object.Destroy((Object)(object)material);
			}
			if (Object.op_Implicit((Object)(object)texture))
			{
				Object.Destroy((Object)(object)texture);
			}
			holder = null;
			overlay = null;
			follower = null;
			mesh = null;
			material = null;
			texture = null;
		}
	}
	internal sealed class ChestStampFollower : MonoBehaviour
	{
		internal Renderer Source;

		internal Renderer Target;

		internal bool Requested;

		internal void Sync()
		{
			if (!Object.op_Implicit((Object)(object)Target))
			{
				return;
			}
			bool flag = Object.op_Implicit((Object)(object)Source) && Source.enabled;
			if (Target.enabled != flag)
			{
				Target.enabled = flag;
			}
			bool flag2 = !Requested || !Object.op_Implicit((Object)(object)Source) || Source.forceRenderingOff;
			if (Target.forceRenderingOff != flag2)
			{
				Target.forceRenderingOff = flag2;
			}
			Renderer source = Source;
			SkinnedMeshRenderer val = (SkinnedMeshRenderer)(object)((source is SkinnedMeshRenderer) ? source : null);
			Renderer target = Target;
			SkinnedMeshRenderer val2 = (SkinnedMeshRenderer)(object)((target is SkinnedMeshRenderer) ? target : null);
			if (Object.op_Implicit((Object)(object)val) && Object.op_Implicit((Object)(object)val2) && Object.op_Implicit((Object)(object)val.sharedMesh))
			{
				for (int i = 0; i < val.sharedMesh.blendShapeCount; i++)
				{
					val2.SetBlendShapeWeight(i, val.GetBlendShapeWeight(i));
				}
			}
		}

		private void LateUpdate()
		{
			Sync();
		}
	}
	[HarmonyPatch(typeof(InventoryGui), "UpdateCraftingPanel")]
	internal static class CraftingDiagnostics
	{
		private static string last;

		private static bool warned;

		[HarmonyPriority(0)]
		private static void Postfix(InventoryGui __instance)
		{
			try
			{
				Player localPlayer = Player.m_localPlayer;
				ObjectDB instance = ObjectDB.instance;
				if (!Object.op_Implicit((Object)(object)localPlayer) || !Object.op_Implicit((Object)(object)instance))
				{
					return;
				}
				CraftingStation currentCraftingStation = localPlayer.GetCurrentCraftingStation();
				List<Recipe> list = AccessTools.Field(typeof(InventoryGui), "m_tempRecipes").GetValue(__instance) as List<Recipe>;
				IEnumerable enumerable = AccessTools.Field(typeof(InventoryGui), "m_availableRecipes").GetValue(__instance) as IEnumerable;
				HashSet<Recipe> hashSet = new HashSet<Recipe>();
				if (enumerable != null)
				{
					foreach (object item in enumerable)
					{
						object? value = AccessTools.Property(item.GetType(), "Recipe").GetValue(item, null);
						Recipe val = (Recipe)((value is Recipe) ? value : null);
						if (Object.op_Implicit((Object)(object)val))
						{
							hashSet.Add(val);
						}
					}
				}
				List<string> list2 = AccessTools.Field(typeof(Player), "s_FilterCraft").GetValue(null) as List<string>;
				bool flag = (bool)AccessTools.Method(typeof(InventoryGui), "InCraftTab", (Type[])null, (Type[])null).Invoke(__instance, null);
				StringBuilder stringBuilder = new StringBuilder("[craft.panel] station=").Append(Object.op_Implicit((Object)(object)currentCraftingStation) ? currentCraftingStation.m_name : "none").Append("; tab=").Append(flag ? "Craft" : "Upgrade")
					.Append("; filters=")
					.Append((list2 == null) ? "unknown" : string.Join(",", list2))
					.Append("; displayed=")
					.Append(hashSet.Count);
				string[] array = new string[3] { "RunicStamp", "PaintYourBuild_Paintbrush", "Lesly_WaterproofingBrush" };
				foreach (string text in array)
				{
					bool flag2 = false;
					foreach (Recipe recipe in instance.m_recipes)
					{
						if (Object.op_Implicit((Object)(object)recipe) && Object.op_Implicit((Object)(object)recipe.m_item) && !(((Object)recipe.m_item).name != text))
						{
							flag2 = true;
							SharedData shared = recipe.m_item.m_itemData.m_shared;
							stringBuilder.Append("\n[craft.recipe] ").Append(text).Append("; enabled=")
								.Append(recipe.m_enabled)
								.Append("; known=")
								.Append(localPlayer.IsRecipeKnown(shared.m_name))
								.Append("; station=")
								.Append(Object.op_Implicit((Object)(object)recipe.m_craftingStation) ? recipe.m_craftingStation.m_name : "none")
								.Append("; upgradeOnly=")
								.Append(recipe.m_noCraftOnlyUpgrade)
								.Append("; dlc=")
								.Append(shared.m_dlc)
								.Append("; available=")
								.Append(list?.Contains(recipe) ?? false)
								.Append("; displayed=")
								.Append(hashSet.Contains(recipe))
								.Append("; requirementsMet=")
								.Append(localPlayer.HaveRequirements(recipe, false, 1, 1));
						}
					}
					if (!flag2)
					{
						stringBuilder.Append("\n[craft.recipe] ").Append(text).Append("; recipe absent");
					}
				}
				string text2 = stringBuilder.ToString();
				if (!(text2 == last))
				{
					last = text2;
					Plugin.LogInfo(text2);
				}
			}
			catch (Exception ex)
			{
				if (!warned)
				{
					warned = true;
					Plugin.Warn("Craft diagnostics unavailable: " + ex.Message);
				}
			}
		}
	}
	internal static class DyePreviewCall
	{
		internal static MethodInfo Resolve(Type owner, Type rootType)
		{
			if (owner == null)
			{
				return null;
			}
			return owner.GetMethod("ApplyObject", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic, null, new Type[3]
			{
				rootType,
				typeof(int),
				typeof(bool)
			}, null);
		}

		internal static void Invoke(MethodInfo method, object root, int packed, string parts)
		{
			if (!(method == null))
			{
				object[] parameters = new object[3] { root, packed, true };
				method.Invoke(null, parameters);
			}
		}
	}
	internal sealed class FavouriteInks
	{
		internal const int Limit = 12;

		internal readonly List<string> Colors = new List<string>();

		internal static bool Valid(string hex)
		{
			if (hex == null || hex.Length != 6)
			{
				return false;
			}
			foreach (char c in hex)
			{
				if ((c < '0' || c > '9') && (c < 'a' || c > 'f') && (c < 'A' || c > 'F'))
				{
					return false;
				}
			}
			return true;
		}

		internal void Load(string encoded)
		{
			Colors.Clear();
			string[] array = (encoded ?? "").Split(',');
			for (int i = 0; i < array.Length; i++)
			{
				string text = array[i].Trim().ToUpperInvariant();
				if (Valid(text) && !Colors.Contains(text) && Colors.Count < 12)
				{
					Colors.Add(text);
				}
			}
		}

		internal bool Toggle(string hex)
		{
			if (!Valid(hex))
			{
				return false;
			}
			hex = hex.ToUpperInvariant();
			if (Colors.Remove(hex))
			{
				return true;
			}
			if (Colors.Count >= 12)
			{
				return false;
			}
			Colors.Add(hex);
			return true;
		}

		internal string Encode()
		{
			return string.Join(",", Colors);
		}

		internal string Next(string current)
		{
			if (Colors.Count == 0)
			{
				return current;
			}
			int num = Colors.IndexOf(current);
			return Colors[(num + 1) % Colors.Count];
		}
	}
	internal sealed class InkWheel : IDisposable
	{
		private readonly FavouriteInks favourites = new FavouriteInks();

		private Action<string> saveFavourites;

		private Texture2D wheel;

		private Texture2D brightness;

		private Vector2 cursor;

		private float value;

		private float hue;

		private float repeat;

		private bool draggingWheel;

		private bool draggingValue;

		private bool dirty;

		internal bool Visible { get; private set; }

		internal string Hex { get; private set; }

		internal void LoadFavourites(string encoded, Action<string> save)
		{
			favourites.Load(encoded);
			saveFavourites = save;
		}

		private void ToggleFavourite()
		{
			if (favourites.Toggle(Hex))
			{
				saveFavourites?.Invoke(favourites.Encode());
			}
		}

		private void Choose(string hex)
		{
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_0050: Unknown result type (might be due to invalid IL or missing references)
			//IL_0056: Unknown result type (might be due to invalid IL or missing references)
			//IL_005b: Unknown result type (might be due to invalid IL or missing references)
			Color val = default(Color);
			ColorUtility.TryParseHtmlString("#" + hex, ref val);
			float num = default(float);
			float num2 = default(float);
			Color.RGBToHSV(val, ref num, ref num2, ref value);
			hue = num;
			cursor = new Vector2(Mathf.Cos(num * MathF.PI * 2f), 0f - Mathf.Sin(num * MathF.PI * 2f)) * num2;
			Changed();
		}

		internal void Open(string hex)
		{
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_0057: Unknown result type (might be due to invalid IL or missing references)
			//IL_005d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0062: Unknown result type (might be due to invalid IL or missing references)
			Color val = default(Color);
			ColorUtility.TryParseHtmlString("#" + hex, ref val);
			float num = default(float);
			Color.RGBToHSV(val, ref hue, ref num, ref value);
			cursor = new Vector2(Mathf.Cos(hue * MathF.PI * 2f), 0f - Mathf.Sin(hue * MathF.PI * 2f)) * num;
			Hex = hex;
			Visible = true;
			dirty = false;
			draggingWheel = (draggingValue = false);
			repeat = 0f;
			BuildWheel();
			UpdateGradient();
		}

		internal void Close()
		{
			Visible = false;
			dirty = false;
			draggingWheel = (draggingValue = false);
		}

		private void Components(out float h, out float saturation)
		{
			h = hue;
			saturation = ((Vector2)(ref cursor)).magnitude;
		}

		private void Changed()
		{
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			Components(out var h, out var saturation);
			string text = ColorUtility.ToHtmlStringRGB(Color.HSVToRGB(h, saturation, value));
			if (text != Hex)
			{
				Hex = text;
				dirty = true;
			}
			UpdateGradient();
		}

		internal bool TakePreview(out string hex)
		{
			hex = Hex;
			if (!dirty)
			{
				return false;
			}
			dirty = false;
			return true;
		}

		internal void UpdateInput(float x, float y)
		{
			//IL_007e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0083: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fb: Unknown result type (might be due to invalid IL or missing references)
			//IL_010b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0115: 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_0124: Unknown result type (might be due to invalid IL or missing references)
			//IL_0129: 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_0139: Unknown result type (might be due to invalid IL or missing references)
			//IL_013a: Unknown result type (might be due to invalid IL or missing references)
			if (ZInput.GetButtonDown("JoyButtonX") || Input.GetKeyDown((KeyCode)102))
			{
				ToggleFavourite();
				ZInput.ResetButtonStatus("JoyButtonX");
			}
			if (ZInput.GetButtonDown("JoyButtonY") || Input.GetKeyDown((KeyCode)9))
			{
				Choose(favourites.Next(Hex));
				ZInput.ResetButtonStatus("JoyButtonY");
			}
			Vector2 zero = default(Vector2);
			((Vector2)(ref zero))..ctor(x, y);
			if (Mathf.Abs(x) <= 0.25f && Mathf.Abs(y) <= 0.25f)
			{
				zero = Vector2.zero;
			}
			if (Input.GetKey((KeyCode)276))
			{
				zero.x = -1f;
			}
			if (Input.GetKey((KeyCode)275))
			{
				zero.x = 1f;
			}
			if (Input.GetKey((KeyCode)273))
			{
				zero.y = -1f;
			}
			if (Input.GetKey((KeyCode)274))
			{
				zero.y = 1f;
			}
			if (((Vector2)(ref zero)).sqrMagnitude > 0f)
			{
				Vector2 val = Vector2.ClampMagnitude(cursor + zero * Mathf.Min(Time.unscaledDeltaTime, 0.05f) * 0.9f, 1f);
				if (val != cursor)
				{
					cursor = val;
					if (((Vector2)(ref cursor)).magnitude > 0.001f)
					{
						hue = Mathf.Repeat(Mathf.Atan2(0f - cursor.y, cursor.x) / (MathF.PI * 2f), 1f);
					}
					Changed();
				}
			}
			int num = ((ZInput.GetButton("JoyDPadUp") || Input.GetKey((KeyCode)280)) ? 1 : ((ZInput.GetButton("JoyDPadDown") || Input.GetKey((KeyCode)281)) ? (-1) : 0));
			if (num == 0)
			{
				repeat = 0f;
			}
			else if (Time.unscaledTime >= repeat)
			{
				float num2 = Mathf.Clamp01(value + (float)num * 0.025f);
				if (num2 != value)
				{
					value = num2;
					Changed();
				}
				repeat = Time.unscaledTime + 0.08f;
			}
		}

		internal int Draw(GUIStyle label, GUIStyle small, GUIStyle button)
		{
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			//IL_005c: 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_0138: Unknown result type (might be due to invalid IL or missing references)
			//IL_013e: Invalid comparison between Unknown and I4
			//IL_0180: Unknown result type (might be due to invalid IL or missing references)
			//IL_0186: Invalid comparison between Unknown and I4
			//IL_00bc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cd: 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_01cc: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d6: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e9: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ef: Unknown result type (might be due to invalid IL or missing references)
			//IL_0201: Unknown result type (might be due to invalid IL or missing references)
			//IL_0206: Unknown result type (might be due to invalid IL or missing references)
			//IL_020b: Unknown result type (might be due to invalid IL or missing references)
			//IL_020c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0218: Unknown result type (might be due to invalid IL or missing references)
			//IL_022e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0233: Unknown result type (might be due to invalid IL or missing references)
			//IL_023d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0249: Unknown result type (might be due to invalid IL or missing references)
			//IL_025f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0264: Unknown result type (might be due to invalid IL or missing references)
			//IL_0286: Unknown result type (might be due to invalid IL or missing references)
			//IL_0292: 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_02c8: Unknown result type (might be due to invalid IL or missing references)
			//IL_02fc: Unknown result type (might be due to invalid IL or missing references)
			//IL_0343: Unknown result type (might be due to invalid IL or missing references)
			//IL_0348: Unknown result type (might be due to invalid IL or missing references)
			//IL_0366: Unknown result type (might be due to invalid IL or missing references)
			//IL_036b: 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_03cd: Unknown result type (might be due to invalid IL or missing references)
			//IL_014a: Unknown result type (might be due to invalid IL or missing references)
			//IL_014f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0107: 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_00f3: Unknown result type (might be due to invalid IL or missing references)
			//IL_0167: Unknown result type (might be due to invalid IL or missing references)
			//IL_0171: 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_0129: Unknown result type (might be due to invalid IL or missing references)
			//IL_041f: Unknown result type (might be due to invalid IL or missing references)
			//IL_049d: Unknown result type (might be due to invalid IL or missing references)
			//IL_04c5: Unknown result type (might be due to invalid IL or missing references)
			//IL_04be: Unknown result type (might be due to invalid IL or missing references)
			//IL_05b2: Unknown result type (might be due to invalid IL or missing references)
			//IL_058e: Unknown result type (might be due to invalid IL or missing references)
			//IL_04f3: Unknown result type (might be due to invalid IL or missing references)
			//IL_04f8: Unknown result type (might be due to invalid IL or missing references)
			//IL_04ff: Unknown result type (might be due to invalid IL or missing references)
			//IL_0522: Unknown result type (might be due to invalid IL or missing references)
			//IL_0531: Expected O, but got Unknown
			//IL_05da: Unknown result type (might be due to invalid IL or missing references)
			//IL_0602: Unknown result type (might be due to invalid IL or missing references)
			GUI.Label(new Rect(85f, 164f, 598f, 35f), "INK COLOUR", label);
			GUI.Label(new Rect(112f, 200f, 544f, 30f), "1. Colour: around the wheel", small);
			GUI.Label(new Rect(112f, 231f, 544f, 30f), "2. Colour strength: centre to edge", small);
			Rect val = default(Rect);
			((Rect)(ref val))..ctor(254f, 270f, 260f, 260f);
			Rect val2 = default(Rect);
			((Rect)(ref val2))..ctor(112f, 560f, 544f, 27f);
			Event current = Event.current;
			if ((int)current.type == 0 && current.button == 0)
			{
				Vector2 val3 = current.mousePosition - ((Rect)(ref val)).center;
				if (((Vector2)(ref val3)).magnitude <= ((Rect)(ref val)).width * 0.5f)
				{
					draggingWheel = true;
					SetCursor(current.mousePosition, val);
					current.Use();
				}
				else if (((Rect)(ref val2)).Contains(current.mousePosition))
				{
					draggingValue = true;
					SetValue(current.mousePosition.x, val2);
					current.Use();
				}
			}
			else if ((int)current.type == 3)
			{
				if (draggingWheel)
				{
					SetCursor(current.mousePosition, val);
					current.Use();
				}
				else if (draggingValue)
				{
					SetValue(current.mousePosition.x, val2);
					current.Use();
				}
			}
			else if ((int)current.type == 1 && (draggingWheel || draggingValue))
			{
				draggingWheel = (draggingValue = false);
				current.Use();
			}
			Color color = GUI.color;
			GUI.color = new Color(value, value, value, 1f);
			GUI.DrawTexture(val, (Texture)(object)wheel);
			GUI.color = color;
			Vector2 val4 = ((Rect)(ref val)).center + cursor * (((Rect)(ref val)).width * 0.5f);
			Fill(new Rect(val4.x - 8f, val4.y - 8f, 16f, 16f), Color.black);
			Fill(new Rect(val4.x - 6f, val4.y - 6f, 12f, 12f), Color.white);
			Color color2 = default(Color);
			ColorUtility.TryParseHtmlString("#" + Hex, ref color2);
			Fill(new Rect(val4.x - 4f, val4.y - 4f, 8f, 8f), color2);
			GUI.Label(new Rect(112f, 527f, 440f, 30f), "3. Brightness  " + Mathf.RoundToInt(value * 100f) + "%", small);
			GUI.DrawTexture(val2, (Texture)(object)brightness);
			Fill(new Rect(((Rect)(ref val2)).x + value * ((Rect)(ref val2)).width - 2f, ((Rect)(ref val2)).y - 3f, 4f, ((Rect)(ref val2)).height + 6f), Color.white);
			Fill(new Rect(112f, 597f, 38f, 34f), color2);
			GUI.Label(new Rect(165f, 596f, 220f, 35f), "#" + Hex, label);
			bool flag = favourites.Colors.Contains(Hex);
			if (GUI.Button(new Rect(388f, 594f, 268f, 38f), flag ? "Remove favourite" : ((favourites.Colors.Count >= 12) ? "Favourites full" : "Save favourite"), button))
			{
				ToggleFavourite();
			}
			GUI.Label(new Rect(112f, 638f, 544f, 28f), "FAVOURITE COLOURS  (" + favourites.Colors.Count + "/12)", small);
			Rect val5 = default(Rect);
			Color color3 = default(Color);
			for (int i = 0; i < favourites.Colors.Count; i++)
			{
				((Rect)(ref val5))..ctor((float)(112 + i * 46), 673f, 40f, 32f);
				ColorUtility.TryParseHtmlString("#" + favourites.Colors[i], ref color3);
				Fill(val5, (favourites.Colors[i] == Hex) ? Color.white : Color.black);
				Fill(new Rect(((Rect)(ref val5)).x + 3f, ((Rect)(ref val5)).y + 3f, 34f, 26f), color3);
				if (GUI.Button(val5, new GUIContent("", "#" + favourites.Colors[i]), GUIStyle.none))
				{
					Choose(favourites.Colors[i]);
				}
			}
			if (favourites.Colors.Count == 0)
			{
				GUI.Label(new Rect(112f, 669f, 544f, 34f), "Save a colour to add its swatch here.", small);
			}
			if (GUI.Button(new Rect(85f, 720f, 290f, 45f), "Keep colour", button))
			{
				return 1;
			}
			if (GUI.Button(new Rect(391f, 720f, 292f, 45f), "Revert colour", button))
			{
				return -1;
			}
			GUI.Label(new Rect(85f, 769f, 598f, 38f), "Live preview • Apply stamp saves the colour to gear.", small);
			return 0;
		}

		private void SetCursor(Vector2 mouse, Rect rect)
		{
			//IL_0001: 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_0009: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: 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)
			cursor = Vector2.ClampMagnitude((mouse - ((Rect)(ref rect)).center) / (((Rect)(ref rect)).width * 0.5f), 1f);
			if (((Vector2)(ref cursor)).sqrMagnitude > 1E-06f)
			{
				hue = Mathf.Repeat(Mathf.Atan2(0f - cursor.y, cursor.x) / (MathF.PI * 2f), 1f);
			}
			Changed();
		}

		private void SetValue(float x, Rect bar)
		{
			value = Mathf.Clamp01((x - ((Rect)(ref bar)).x) / ((Rect)(ref bar)).width);
			Changed();
		}

		private static void Fill(Rect rect, Color color)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			Color color2 = GUI.color;
			GUI.color = color;
			GUI.DrawTexture(rect, (Texture)(object)Texture2D.whiteTexture);
			GUI.color = color2;
		}

		private void BuildWheel()
		{
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: Expected O, but got Unknown
			//IL_009d: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a2: 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_00d0: 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)
			if (Object.op_Implicit((Object)(object)wheel))
			{
				return;
			}
			wheel = new Texture2D(256, 256, (TextureFormat)4, false);
			Color32[] array = (Color32[])(object)new Color32[65536];
			for (int i = 0; i < 256; i++)
			{
				for (int j = 0; j < 256; j++)
				{
					float num = ((float)j + 0.5f - 128f) / 128f;
					float num2 = ((float)i + 0.5f - 128f) / 128f;
					float num3 = Mathf.Sqrt(num * num + num2 * num2);
					Color val = Color.HSVToRGB(Mathf.Repeat(Mathf.Atan2(num2, num) / (MathF.PI * 2f), 1f), Mathf.Clamp01(num3), 1f);
					val.a = Mathf.Clamp01((1f - num3) * 256f * 0.5f);
					array[i * 256 + j] = Color32.op_Implicit(val);
				}
			}
			wheel.SetPixels32(array);
			wheel.Apply(false, true);
			((Texture)wheel).filterMode = (FilterMode)1;
			((Texture)wheel).wrapMode = (TextureWrapMode)1;
		}

		private void UpdateGradient()
		{
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Expected O, but got Unknown
			//IL_005d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0062: Unknown result type (might be due to invalid IL or missing references)
			//IL_0067: Unknown result type (might be due to invalid IL or missing references)
			if (!Object.op_Implicit((Object)(object)brightness))
			{
				brightness = new Texture2D(256, 1, (TextureFormat)4, false);
				((Texture)brightness).wrapMode = (TextureWrapMode)1;
				((Texture)brightness).filterMode = (FilterMode)1;
			}
			Components(out var h, out var saturation);
			Color32[] array = (Color32[])(object)new Color32[256];
			for (int i = 0; i < 256; i++)
			{
				array[i] = Color32.op_Implicit(Color.HSVToRGB(h, saturation, (float)i / 255f));
			}
			brightness.SetPixels32(array);
			brightness.Apply(false, false);
		}

		public void Dispose()
		{
			Close();
			if (Object.op_Implicit((Object)(object)wheel))
			{
				Object.Destroy((Object)(object)wheel);
			}
			if (Object.op_Implicit((Object)(object)brightness))
			{
				Object.Destroy((Object)(object)brightness);
			}
			wheel = null;
			brightness = null;
		}
	}
	public sealed class MarkData
	{
		public const string Key = "MarkYourGear.Emblem";

		public const string NetKey = "MYG.Cape";

		public string Pattern = "raven";

		public int Ink;

		public int Size = 1;

		public int Height = 2;

		public string CustomInk;

		public static readonly string[] InkNames = new string[6] { "Ivory", "Raven black", "Old gold", "Crimson", "Sky blue", "Forest green" };

		public static readonly string[] InkHex = new string[6] { "EEE3C7", "171C22", "CFA34D", "A92932", "65B9E7", "4B9564" };

		private static readonly float[] Widths = new float[3] { 0.35f, 0.48f, 0.6f };

		public string ColorHex => CustomInk ?? InkHex[Ink];

		public float Width => Widths[Size];

		public float CenterY => 0.63f + (float)Height * 0.055f;

		public string Encode()
		{
			if (CustomInk != null)
			{
				return "2|" + Pattern + "|" + CustomInk + "|" + Size + "|" + Height;
			}
			return "1|" + Pattern + "|" + Ink + "|" + Size + "|" + Height;
		}

		public MarkData Copy()
		{
			return new MarkData
			{
				Pattern = Pattern,
				Ink = Ink,
				CustomInk = CustomInk,
				Size = Size,
				Height = Height
			};
		}

		public static bool TryParse(string text, out MarkData data)
		{
			data = null;
			if (string.IsNullOrEmpty(text) || text.Length > 64)
			{
				return false;
			}
			string[] array = text.Split('|');
			int result = 0;
			string customInk = null;
			if (array.Length != 5 || PatternCatalog.Find(array[1]) == null || !int.TryParse(array[3], NumberStyles.None, CultureInfo.InvariantCulture, out var result2) || !int.TryParse(array[4], NumberStyles.None, CultureInfo.InvariantCulture, out var result3) || result2 < 0 || result2 > 2 || result3 < 0 || result3 > 4)
			{
				return false;
			}
			if (array[0] == "1")
			{
				if (!int.TryParse(array[2], NumberStyles.None, CultureInfo.InvariantCulture, out result) || result < 0 || result >= InkHex.Length)
				{
					return false;
				}
			}
			else
			{
				if (!(array[0] == "2"))
				{
					return false;
				}
				if (array[2].Length != 6)
				{
					return false;
				}
				string text2 = array[2];
				foreach (char c in text2)
				{
					if ((c < '0' || c > '9') && (c < 'A' || c > 'F') && (c < 'a' || c > 'f'))
					{
						return false;
					}
				}
				customInk = array[2].ToUpperInvariant();
			}
			data = new MarkData
			{
				Pattern = array[1],
				Ink = result,
				CustomInk = customInk,
				Size = result2,
				Height = result3
			};
			return true;
		}
	}
	public static class ProjectionMath
	{
		public static bool Barycentric(float x, float y, float ax, float ay, float bx, float by, float cx, float cy, out float a, out float b, out float c)
		{
			float num = (by - cy) * (ax - cx) + (cx - bx) * (ay - cy);
			a = (b = (c = 0f));
			if (Math.Abs(num) < 1E-09f)
			{
				return false;
			}
			a = ((by - cy) * (x - cx) + (cx - bx) * (y - cy)) / num;
			b = ((cy - ay) * (x - cx) + (ax - cx) * (y - cy)) / num;
			c = 1f - a - b;
			if (a >= -0.0001f && b >= -0.0001f)
			{
				return c >= -0.0001f;
			}
			return false;
		}

		public static bool EmblemUV(float x, float y, float bodyWidth, float bodyHeight, MarkData mark, out float u, out float v)
		{
			float width = mark.Width;
			float num = width * bodyWidth / bodyHeight;
			u = (x - 0.5f) / width + 0.5f;
			v = (y - mark.CenterY) / num + 0.5f;
			if (u >= 0f && u <= 1f && v >= 0f)
			{
				return v <= 1f;
			}
			return false;
		}
	}
	internal static class NeutralMesh
	{
		internal static Mesh Bake(SkinnedMeshRenderer source)
		{
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_0037: Expected O, but got Unknown
			//IL_0056: Unknown result type (might be due to invalid IL or missing references)
			//IL_005b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0062: Unknown result type (might be due to invalid IL or missing references)
			//IL_0081: Unknown result type (might be due to invalid IL or missing references)
			//IL_0086: 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_00a2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ef: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f5: Expected O, but got Unknown
			Mesh sharedMesh = source.sharedMesh;
			Matrix4x4[] bindposes = sharedMesh.bindposes;
			if (bindposes.Length == 0)
			{
				throw new Exception("No bind poses for stable gear projection: " + ((Object)sharedMesh).name);
			}
			GameObject val = null;
			Mesh val2 = null;
			try
			{
				val = new GameObject("MYG_NeutralBake");
				((Object)val).hideFlags = (HideFlags)61;
				Transform[] array = (Transform[])(object)new Transform[bindposes.Length];
				for (int i = 0; i < bindposes.Length; i++)
				{
					Matrix4x4 inverse = ((Matrix4x4)(ref bindposes[i])).inverse;
					Transform transform = new GameObject("bone").transform;
					transform.SetParent(val.transform, false);
					transform.localPosition = Vector4.op_Implicit(((Matrix4x4)(ref inverse)).GetColumn(3));
					transform.localRotation = ((Matrix4x4)(ref inverse)).rotation;
					transform.localScale = ((Matrix4x4)(ref inverse)).lossyScale;
					array[i] = transform;
				}
				SkinnedMeshRenderer obj = val.AddComponent<SkinnedMeshRenderer>();
				((Renderer)obj).enabled = false;
				obj.sharedMesh = sharedMesh;
				obj.bones = array;
				obj.rootBone = val.transform;
				obj.quality = (SkinQuality)4;
				val2 = new Mesh();
				obj.BakeMesh(val2);
				if (val2.vertexCount != sharedMesh.vertexCount)
				{
					throw new Exception("Neutral gear bake returned incomplete geometry: " + ((Object)sharedMesh).name);
				}
				return val2;
			}
			catch
			{
				if (Object.op_Implicit((Object)(object)val2))
				{
					Object.Destroy((Object)(object)val2);
				}
				throw;
			}
			finally
			{
				if (Object.op_Implicit((Object)(object)val))
				{
					val.SetActive(false);
					Object.Destroy((Object)(object)val);
				}
			}
		}
	}
	public sealed class PatternInfo
	{
		public readonly string Id;

		public readonly string Name;

		public readonly string Resource;

		public readonly int Category;

		public PatternInfo(string id, string name, int category, string resource = null)
		{
			Id = id;
			Name = name;
			Category = category;
			Resource = resource ?? ("Patterns." + id);
		}
	}
	public static class PatternCatalog
	{
		public static readonly string[] Categories = new string[6] { "Beasts", "Viking symbols", "Nature", "Nordic patterns", "Dark designs", "Clan marks" };

		public static readonly PatternInfo[] Patterns = new PatternInfo[60]
		{
			new PatternInfo("raven_crest", "Raven", 0, "Patterns.raven"),
			new PatternInfo("stag", "Stag", 0),
			new PatternInfo("wolf", "Wolf", 0),
			new PatternInfo("bear", "Bear", 0),
			new PatternInfo("boar", "Boar", 0),
			new PatternInfo("serpent", "Serpent", 0),
			new PatternInfo("dragon", "Dragon", 0),
			new PatternInfo("eagle", "Eagle", 0),
			new PatternInfo("fox", "Fox", 0),
			new PatternInfo("owl", "Owl", 0),
			new PatternInfo("longship", "Longship", 1),
			new PatternInfo("crossed_axes", "Crossed Axes", 1),
			new PatternInfo("round_shield", "Round Shield", 1),
			new PatternInfo("hammer", "Hammer", 1),
			new PatternInfo("horn", "Horn", 1),
			new PatternInfo("flaming_sword", "Flaming Sword", 1),
			new PatternInfo("spear", "Spear", 1),
			new PatternInfo("anchor", "Anchor", 1),
			new PatternInfo("helmet", "Helmet", 1),
			new PatternInfo("oath_ring", "Oath Ring", 1),
			new PatternInfo("world_tree", "World Tree", 2),
			new PatternInfo("oak_leaf", "Oak Leaf", 2),
			new PatternInfo("mountain", "Mountain", 2),
			new PatternInfo("sun", "Sun", 2),
			new PatternInfo("crescent_moon", "Crescent Moon", 2),
			new PatternInfo("snowflake", "Snowflake", 2),
			new PatternInfo("pine", "Pine", 2),
			new PatternInfo("ocean_wave", "Ocean Wave", 2),
			new PatternInfo("thistle", "Thistle", 2),
			new PatternInfo("lightning", "Lightning", 2),
			new PatternInfo("knotwork_circle", "Knotwork Circle", 3),
			new PatternInfo("interwoven_beasts", "Interwoven Beasts", 3),
			new PatternInfo("winged_crest", "Winged Crest", 3),
			new PatternInfo("angular_border", "Angular Border", 3),
			new PatternInfo("braided_diamond", "Braided Diamond", 3),
			new PatternInfo("serpent_knot", "Serpent Knot", 3),
			new PatternInfo("woven_cross", "Woven Cross", 3),
			new PatternInfo("triple_spiral", "Triple Spiral", 3),
			new PatternInfo("endless_knot", "Endless Knot", 3),
			new PatternInfo("woven_star", "Woven Star", 3),
			new PatternInfo("skull", "Skull", 4),
			new PatternInfo("skeletal_raven", "Skeletal Raven", 4),
			new PatternInfo("serpent_ring", "Serpent Ring", 4),
			new PatternInfo("claw_marks", "Claw Marks", 4),
			new PatternInfo("bat", "Bat", 4),
			new PatternInfo("spider", "Spider", 4),
			new PatternInfo("broken_antlers", "Broken Antlers", 4),
			new PatternInfo("hooded_wraith", "Hooded Wraith", 4),
			new PatternInfo("bone_blades", "Bone Blades", 4),
			new PatternInfo("thorn_heart", "Thorn Heart", 4),
			new PatternInfo("crown", "Crown", 5),
			new PatternInfo("broken_shield", "Broken Shield", 5),
			new PatternInfo("wolf_pack", "Wolf Pack", 5),
			new PatternInfo("antwerp_mongols", "Antwerp Mongols", 5),
			new PatternInfo("raven_banner", "Raven Banner", 5),
			new PatternInfo("stag_guard", "Stag Guard", 5),
			new PatternInfo("mountain_fort", "Mountain Fort", 5),
			new PatternInfo("twin_bears", "Twin Bears", 5),
			new PatternInfo("sea_raiders", "Sea Raiders", 5),
			new PatternInfo("flame_watch", "Flame Watch", 5)
		};

		private static readonly PatternInfo LegacyRaven = new PatternInfo("raven", "Raven (classic)", 0, "raven");

		public static PatternInfo Find(string id)
		{
			if (id == "raven")
			{
				return LegacyRaven;
			}
			PatternInfo[] patterns = Patterns;
			foreach (PatternInfo patternInfo in patterns)
			{
				if (patternInfo.Id == id)
				{
					return patternInfo;
				}
			}
			return null;
		}

		public static PatternInfo At(int category, int index)
		{
			return Patterns[category * 10 + (index % 10 + 10) % 10];
		}

		public static int Index(string id)
		{
			for (int i = 0; i < Patterns.Length; i++)
			{
				if (Patterns[i].Id == id)
				{
					return i % 10;
				}
			}
			return -1;
		}
	}
	[BepInPlugin("valheim.markyourgear", "Mark Your Gear", "0.4.7")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	public sealed class Plugin : BaseUnityPlugin
	{
		public const string Id = "valheim.markyourgear";

		public const string Version = "0.4.7";

		internal static Plugin Instance;

		private readonly InkWheel inkWheel = new InkWheel();

		private MarkData beforeInk;

		private bool beforeInkVisible;

		private Harmony harmony;

		private bool front;

		private bool open;

		private bool pad;

		private bool oldCursor;

		private bool oldRequest;

		private CursorLockMode oldLock;

		private int releaseFrame = -1;

		private int selected;

		private int row;

		private int direction;

		private int category;

		private float armedAt;

		private float repeat;

		private Vector3 lastMouse;

		private ItemData stampItem;

		private List<ItemData> capes = new List<ItemData>();

		private MarkData draft = new MarkData();

		private bool showMark = true;

		private string message = "";

		private CapePreview preview = new CapePreview();

		private GUIStyle title;

		private GUIStyle label;

		private GUIStyle small;

		private GUIStyle button;

		private GUIStyle selectedButton;

		private GUIStyle help;

		private Texture2D panel;

		private Texture2D accent;

		internal bool IsOpen => open;

		internal static bool Blocks
		{
			get
			{
				if (Object.op_Implicit((Object)(object)Instance))
				{
					if (!Instance.open)
					{
						return Time.frameCount <= Instance.releaseFrame;
					}
					return true;
				}
				return false;
			}
		}

		internal static void LogInfo(string text)
		{
			if (Object.op_Implicit((Object)(object)Instance))
			{
				((BaseUnityPlugin)Instance).Logger.LogInfo((object)text);
			}
		}

		internal static void Warn(string text)
		{
			if (Object.op_Implicit((Object)(object)Instance))
			{
				((BaseUnityPlugin)Instance).Logger.LogWarning((object)text);
			}
		}

		private void Awake()
		{
			//IL_0065: Unknown result type (might be due to invalid IL or missing references)
			//IL_006f: Expected O, but got Unknown
			Instance = this;
			ConfigEntry<string> favourites = ((BaseUnityPlugin)this).Config.Bind<string>("Ink", "FavouriteColours", "", "Saved ink colours as comma-separated RGB hex codes (up to 12).");
			inkWheel.LoadFavourites(favourites.Value, delegate(string value)
			{
				favourites.Value = value;
				((BaseUnityPlugin)this).Config.Save();
			});
			Assets.Load();
			harmony = new Harmony("valheim.markyourgear");
			harmony.PatchAll(typeof(Plugin).Assembly);
			DyeBridge.Install(harmony);
			((BaseUnityPlugin)this).Logger.LogInfo((object)"Mark Your Gear 0.4.7 loaded. 60 stamps in 6 categories; isolated game-frame-rate preview; capes and chest armor; Dye Your Gear compatibility enabled.");
		}

		private void OnDestroy()
		{
			Close();
			inkWheel.Dispose();
			Harmony obj = harmony;
			if (obj != null)
			{
				obj.UnpatchSelf();
			}
			CapeMonitor[] array = Object.FindObjectsByType<CapeMonitor>((FindObjectsSortMode)0);
			for (int i = 0; i < array.Length; i++)
			{
				Object.Destroy((Object)(object)array[i]);
			}
			ChestMonitor[] array2 = Object.FindObjectsByType<ChestMonitor>((FindObjectsSortMode)0);
			for (int i = 0; i < array2.Length; i++)
			{
				Object.Destroy((Object)(object)array2[i]);
			}
			Assets.Dispose();
			Stamp.Dispose();
			if (Object.op_Implicit((Object)(object)panel))
			{
				Object.Destroy((Object)(object)panel);
			}
			if (Object.op_Implicit((Object)(object)accent))
			{
				Object.Destroy((Object)(object)accent);
			}
			Instance = null;
		}

		private void OnDisable()
		{
			Close();
		}

		internal void Open(ItemData tool)
		{
			//IL_00ba: 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_00de: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e3: Unknown result type (might be due to invalid IL or missing references)
			Player localPlayer = Player.m_localPlayer;
			if (!Object.op_Implicit((Object)(object)localPlayer) || open)
			{
				return;
			}
			stampItem = tool;
			capes.Clear();
			foreach (ItemData allItem in ((Humanoid)localPlayer).GetInventory().GetAllItems())
			{
				if (Gear.Supported(allItem))
				{
					capes.Add(allItem);
				}
			}
			selected = Mathf.Clamp(selected, 0, Mathf.Max(0, capes.Count - 1));
			row = 0;
			message = "";
			LoadDraft();
			oldCursor = Cursor.visible;
			oldLock = Cursor.lockState;
			oldRequest = ZCursor.IsRequested;
			pad = !ZInput.IsMouseActive();
			lastMouse = Input.mousePosition;
			if (Object.op_Implicit((Object)(object)InventoryGui.instance) && InventoryGui.IsVisible())
			{
				InventoryGui.instance.Hide();
			}
			open = true;
			armedAt = Time.unscaledTime + 0.3f;
			direction = 0;
			preview.ResetView(front);
			KeepCursor();
		}

		internal void Close()
		{
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			//IL_0053: Unknown result type (might be due to invalid IL or missing references)
			if (open)
			{
				open = false;
				inkWheel.Close();
				releaseFrame = Time.frameCount + 2;
				preview.Dispose();
				if (oldRequest)
				{
					ZCursor.Show();
				}
				else
				{
					ZCursor.Hide();
				}
				ZCursor.LockState = oldLock;
				Cursor.lockState = oldLock;
				Cursor.visible = oldCursor;
			}
		}

		private void LoadDraft()
		{
			inkWheel.Close();
			if (capes.Count == 0 || !Gear.IsChest(capes[selected]))
			{
				front = false;
			}
			draft = (MarkData.TryParse((capes.Count > 0) ? Gear.Read(capes[selected], front) : "", out var data) ? data : new MarkData
			{
				Pattern = "raven_crest"
			});
			category = PatternCatalog.Find(draft.Pattern).Category;
			message = "";
			showMark = true;
			preview.Dispose();
			preview.ResetView(front);
		}

		private void Update()
		{
			//IL_01c0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c6: Unknown result type (might be due to invalid IL or missing references)
			//IL_01cb: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d0: 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)
			Stamp.Maintain();
			if (!open)
			{
				return;
			}
			Player localPlayer = Player.m_localPlayer;
			if (!Object.op_Implicit((Object)(object)localPlayer) || ((Character)localPlayer).IsDead() || !Application.isFocused || !((Humanoid)localPlayer).GetInventory().GetAllItems().Contains(stampItem))
			{
				Close();
				return;
			}
			if (capes.Count > 0 && !((Humanoid)localPlayer).GetInventory().GetAllItems().Contains(capes[selected]))
			{
				Close();
				return;
			}
			bool buttonDown = ZInput.GetButtonDown("JoyMenu");
			if (Input.GetKeyDown((KeyCode)27) || ZInput.GetButtonDown("JoyButtonB") || buttonDown)
			{
				ZInput.ResetButtonStatus("JoyButtonB");
				ZInput.ResetButtonStatus("JoyMenu");
				if (inkWheel.Visible && !buttonDown)
				{
					FinishInk(accept: false);
				}
				else
				{
					Close();
				}
				return;
			}
			float joyLeftStickX = ZInput.GetJoyLeftStickX();
			float joyLeftStickY = ZInput.GetJoyLeftStickY();
			bool buttonDown2 = ZInput.GetButtonDown("JoyDPadUp");
			bool buttonDown3 = ZInput.GetButtonDown("JoyDPadDown");
			bool buttonDown4 = ZInput.GetButtonDown("JoyDPadLeft");
			bool buttonDown5 = ZInput.GetButtonDown("JoyDPadRight");
			if ((inkWheel.Visible && (Mathf.Abs(ZInput.GetJoyRightStickX()) > 0.25f || Mathf.Abs(ZInput.GetJoyRightStickY()) > 0.25f)) || Mathf.Abs(joyLeftStickX) > 0.35f || Mathf.Abs(joyLeftStickY) > 0.35f || buttonDown2 || buttonDown3 || buttonDown4 || buttonDown5 || ZInput.GetButtonDown("JoyButtonA") || (inkWheel.Visible && (ZInput.GetButtonDown("JoyButtonX") || ZInput.GetButtonDown("JoyButtonY"))) || ZInput.GetJoyLTrigger() > 0.1f || ZInput.GetJoyRTrigger() > 0.1f)
			{
				pad = true;
			}
			Vector3 val = Input.mousePosition - lastMouse;
			if (((Vector3)(ref val)).sqrMagnitude > 4f || Input.GetMouseButtonDown(0))
			{
				pad = false;
			}
			lastMouse = Input.mousePosition;
			if (Time.unscaledTime < armedAt)
			{
				return;
			}
			if (inkWheel.Visible)
			{
				inkWheel.UpdateInput(ZInput.GetJoyRightStickX(), ZInput.GetJoyRightStickY());
				if (inkWheel.TakePreview(out var hex))
				{
					draft.CustomInk = hex;
					showMark = true;
					preview.Invalidate();
				}
				float num = ZInput.GetJoyRTrigger() - ZInput.GetJoyLTrigger();
				if (Mathf.Abs(num) > 0.08f)
				{
					preview.Rotate(num * Mathf.Min(Time.unscaledDeltaTime, 0.05f) * 100f);
				}
				if (ZInput.GetButtonDown("JoyButtonA") || ZInput.GetButtonDown("JoyPlace") || Input.GetKeyDown((KeyCode)13))
				{
					FinishInk(accept: true);
					ZInput.ResetButtonStatus("JoyButtonA");
					ZInput.ResetButtonStatus("JoyPlace");
				}
				return;
			}
			int num2 = ((!(Mathf.Abs(joyLeftStickY) > 0.5f)) ? ((Mathf.Abs(joyLeftStickX) > 0.5f) ? ((joyLeftStickX < 0f) ? 3 : 4) : 0) : ((joyLeftStickY < 0f) ? 1 : 2));
			int num3 = ((buttonDown2 || Input.GetKeyDown((KeyCode)273)) ? 1 : ((buttonDown3 || Input.GetKeyDown((KeyCode)274)) ? 2 : ((buttonDown4 || Input.GetKeyDown((KeyCode)276)) ? 3 : ((buttonDown5 || Input.GetKeyDown((KeyCode)275)) ? 4 : 0))));
			if (num3 != 0)
			{
				Navigate(num3);
			}
			else if (num2 != 0 && (num2 != direction || Time.unscaledTime >= repeat))
			{
				Navigate(num2);
				repeat = Time.unscaledTime + ((num2 != direction) ? 0.35f : 0.14f);
			}
			direction = num2;
			float num4 = ZInput.GetJoyRTrigger() - ZInput.GetJoyLTrigger();
			if (Mathf.Abs(num4) > 0.08f)
			{
				preview.Rotate(num4 * Mathf.Min(Time.unscaledDeltaTime, 0.05f) * 100f);
			}
			if (Input.GetKeyDown((KeyCode)113))
			{
				preview.Rotate(-15f);
			}
			if (Input.GetKeyDown((KeyCode)101))
			{
				preview.Rotate(15f);
			}
			if (ZInput.GetButtonDown("JoyButtonA") || ZInput.GetButtonDown("JoyPlace") || Input.GetKeyDown((KeyCode)13))
			{
				if (row == 7)
				{
					Apply();
				}
				else if (row == 8)
				{
					Remove();
				}
				else if (row == 9)
				{
					Close();
				}
				else
				{
					Change(1);
				}
				ZInput.ResetButtonStatus("JoyButtonA");
				ZInput.ResetButtonStatus("JoyPlace");
			}
			string[] array = new string[4] { "JoyDPadUp", "JoyDPadDown", "JoyDPadLeft", "JoyDPadRight" };
			for (int i = 0; i < array.Length; i++)
			{
				ZInput.ResetButtonStatus(array[i]);
			}
		}

		private void Navigate(int dir)
		{
			switch (dir)
			{
			case 1:
				row = (row + 9) % 10;
				break;
			case 2:
				row = (row + 1) % 10;
				break;
			default:
				Change((dir != 3) ? 1 : (-1));
				break;
			}
		}

		private void Change(int delta)
		{
			if (capes.Count == 0)
			{
				return;
			}
			switch (row)
			{
			case 0:
				selected = (selected + delta + capes.Count) % capes.Count;
				LoadDraft();
				break;
			case 1:
				if (Gear.IsChest(capes[selected]))
				{
					front = !front;
					LoadDraft();
				}
				break;
			case 2:
				category = (category + delta + PatternCatalog.Categories.Length) % PatternCatalog.Categories.Length;
				draft.Pattern = PatternCatalog.At(category, 0).Id;
				showMark = true;
				break;
			case 3:
				draft.Pattern = PatternCatalog.At(category, PatternCatalog.Index(draft.Pattern) + delta).Id;
				showMark = true;
				break;
			case 4:
				OpenInk();
				break;
			case 5:
				draft.Size = Mathf.Clamp(draft.Size + delta, 0, 2);
				showMark = true;
				break;
			case 6:
				draft.Height = Mathf.Clamp(draft.Height + delta, 0, 4);
				showMark = true;
				break;
			}
			preview.Invalidate();
		}

		private void OpenInk()
		{
			beforeInk = draft.Copy();
			beforeInkVisible = showMark;
			inkWheel.Open(draft.ColorHex);
			armedAt = Time.unscaledTime + 0.15f;
		}

		private void FinishInk(bool accept)
		{
			if (accept)
			{
				draft.CustomInk = inkWheel.Hex;
				showMark = true;
			}
			else
			{
				draft = beforeInk;
				showMark = beforeInkVisible;
			}
			inkWheel.Close();
			preview.Invalidate();
			armedAt = Time.unscaledTime + 0.15f;
		}

		private void Apply()
		{
			if (capes.Count == 0)
			{
				return;
			}
			if (!showMark)
			{
				message = "Select a stamp to apply an emblem, or use Remove emblem.";
				return;
			}
			if (!preview.Ready)
			{
				message = "Wait for a valid gear preview before applying.";
				return;
			}
			Player localPlayer = Player.m_localPlayer;
			ItemData val = capes[selected];
			if (Object.op_Implicit((Object)(object)localPlayer) && ((Humanoid)localPlayer).GetInventory().GetAllItems().Contains(val))
			{
				val.m_customData[front ? "MarkYourGear.FrontEmblem" : "MarkYourGear.Emblem"] = draft.Encode();
				Changed(localPlayer);
				message = PatternCatalog.Find(draft.Pattern).Name + " applied to the " + (front ? "