Decompiled source of FletchersForge v1.0.1

FletchersForge.dll

Decompiled 5 days ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using System.Text;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using Jotunn.Configs;
using Jotunn.Entities;
using Jotunn.Managers;
using Jotunn.Utils;
using Microsoft.CodeAnalysis;
using TMPro;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[assembly: AssemblyCompany("FletchersForge")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyDescription("Disassemble arrows into shafts and heads; reforge in the field with the Fletcher's knife.")]
[assembly: AssemblyFileVersion("1.0.1.0")]
[assembly: AssemblyInformationalVersion("1.0.1+ea5b25f52530fab5a714749139adeb86bdaafc43")]
[assembly: AssemblyProduct("FletchersForge")]
[assembly: AssemblyTitle("FletchersForge")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.1.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace FletchersForge
{
	internal static class ArrowAssemblyRegistry
	{
		internal sealed class ArrowPair
		{
			public string ShaftPrefab;

			public string HeadPrefab;

			public string ArrowPrefab;
		}

		private static readonly Dictionary<string, ArrowPair> ArrowToParts = new Dictionary<string, ArrowPair>();

		private static readonly Dictionary<string, string> ShaftHeadToArrow = new Dictionary<string, string>();

		private static readonly HashSet<string> BoltPrefabs = new HashSet<string>(StringComparer.Ordinal) { "BoltBone", "BoltIron", "BoltBlackmetal", "BoltCarapace", "BoltCharred" };

		internal static void Initialize()
		{
			Register("ArrowWood", "FF_ShaftStandard", null, "ArrowWood");
			Register("ArrowFire", "FF_ShaftStandard", "FF_HeadFire", "ArrowFire");
			Register("ArrowFlint", "FF_ShaftStandard", "FF_HeadFlint", "ArrowFlint");
			Register("ArrowBronze", "FF_ShaftStandard", "FF_HeadBronze", "ArrowBronze");
			Register("ArrowIron", "FF_ShaftStandard", "FF_HeadIron", "ArrowIron");
			Register("ArrowSilver", "FF_ShaftStandard", "FF_HeadSilver", "ArrowSilver");
			Register("ArrowObsidian", "FF_ShaftStandard", "FF_HeadObsidian", "ArrowObsidian");
			Register("ArrowPoison", "FF_ShaftStandard", "FF_HeadPoison", "ArrowPoison");
			Register("ArrowFrost", "FF_ShaftStandard", "FF_HeadFrost", "ArrowFrost");
			Register("ArrowNeedle", "FF_ShaftNeedle", "FF_HeadNeedle", "ArrowNeedle");
			Register("ArrowCarapace", "FF_ShaftStandard", "FF_HeadCarapace", "ArrowCarapace");
			Register("ArrowCharred", "FF_ShaftAsh", "FF_HeadCharred", "ArrowCharred");
		}

		private static void Register(string arrow, string shaft, string head, string arrowPrefab)
		{
			ArrowToParts[arrow] = new ArrowPair
			{
				ShaftPrefab = shaft,
				HeadPrefab = head,
				ArrowPrefab = arrowPrefab
			};
			ShaftHeadToArrow[Key(shaft, head)] = arrowPrefab;
		}

		internal static bool TryGetParts(string arrowPrefabName, out string shaftPrefab, out string headPrefab)
		{
			shaftPrefab = null;
			headPrefab = null;
			if (!ArrowToParts.TryGetValue(arrowPrefabName, out var value))
			{
				return false;
			}
			shaftPrefab = value.ShaftPrefab;
			headPrefab = value.HeadPrefab;
			return true;
		}

		internal static bool TryGetArrow(string shaftPrefab, string headPrefab, out string arrowPrefab)
		{
			if (ShaftHeadToArrow.TryGetValue(Key(shaftPrefab, headPrefab), out arrowPrefab))
			{
				return true;
			}
			arrowPrefab = null;
			return false;
		}

		internal static string NormalizePrefabName(string prefabName)
		{
			if (string.IsNullOrEmpty(prefabName))
			{
				return string.Empty;
			}
			if (prefabName.EndsWith("(Clone)", StringComparison.Ordinal))
			{
				return prefabName.Substring(0, prefabName.Length - "(Clone)".Length).Trim();
			}
			return prefabName;
		}

		internal static bool IsArrowPrefab(string prefabName)
		{
			return ArrowToParts.ContainsKey(NormalizePrefabName(prefabName));
		}

		internal static bool IsBoltPrefab(string prefabName)
		{
			return BoltPrefabs.Contains(NormalizePrefabName(prefabName));
		}

		internal static bool IsProjectileAmmoPrefab(string prefabName)
		{
			if (!IsArrowPrefab(prefabName))
			{
				return IsBoltPrefab(prefabName);
			}
			return true;
		}

		internal static bool IsShaftPrefab(string prefabName)
		{
			string text = NormalizePrefabName(prefabName);
			if (!(text == "FF_ShaftStandard") && !(text == "FF_ShaftNeedle"))
			{
				return text == "FF_ShaftAsh";
			}
			return true;
		}

		internal static bool IsHeadPrefab(string prefabName)
		{
			return NormalizePrefabName(prefabName).StartsWith("FF_Head", StringComparison.Ordinal);
		}

		internal static bool IsKnifePrefab(string prefabName)
		{
			return NormalizePrefabName(prefabName) == "FF_FletchersKnife";
		}

		internal static bool IsQuiverPrefab(string prefabName)
		{
			return NormalizePrefabName(prefabName) == "FF_Quiver";
		}

		internal static bool IsQuiverStorageItem(string prefabName)
		{
			if (!IsKnifePrefab(prefabName) && !IsHeadPrefab(prefabName) && !IsShaftPrefab(prefabName))
			{
				return IsProjectileAmmoPrefab(prefabName);
			}
			return true;
		}

		private static string Key(string shaft, string head)
		{
			return shaft + "|" + (head ?? string.Empty);
		}
	}
	internal static class AssetBundleLoader
	{
		private static AssetBundle bundle;

		private static GameObject headPouchPrefab;

		private static GameObject knifePrefab;

		private static GameObject quiverPrefab;

		private static bool bundleLoadAttempted;

		private static bool knifeVisualLoadAttempted;

		private static bool quiverVisualLoadAttempted;

		internal static GameObject HeadPouchPrefab
		{
			get
			{
				EnsureBundleLoaded();
				return headPouchPrefab;
			}
		}

		internal static GameObject KnifePrefab
		{
			get
			{
				EnsureKnifeVisualLoaded();
				return knifePrefab;
			}
		}

		internal static GameObject QuiverPrefab
		{
			get
			{
				EnsureQuiverVisualLoaded();
				return quiverPrefab;
			}
		}

		internal static void EnsureLoaded()
		{
			EnsureBundleLoaded();
		}

		private static void EnsureBundleLoaded()
		{
			if (bundleLoadAttempted)
			{
				return;
			}
			bundleLoadAttempted = true;
			try
			{
				bundle = AssetUtils.LoadAssetBundleFromResources("fletchersforge", typeof(FletchersForgePlugin).Assembly);
				if ((Object)(object)bundle == (Object)null)
				{
					ManualLogSource log = FletchersForgePlugin.Log;
					if (log != null)
					{
						log.LogWarning((object)"AssetBundle 'fletchersforge' not found in embedded resources.");
					}
					return;
				}
				headPouchPrefab = LoadPrefab("FF_HeadPouch", "Assets/CustomItems/FF_HeadPouch.prefab");
				ManualLogSource log2 = FletchersForgePlugin.Log;
				if (log2 != null)
				{
					log2.LogInfo((object)string.Format("Loaded AssetBundle '{0}' (pouch={1}).", "fletchersforge", (Object)(object)headPouchPrefab != (Object)null));
				}
				if ((Object)(object)headPouchPrefab == (Object)null)
				{
					ManualLogSource log3 = FletchersForgePlugin.Log;
					if (log3 != null)
					{
						log3.LogWarning((object)("AssetBundle assets: " + string.Join(", ", bundle.GetAllAssetNames())));
					}
				}
			}
			catch (Exception arg)
			{
				ManualLogSource log4 = FletchersForgePlugin.Log;
				if (log4 != null)
				{
					log4.LogError((object)string.Format("Failed to load AssetBundle '{0}': {1}", "fletchersforge", arg));
				}
			}
		}

		private static void EnsureKnifeVisualLoaded()
		{
			EnsureBundleLoaded();
			if (!knifeVisualLoadAttempted)
			{
				knifeVisualLoadAttempted = true;
				knifePrefab = LoadPrefabCopy("FF_FletchersKnife", "Assets/CustomItems/FF_FletchersKnife.prefab", "FF_FletchersKnifeVisual");
				ManualLogSource log = FletchersForgePlugin.Log;
				if (log != null)
				{
					log.LogInfo((object)$"Knife visual loaded: {(Object)(object)knifePrefab != (Object)null}.");
				}
			}
		}

		private static void EnsureQuiverVisualLoaded()
		{
			EnsureBundleLoaded();
			if (!quiverVisualLoadAttempted)
			{
				quiverVisualLoadAttempted = true;
				quiverPrefab = LoadPrefabCopy("FF_Quiver", "Assets/CustomItems/FF_Quiver.prefab", "FF_QuiverVisual");
				ManualLogSource log = FletchersForgePlugin.Log;
				if (log != null)
				{
					log.LogInfo((object)$"Quiver visual loaded: {(Object)(object)quiverPrefab != (Object)null}.");
				}
			}
		}

		private static GameObject LoadPrefab(string shortName, string assetPath)
		{
			if ((Object)(object)bundle == (Object)null)
			{
				return null;
			}
			GameObject val = bundle.LoadAsset<GameObject>(shortName);
			if ((Object)(object)val == (Object)null && !string.IsNullOrEmpty(assetPath))
			{
				val = bundle.LoadAsset<GameObject>(assetPath);
			}
			return val;
		}

		private static GameObject LoadPrefabCopy(string shortName, string assetPath, string instanceName)
		{
			GameObject val = LoadPrefab(shortName, assetPath);
			if ((Object)(object)val == (Object)null)
			{
				return null;
			}
			((Object)val).name = instanceName;
			GameObject obj = Object.Instantiate<GameObject>(val);
			((Object)obj).name = instanceName;
			((Object)obj).hideFlags = (HideFlags)61;
			Object.DontDestroyOnLoad((Object)(object)obj);
			return obj;
		}
	}
	internal static class ComponentDropVisualUtility
	{
		private static GameObject GetBoxPrefab()
		{
			GameObject prefab = PrefabManager.Instance.GetPrefab("CargoCrate");
			if ((Object)(object)prefab != (Object)null)
			{
				return prefab;
			}
			string[] headDropBoxPrefabFallbacks = ModConstants.HeadDropBoxPrefabFallbacks;
			foreach (string text in headDropBoxPrefabFallbacks)
			{
				prefab = PrefabManager.Instance.GetPrefab(text);
				if ((Object)(object)prefab != (Object)null)
				{
					return prefab;
				}
			}
			return null;
		}

		internal static void ApplyHeadDropVisual(CustomItem item, string sourceArrow)
		{
			if (!((Object)(object)((item != null) ? item.ItemDrop : null) == (Object)null) && !TryApplyHeadPouchVisual(((Component)item.ItemDrop).gameObject))
			{
				ApplyShipwreckBoxVisual(((Component)item.ItemDrop).gameObject);
			}
		}

		private static bool TryApplyHeadPouchVisual(GameObject dropPrefab)
		{
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: Expected O, but got Unknown
			//IL_003a: Unknown result type (might be due to invalid IL or missing references)
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			//IL_005a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0064: Unknown result type (might be due to invalid IL or missing references)
			//IL_008b: Unknown result type (might be due to invalid IL or missing references)
			//IL_009b: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ab: Unknown result type (might be due to invalid IL or missing references)
			GameObject headPouchPrefab = AssetBundleLoader.HeadPouchPrefab;
			if ((Object)(object)headPouchPrefab == (Object)null)
			{
				return false;
			}
			RemoveDropVisual(dropPrefab);
			GameObject val = new GameObject("FF_DropVisual");
			val.transform.SetParent(dropPrefab.transform, false);
			val.transform.localPosition = Vector3.zero;
			val.transform.localRotation = Quaternion.identity;
			val.transform.localScale = Vector3.one * 2.5f;
			GameObject obj = Object.Instantiate<GameObject>(headPouchPrefab, val.transform);
			((Object)obj).name = "FF_HeadPouchVisual";
			obj.transform.localPosition = Vector3.zero;
			obj.transform.localRotation = Quaternion.identity;
			obj.transform.localScale = Vector3.one;
			StripLodHelpers(obj);
			DisableVisualColliders(obj);
			DisableVanillaDropRenderers(dropPrefab);
			EnsurePouchDropPhysics(dropPrefab);
			ManualLogSource log = FletchersForgePlugin.Log;
			if (log != null)
			{
				log.LogInfo((object)$"Applied leather pouch drop visual (scale {2.5f:0.##}) for {((Object)dropPrefab).name}.");
			}
			return true;
		}

		internal static void ApplyQuiverDropVisual(CustomItem item)
		{
			//IL_0050: Unknown result type (might be due to invalid IL or missing references)
			//IL_0056: Expected O, but got Unknown
			//IL_006e: Unknown result type (might be due to invalid IL or missing references)
			//IL_007e: Unknown result type (might be due to invalid IL or missing references)
			//IL_008e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0098: 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_00cf: Unknown result type (might be due to invalid IL or missing references)
			//IL_00df: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)((item != null) ? item.ItemDrop : null) == (Object)null)
			{
				return;
			}
			GameObject gameObject = ((Component)item.ItemDrop).gameObject;
			GameObject quiverPrefab = AssetBundleLoader.QuiverPrefab;
			if ((Object)(object)quiverPrefab == (Object)null)
			{
				ManualLogSource log = FletchersForgePlugin.Log;
				if (log != null)
				{
					log.LogWarning((object)"FF_Quiver bundle prefab missing; keeping deer hide drop mesh.");
				}
				return;
			}
			RemoveDropVisual(gameObject);
			GameObject val = new GameObject("FF_DropVisual");
			val.transform.SetParent(gameObject.transform, false);
			val.transform.localPosition = Vector3.zero;
			val.transform.localRotation = Quaternion.identity;
			val.transform.localScale = Vector3.one * 1.375f;
			GameObject obj = Object.Instantiate<GameObject>(quiverPrefab, val.transform);
			((Object)obj).name = "FF_QuiverVisual";
			obj.transform.localPosition = Vector3.zero;
			obj.transform.localRotation = Quaternion.identity;
			obj.transform.localScale = Vector3.one;
			CustomVisualUtility.PrepareBundledInstance(obj);
			CustomVisualUtility.ApplyMaterialsFromSource(obj, AssetBundleLoader.HeadPouchPrefab);
			DisableVanillaDropRenderers(gameObject);
			EnsurePouchDropPhysics(gameObject);
			ManualLogSource log2 = FletchersForgePlugin.Log;
			if (log2 != null)
			{
				log2.LogInfo((object)$"Applied quiver drop visual (scale {1.375f:0.##}) for {((Object)gameObject).name}.");
			}
		}

		private static void StripLodHelpers(GameObject pouchRoot)
		{
			LODGroup component = pouchRoot.GetComponent<LODGroup>();
			if ((Object)(object)component != (Object)null)
			{
				Object.Destroy((Object)(object)component);
			}
			List<GameObject> list = new List<GameObject>();
			Transform[] componentsInChildren = pouchRoot.GetComponentsInChildren<Transform>(true);
			foreach (Transform val in componentsInChildren)
			{
				if (!((Object)(object)val == (Object)null) && !((Object)(object)val == (Object)(object)pouchRoot.transform))
				{
					string name = ((Object)val).name;
					if (name.IndexOf("LOD1", StringComparison.OrdinalIgnoreCase) >= 0 || name.IndexOf("LOD2", StringComparison.OrdinalIgnoreCase) >= 0 || name.IndexOf("LOD3", StringComparison.OrdinalIgnoreCase) >= 0)
					{
						list.Add(((Component)val).gameObject);
					}
				}
			}
			foreach (GameObject item in list)
			{
				Object.Destroy((Object)(object)item);
			}
		}

		private static void DisableVisualColliders(GameObject visualRoot)
		{
			Collider[] componentsInChildren = visualRoot.GetComponentsInChildren<Collider>(true);
			foreach (Collider val in componentsInChildren)
			{
				if ((Object)(object)val != (Object)null)
				{
					val.enabled = false;
				}
			}
		}

		private static void EnsurePouchDropPhysics(GameObject dropPrefab)
		{
			//IL_008a: Unknown result type (might be due to invalid IL or missing references)
			//IL_009b: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b0: Unknown result type (might be due to invalid IL or missing references)
			Collider[] componentsInChildren = dropPrefab.GetComponentsInChildren<Collider>(true);
			foreach (Collider val in componentsInChildren)
			{
				if ((Object)(object)((Component)val).transform != (Object)(object)dropPrefab.transform)
				{
					val.enabled = false;
				}
			}
			SphereCollider component = dropPrefab.GetComponent<SphereCollider>();
			if ((Object)(object)component != (Object)null)
			{
				Object.Destroy((Object)(object)component);
			}
			BoxCollider val2 = dropPrefab.GetComponent<BoxCollider>();
			if ((Object)(object)val2 == (Object)null)
			{
				val2 = dropPrefab.AddComponent<BoxCollider>();
			}
			float num = 1.1f;
			((Collider)val2).enabled = true;
			((Collider)val2).isTrigger = false;
			val2.size = new Vector3(num, num * 0.85f, num);
			val2.center = new Vector3(0f, val2.size.y * 0.5f, 0f);
			Rigidbody val3 = dropPrefab.GetComponent<Rigidbody>();
			if ((Object)(object)val3 == (Object)null)
			{
				val3 = dropPrefab.AddComponent<Rigidbody>();
			}
			val3.isKinematic = false;
			val3.useGravity = true;
			val3.mass = 2f;
			val3.linearDamping = 1.5f;
			val3.angularDamping = 8f;
			val3.collisionDetectionMode = (CollisionDetectionMode)1;
			val3.constraints = (RigidbodyConstraints)112;
		}

		internal static void ApplyShaftDropVisual(CustomItem item, string sourceArrow, bool ashTint = false)
		{
			if (!((Object)(object)((item != null) ? item.ItemDrop : null) == (Object)null))
			{
				ApplyArrowPartDropVisual(((Component)item.ItemDrop).gameObject, sourceArrow, isHead: false, ashTint);
			}
		}

		private static void ApplyShipwreckBoxVisual(GameObject dropPrefab)
		{
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Expected O, but got Unknown
			//IL_004d: 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_006d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0077: Unknown result type (might be due to invalid IL or missing references)
			GameObject boxPrefab = GetBoxPrefab();
			if ((Object)(object)boxPrefab == (Object)null)
			{
				ManualLogSource log = FletchersForgePlugin.Log;
				if (log != null)
				{
					log.LogWarning((object)"No box prefab found for head drop visual; keeping iron scrap mesh.");
				}
				return;
			}
			RemoveDropVisual(dropPrefab);
			GameObject val = new GameObject("FF_DropVisual");
			val.transform.SetParent(dropPrefab.transform, false);
			val.transform.localPosition = Vector3.zero;
			val.transform.localRotation = Quaternion.identity;
			val.transform.localScale = Vector3.one * 0.25f;
			if (!CopyMeshHierarchyFromRoot(boxPrefab.transform, val.transform))
			{
				Object.Destroy((Object)(object)val);
				EnableVanillaDropRenderers(dropPrefab);
				ManualLogSource log2 = FletchersForgePlugin.Log;
				if (log2 != null)
				{
					log2.LogWarning((object)("No box mesh copied for " + ((Object)dropPrefab).name + "; keeping iron scrap mesh."));
				}
				return;
			}
			AlignDropVisualToGround(val.transform);
			DisableVanillaDropRenderers(dropPrefab);
			EnsureDropPhysics(dropPrefab);
			ManualLogSource log3 = FletchersForgePlugin.Log;
			if (log3 != null)
			{
				log3.LogInfo((object)$"Applied box drop visual ({0.25f:P0}) for {((Object)dropPrefab).name} from '{((Object)boxPrefab).name}'.");
			}
		}

		private static void ApplyArrowPartDropVisual(GameObject dropPrefab, string sourceArrow, bool isHead, bool ashTint = false)
		{
			GameObject val = (isHead ? IconRigUtility.BuildHeadIconRig(sourceArrow, 1f) : IconRigUtility.BuildShaftIconRig(sourceArrow, ashTint));
			if ((Object)(object)val == (Object)null)
			{
				ManualLogSource log = FletchersForgePlugin.Log;
				if (log != null)
				{
					log.LogWarning((object)("Could not build drop visual for " + ((Object)dropPrefab).name + " from " + sourceArrow + "."));
				}
				EnableVanillaDropRenderers(dropPrefab);
				return;
			}
			bool num = TryCopyMeshVisual(dropPrefab, val, isHead);
			Object.Destroy((Object)(object)val);
			if (!num)
			{
				EnableVanillaDropRenderers(dropPrefab);
				ManualLogSource log2 = FletchersForgePlugin.Log;
				if (log2 != null)
				{
					log2.LogWarning((object)("No mesh copied for drop visual on " + ((Object)dropPrefab).name + "."));
				}
				return;
			}
			DisableVanillaDropRenderers(dropPrefab);
			EnsureDropPhysics(dropPrefab);
			ManualLogSource log3 = FletchersForgePlugin.Log;
			if (log3 != null)
			{
				log3.LogInfo((object)("Applied drop visual for " + ((Object)dropPrefab).name + "."));
			}
		}

		private static void RemoveDropVisual(GameObject dropPrefab)
		{
			Transform val = dropPrefab.transform.Find("FF_DropVisual");
			if ((Object)(object)val != (Object)null)
			{
				Object.Destroy((Object)(object)((Component)val).gameObject);
			}
		}

		private static bool TryCopyMeshVisual(GameObject dropPrefab, GameObject rig, bool isHead)
		{
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Expected O, but got Unknown
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			//IL_0058: Unknown result type (might be due to invalid IL or missing references)
			//IL_006c: Unknown result type (might be due to invalid IL or missing references)
			RemoveDropVisual(dropPrefab);
			GameObject val = new GameObject("FF_DropVisual");
			val.transform.SetParent(dropPrefab.transform, false);
			val.transform.localPosition = Vector3.zero;
			val.transform.localRotation = Quaternion.Euler(0f, 0f, 90f);
			val.transform.localScale = Vector3.one * (isHead ? 0.28f : 0.22f);
			bool flag = false;
			Renderer[] componentsInChildren = rig.GetComponentsInChildren<Renderer>(true);
			foreach (Renderer val2 in componentsInChildren)
			{
				if (!((Object)(object)val2 == (Object)null) && CopyRendererMesh(val2, val.transform))
				{
					flag = true;
				}
			}
			if (!flag)
			{
				Object.Destroy((Object)(object)val);
			}
			return flag;
		}

		private static bool CopyMeshHierarchyFromRoot(Transform sourceRoot, Transform destRoot)
		{
			bool result = false;
			Renderer[] componentsInChildren = ((Component)sourceRoot).GetComponentsInChildren<Renderer>(true);
			foreach (Renderer val in componentsInChildren)
			{
				if (!((Object)(object)val == (Object)null) && CopyRendererMeshRelative(val, sourceRoot, destRoot))
				{
					result = true;
				}
			}
			return result;
		}

		private static bool CopyRendererMeshRelative(Renderer source, Transform sourceRoot, Transform destRoot)
		{
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			//IL_004d: Unknown result type (might be due to invalid IL or missing references)
			//IL_005a: 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)
			//IL_006c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0076: Unknown result type (might be due to invalid IL or missing references)
			//IL_007d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0082: Unknown result type (might be due to invalid IL or missing references)
			//IL_008d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0092: 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_00a7: 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_00ae: Unknown result type (might be due to invalid IL or missing references)
			//IL_00af: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cc: 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_00dd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f2: Unknown result type (might be due to invalid IL or missing references)
			Mesh val = null;
			if (source is MeshRenderer)
			{
				MeshFilter component = ((Component)source).GetComponent<MeshFilter>();
				if ((Object)(object)component != (Object)null)
				{
					val = component.sharedMesh;
				}
			}
			else
			{
				SkinnedMeshRenderer val2 = (SkinnedMeshRenderer)(object)((source is SkinnedMeshRenderer) ? source : null);
				if (val2 != null)
				{
					val = val2.sharedMesh;
				}
			}
			if ((Object)(object)val == (Object)null)
			{
				return false;
			}
			GameObject val3 = new GameObject(((Object)source).name);
			val3.transform.SetParent(destRoot, false);
			val3.transform.localPosition = sourceRoot.InverseTransformPoint(((Component)source).transform.position);
			val3.transform.localRotation = Quaternion.Inverse(sourceRoot.rotation) * ((Component)source).transform.rotation;
			Vector3 lossyScale = ((Component)source).transform.lossyScale;
			Vector3 lossyScale2 = sourceRoot.lossyScale;
			val3.transform.localScale = new Vector3(SafeDivide(lossyScale.x, lossyScale2.x), SafeDivide(lossyScale.y, lossyScale2.y), SafeDivide(lossyScale.z, lossyScale2.z));
			val3.AddComponent<MeshFilter>().sharedMesh = val;
			((Renderer)val3.AddComponent<MeshRenderer>()).sharedMaterials = source.sharedMaterials;
			return true;
		}

		private static bool CopyRendererMesh(Renderer source, Transform parent)
		{
			//IL_0045: Unknown result type (might be due to invalid IL or missing references)
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0057: Unknown result type (might be due to invalid IL or missing references)
			//IL_0063: Unknown result type (might be due to invalid IL or missing references)
			//IL_006d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0079: 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_008f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0099: Unknown result type (might be due to invalid IL or missing references)
			Mesh val = null;
			if (source is MeshRenderer)
			{
				MeshFilter component = ((Component)source).GetComponent<MeshFilter>();
				if ((Object)(object)component != (Object)null)
				{
					val = component.sharedMesh;
				}
			}
			else
			{
				SkinnedMeshRenderer val2 = (SkinnedMeshRenderer)(object)((source is SkinnedMeshRenderer) ? source : null);
				if (val2 != null)
				{
					val = val2.sharedMesh;
				}
			}
			if ((Object)(object)val == (Object)null)
			{
				return false;
			}
			GameObject val3 = new GameObject(((Object)source).name);
			val3.transform.SetParent(parent, false);
			val3.transform.localPosition = ((Component)source).transform.localPosition;
			val3.transform.localRotation = ((Component)source).transform.localRotation;
			val3.transform.localScale = ((Component)source).transform.localScale;
			val3.AddComponent<MeshFilter>().sharedMesh = val;
			((Renderer)val3.AddComponent<MeshRenderer>()).sharedMaterials = source.sharedMaterials;
			return true;
		}

		private static void DisableVanillaDropRenderers(GameObject dropPrefab)
		{
			Transform val = dropPrefab.transform.Find("FF_DropVisual");
			Renderer[] componentsInChildren = dropPrefab.GetComponentsInChildren<Renderer>(true);
			foreach (Renderer val2 in componentsInChildren)
			{
				if (!((Object)(object)val != (Object)null) || !((Component)val2).transform.IsChildOf(val))
				{
					val2.enabled = false;
				}
			}
		}

		private static void EnableVanillaDropRenderers(GameObject dropPrefab)
		{
			Transform val = dropPrefab.transform.Find("FF_DropVisual");
			Renderer[] componentsInChildren = dropPrefab.GetComponentsInChildren<Renderer>(true);
			foreach (Renderer val2 in componentsInChildren)
			{
				if (!((Object)(object)val != (Object)null) || !((Component)val2).transform.IsChildOf(val))
				{
					val2.enabled = true;
				}
			}
		}

		private static void EnsureDropPhysics(GameObject dropPrefab)
		{
			//IL_0067: Unknown result type (might be due to invalid IL or missing references)
			Collider[] componentsInChildren = dropPrefab.GetComponentsInChildren<Collider>(true);
			foreach (Collider val in componentsInChildren)
			{
				if ((Object)(object)val != (Object)null)
				{
					val.enabled = true;
				}
			}
			Rigidbody component = dropPrefab.GetComponent<Rigidbody>();
			if ((Object)(object)component != (Object)null)
			{
				component.isKinematic = false;
				component.useGravity = true;
			}
			if ((Object)(object)dropPrefab.GetComponent<Collider>() == (Object)null)
			{
				SphereCollider obj = dropPrefab.AddComponent<SphereCollider>();
				obj.radius = 0.045f;
				obj.center = Vector3.zero;
			}
		}

		private static void AlignDropVisualToGround(Transform visualRoot)
		{
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			//IL_0046: Unknown result type (might be due to invalid IL or missing references)
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0055: Unknown result type (might be due to invalid IL or missing references)
			//IL_005a: Unknown result type (might be due to invalid IL or missing references)
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0067: Unknown result type (might be due to invalid IL or missing references)
			//IL_006e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0079: Unknown result type (might be due to invalid IL or missing references)
			//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_008d: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cf: Unknown result type (might be due to invalid IL or missing references)
			float num = float.MaxValue;
			Renderer[] componentsInChildren = ((Component)visualRoot).GetComponentsInChildren<Renderer>(true);
			foreach (Renderer val in componentsInChildren)
			{
				MeshFilter component = ((Component)val).GetComponent<MeshFilter>();
				if (!((Object)(object)component == (Object)null) && !((Object)(object)component.sharedMesh == (Object)null))
				{
					Bounds bounds = component.sharedMesh.bounds;
					Vector3 val2 = Vector3.Scale(((Bounds)(ref bounds)).extents, ((Component)val).transform.localScale);
					float num2 = (((Component)val).transform.localPosition + Vector3.Scale(((Bounds)(ref bounds)).center, ((Component)val).transform.localScale)).y - val2.y;
					num = Mathf.Min(num, num2);
				}
			}
			if (num < float.MaxValue && !Mathf.Approximately(num, 0f))
			{
				visualRoot.localPosition = new Vector3(0f, 0f - num, 0f);
			}
		}

		private static float SafeDivide(float value, float divisor)
		{
			if (!Mathf.Approximately(divisor, 0f))
			{
				return value / divisor;
			}
			return value;
		}
	}
	internal static class CustomVisualUtility
	{
		internal static GameObject ApplyBundledVisual(GameObject itemPrefab, GameObject bundledPrefab, string visualRootName, Vector3 localPosition, Vector3 localEulerAngles, Vector3 localScale)
		{
			//IL_0037: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: Expected O, but got Unknown
			//IL_0050: 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_005e: Unknown result type (might be due to invalid IL or missing references)
			//IL_006e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0098: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a8: 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)
			if ((Object)(object)itemPrefab == (Object)null || (Object)(object)bundledPrefab == (Object)null)
			{
				return null;
			}
			RemoveVisualRoot(itemPrefab, visualRootName);
			Transform val = itemPrefab.transform.Find("attach") ?? itemPrefab.transform;
			GameObject val2 = new GameObject(visualRootName);
			val2.transform.SetParent(val, false);
			val2.transform.localPosition = localPosition;
			val2.transform.localRotation = Quaternion.Euler(localEulerAngles);
			val2.transform.localScale = localScale;
			GameObject obj = Object.Instantiate<GameObject>(bundledPrefab, val2.transform);
			((Object)obj).name = visualRootName + "_Mesh";
			obj.transform.localPosition = Vector3.zero;
			obj.transform.localRotation = Quaternion.identity;
			obj.transform.localScale = Vector3.one;
			PrepareBundledInstance(obj);
			return val2;
		}

		internal static void PrepareBundledInstance(GameObject instance)
		{
			StripLodGroup(instance);
			DisableColliders(instance);
			StripRigidbodies(instance);
		}

		internal static void RemoveVisualRootFromItem(GameObject itemPrefab, string visualRootName)
		{
			RemoveVisualRoot(itemPrefab, visualRootName);
		}

		internal static bool HasEnabledRenderers(GameObject root)
		{
			if ((Object)(object)root == (Object)null)
			{
				return false;
			}
			Renderer[] componentsInChildren = root.GetComponentsInChildren<Renderer>(true);
			foreach (Renderer val in componentsInChildren)
			{
				if ((Object)(object)val == (Object)null || !val.enabled)
				{
					continue;
				}
				Material[] sharedMaterials = val.sharedMaterials;
				if (sharedMaterials == null || sharedMaterials.Length == 0)
				{
					continue;
				}
				Material[] array = sharedMaterials;
				for (int j = 0; j < array.Length; j++)
				{
					if ((Object)(object)array[j] != (Object)null)
					{
						return true;
					}
				}
			}
			return false;
		}

		internal static void ApplyTemplateMaterials(GameObject visualRoot, string templatePrefabName)
		{
			if ((Object)(object)visualRoot == (Object)null)
			{
				return;
			}
			GameObject prefab = PrefabManager.Instance.GetPrefab(templatePrefabName);
			if ((Object)(object)prefab == (Object)null)
			{
				ManualLogSource log = FletchersForgePlugin.Log;
				if (log != null)
				{
					log.LogWarning((object)("Template prefab '" + templatePrefabName + "' not found for material remap."));
				}
				return;
			}
			Transform val = prefab.transform.Find("attach");
			Renderer val2 = null;
			if ((Object)(object)val != (Object)null)
			{
				Transform obj = val.Find("mesh");
				val2 = ((obj != null) ? ((Component)obj).GetComponent<Renderer>() : null);
			}
			if ((Object)(object)val2 == (Object)null)
			{
				Transform obj2 = PrefabPathUtility.FindRendererChild(prefab.transform);
				val2 = ((obj2 != null) ? ((Component)obj2).GetComponent<Renderer>() : null);
			}
			if ((Object)(object)val2 == (Object)null || val2.sharedMaterials == null || val2.sharedMaterials.Length == 0)
			{
				ManualLogSource log2 = FletchersForgePlugin.Log;
				if (log2 != null)
				{
					log2.LogWarning((object)("No renderer materials on template '" + templatePrefabName + "'."));
				}
				return;
			}
			Material[] sharedMaterials = val2.sharedMaterials;
			Renderer[] componentsInChildren = visualRoot.GetComponentsInChildren<Renderer>(true);
			foreach (Renderer val3 in componentsInChildren)
			{
				if (!((Object)(object)val3 == (Object)null))
				{
					Material[] array = (Material[])(object)new Material[Math.Max(1, val3.sharedMaterials.Length)];
					for (int j = 0; j < array.Length; j++)
					{
						array[j] = sharedMaterials[Math.Min(j, sharedMaterials.Length - 1)];
					}
					val3.sharedMaterials = array;
					val3.enabled = true;
				}
			}
		}

		internal static void ApplyMaterialsFromSource(GameObject visualRoot, GameObject sourcePrefab)
		{
			if ((Object)(object)visualRoot == (Object)null || (Object)(object)sourcePrefab == (Object)null)
			{
				return;
			}
			Material val = null;
			Renderer[] componentsInChildren = sourcePrefab.GetComponentsInChildren<Renderer>(true);
			foreach (Renderer val2 in componentsInChildren)
			{
				if (((val2 != null) ? val2.sharedMaterials : null) == null)
				{
					continue;
				}
				Material[] sharedMaterials = val2.sharedMaterials;
				foreach (Material val3 in sharedMaterials)
				{
					if ((Object)(object)val3 != (Object)null)
					{
						val = val3;
						break;
					}
				}
				if ((Object)(object)val != (Object)null)
				{
					break;
				}
			}
			if ((Object)(object)val == (Object)null)
			{
				ManualLogSource log = FletchersForgePlugin.Log;
				if (log != null)
				{
					log.LogWarning((object)("No materials found on '" + ((Object)sourcePrefab).name + "' to copy."));
				}
				return;
			}
			componentsInChildren = visualRoot.GetComponentsInChildren<Renderer>(true);
			foreach (Renderer val4 in componentsInChildren)
			{
				if (!((Object)(object)val4 == (Object)null))
				{
					Material[] array = (Material[])(object)new Material[Math.Max(1, val4.sharedMaterials.Length)];
					for (int k = 0; k < array.Length; k++)
					{
						array[k] = val;
					}
					val4.sharedMaterials = array;
					val4.enabled = true;
				}
			}
		}

		private static void RemoveVisualRoot(GameObject itemPrefab, string visualRootName)
		{
			Transform val = itemPrefab.transform.Find(visualRootName);
			if ((Object)(object)val != (Object)null)
			{
				Object.Destroy((Object)(object)((Component)val).gameObject);
			}
			Transform val2 = itemPrefab.transform.Find("attach");
			if ((Object)(object)val2 != (Object)null)
			{
				Transform val3 = val2.Find(visualRootName);
				if ((Object)(object)val3 != (Object)null)
				{
					Object.Destroy((Object)(object)((Component)val3).gameObject);
				}
			}
		}

		private static void StripLodGroup(GameObject root)
		{
			LODGroup component = root.GetComponent<LODGroup>();
			if ((Object)(object)component != (Object)null)
			{
				Object.Destroy((Object)(object)component);
			}
			List<GameObject> list = new List<GameObject>();
			Transform[] componentsInChildren = root.GetComponentsInChildren<Transform>(true);
			foreach (Transform val in componentsInChildren)
			{
				if (!((Object)(object)val == (Object)null) && !((Object)(object)val == (Object)(object)root.transform))
				{
					string name = ((Object)val).name;
					if (name.IndexOf("LOD1", StringComparison.OrdinalIgnoreCase) >= 0 || name.IndexOf("LOD2", StringComparison.OrdinalIgnoreCase) >= 0 || name.IndexOf("LOD3", StringComparison.OrdinalIgnoreCase) >= 0)
					{
						list.Add(((Component)val).gameObject);
					}
				}
			}
			foreach (GameObject item in list)
			{
				Object.Destroy((Object)(object)item);
			}
		}

		private static void DisableColliders(GameObject root)
		{
			Collider[] componentsInChildren = root.GetComponentsInChildren<Collider>(true);
			foreach (Collider val in componentsInChildren)
			{
				if ((Object)(object)val != (Object)null)
				{
					val.enabled = false;
				}
			}
		}

		private static void StripRigidbodies(GameObject root)
		{
			Rigidbody[] componentsInChildren = root.GetComponentsInChildren<Rigidbody>(true);
			foreach (Rigidbody val in componentsInChildren)
			{
				if ((Object)(object)val != (Object)null)
				{
					Object.Destroy((Object)(object)val);
				}
			}
		}
	}
	internal static class FletchBenchButtonUi
	{
		private const string TakeAllLabelKey = "$inventory_takeall";

		private const string StackAllLabelKey = "$inventory_stackall";

		internal static void Update(InventoryGui gui, bool benchOpen)
		{
			if ((Object)(object)gui == (Object)null)
			{
				return;
			}
			bool flag = !benchOpen && gui.IsContainerOpen();
			bool flag2 = benchOpen && InventoryGui.IsVisible();
			if ((Object)(object)gui.m_takeAllButton != (Object)null)
			{
				((Component)gui.m_takeAllButton).gameObject.SetActive(flag || flag2);
				if (flag2)
				{
					SetButtonLabel(gui.m_takeAllButton, GetReforgeLabel());
				}
				else if (flag)
				{
					RestoreVanillaLabel(gui.m_takeAllButton, "$inventory_takeall", "Take all");
				}
			}
			if ((Object)(object)gui.m_stackAllButton != (Object)null)
			{
				((Component)gui.m_stackAllButton).gameObject.SetActive(flag || flag2);
				if (flag2)
				{
					SetButtonLabel(gui.m_stackAllButton, GetSplitLabel());
				}
				else if (flag)
				{
					RestoreVanillaLabel(gui.m_stackAllButton, "$inventory_stackall", "Place stacks");
				}
			}
		}

		private static string GetReforgeLabel()
		{
			string text = Localization.instance.Localize("$FF_Reforge");
			if (!string.IsNullOrEmpty(text) && !text.StartsWith("$", StringComparison.Ordinal))
			{
				return text;
			}
			return "Reforge";
		}

		private static string GetSplitLabel()
		{
			string text = Localization.instance.Localize("$FF_Split");
			if (!string.IsNullOrEmpty(text) && !text.StartsWith("$", StringComparison.Ordinal))
			{
				return text;
			}
			return "Split";
		}

		private static void RestoreVanillaLabel(Button button, string locKey, string fallback)
		{
			string text = Localization.instance.Localize(locKey);
			if (string.IsNullOrEmpty(text) || text.StartsWith("$", StringComparison.Ordinal))
			{
				text = fallback;
			}
			SetButtonLabel(button, text);
		}

		private static void SetButtonLabel(Button button, string label)
		{
			TMP_Text componentInChildren = ((Component)button).GetComponentInChildren<TMP_Text>(true);
			if ((Object)(object)componentInChildren != (Object)null)
			{
				componentInChildren.text = label;
			}
		}
	}
	internal static class FletchBenchInventory
	{
		private static Inventory inventory;

		internal static Inventory Inventory => inventory;

		internal static void Initialize()
		{
			//IL_0045: Unknown result type (might be due to invalid IL or missing references)
			//IL_004f: Expected O, but got Unknown
			if (inventory == null)
			{
				Sprite val = null;
				GameObject prefab = PrefabManager.Instance.GetPrefab("chest");
				Container val2 = (((Object)(object)prefab != (Object)null) ? prefab.GetComponent<Container>() : null);
				if ((Object)(object)val2 != (Object)null)
				{
					val = val2.m_bkg;
				}
				inventory = new Inventory("$FF_FletchContainer", val, 2, 1);
				ManualLogSource log = FletchersForgePlugin.Log;
				if (log != null)
				{
					log.LogInfo((object)"Initialized virtual Fletcher bench inventory.");
				}
			}
		}

		internal static void ClearSlots()
		{
			if (inventory != null)
			{
				inventory.RemoveAll();
			}
		}
	}
	[BepInPlugin("hardwire99.fletchersforge", "Fletchers Forge", "1.0.1")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	public sealed class FletchersForgePlugin : BaseUnityPlugin
	{
		internal static ManualLogSource Log;

		private Harmony harmony;

		private void Awake()
		{
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			//IL_0042: Expected O, but got Unknown
			Log = ((BaseUnityPlugin)this).Logger;
			ModConfig.Bind(((BaseUnityPlugin)this).Config);
			if (!ModConfig.Enabled.Value)
			{
				Log.LogInfo((object)"Fletchers Forge is disabled in config.");
				return;
			}
			harmony = new Harmony("hardwire99.fletchersforge");
			harmony.PatchAll(typeof(FletchersForgePlugin).Assembly);
			LocalizationRegistrar.Initialize();
			((Component)this).gameObject.AddComponent<FletchUiBehaviour>();
			PrefabManager.OnVanillaPrefabsAvailable += OnVanillaPrefabsAvailable;
			ItemManager.OnItemsRegisteredFejd += OnItemsRegisteredFejd;
			ItemManager.OnItemsRegistered += OnItemsRegisteredWorld;
			Log.LogInfo((object)"Fletchers Forge 1.0.1 loaded.");
			Log.LogInfo((object)$"Legacy bench prefab hash: {ModConstants.LegacyContainerPrefabHash}");
		}

		private void OnDestroy()
		{
			PrefabManager.OnVanillaPrefabsAvailable -= OnVanillaPrefabsAvailable;
			ItemManager.OnItemsRegisteredFejd -= OnItemsRegisteredFejd;
			ItemManager.OnItemsRegistered -= OnItemsRegisteredWorld;
			Harmony obj = harmony;
			if (obj != null)
			{
				obj.UnpatchSelf();
			}
		}

		private static void OnVanillaPrefabsAvailable()
		{
			AssetBundleLoader.EnsureLoaded();
			ItemRegistrar.RegisterAll();
			RecipeRegistrar.RegisterAll();
			PrefabManager.OnVanillaPrefabsAvailable -= OnVanillaPrefabsAvailable;
		}

		private static void OnItemsRegisteredFejd()
		{
			ItemRegistrar.ApplyEmbeddedHeadIconsOnly();
		}

		private static void OnItemsRegisteredWorld()
		{
			ItemRegistrar.ApplyDeferredIcons();
		}
	}
	internal static class FletchersKnifeConfigurator
	{
		internal static void Configure(SharedData shared)
		{
			//IL_0002: 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_0128: Unknown result type (might be due to invalid IL or missing references)
			shared.m_itemType = (ItemType)3;
			shared.m_toolTier = 0;
			shared.m_weight = 0.25f;
			shared.m_teleportable = true;
			shared.m_maxStackSize = 1;
			shared.m_maxQuality = 1;
			shared.m_value = 0;
			shared.m_useDurability = false;
			shared.m_maxDurability = 0f;
			shared.m_durabilityDrain = 0f;
			shared.m_blockPower = 0f;
			shared.m_blockPowerPerLevel = 0f;
			shared.m_blockable = false;
			shared.m_deflectionForce = 0f;
			shared.m_deflectionForcePerLevel = 0f;
			shared.m_timedBlockBonus = 1f;
			shared.m_blockAdrenaline = 0f;
			shared.m_perfectBlockAdrenaline = 0f;
			shared.m_perfectBlockStaminaRegen = 0f;
			shared.m_perfectBlockStatusEffect = null;
			shared.m_maxAdrenaline = 0f;
			shared.m_fullAdrenalineSE = null;
			shared.m_attackForce = 0f;
			shared.m_backstabBonus = 1f;
			shared.m_armor = 0f;
			shared.m_armorPerLevel = 0f;
			shared.m_attackStatusEffect = null;
			shared.m_attackStatusEffectChance = 0f;
			shared.m_equipStatusEffect = null;
			shared.m_secondaryAttack = null;
			shared.m_damages = default(DamageTypes);
			shared.m_damagesPerLevel = default(DamageTypes);
			GameObject prefab = PrefabManager.Instance.GetPrefab("KnifeCopper");
			ItemDrop val = ((prefab != null) ? prefab.GetComponent<ItemDrop>() : null);
			if (val?.m_itemData?.m_shared?.m_attack == null)
			{
				shared.m_attack = null;
				ManualLogSource log = FletchersForgePlugin.Log;
				if (log != null)
				{
					log.LogWarning((object)"Fletcher's knife: KnifeCopper attack template missing; knife has no swing.");
				}
			}
			else
			{
				shared.m_attack = CloneAttack(val.m_itemData.m_shared.m_attack);
				shared.m_attack.m_damageMultiplier = 0f;
				shared.m_attack.m_forceMultiplier = 0f;
				shared.m_attack.m_raiseSkillAmount = 0f;
				shared.m_attack.m_attackStamina = 0f;
				shared.m_attack.m_selfDamage = 0;
			}
		}

		private static Attack CloneAttack(Attack source)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Expected O, but got Unknown
			Attack val = new Attack();
			FieldInfo[] fields = typeof(Attack).GetFields(BindingFlags.Instance | BindingFlags.Public);
			foreach (FieldInfo fieldInfo in fields)
			{
				fieldInfo.SetValue(val, fieldInfo.GetValue(source));
			}
			return val;
		}
	}
	internal static class FletchersKnifeHelper
	{
		private static readonly MethodInfo GetRightItemMethod = typeof(Humanoid).GetMethod("GetRightItem", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);

		private static readonly MethodInfo GetLeftItemMethod = typeof(Humanoid).GetMethod("GetLeftItem", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);

		internal static bool IsKnifeInHand(Player player)
		{
			if ((Object)(object)player == (Object)null)
			{
				return false;
			}
			if (!IsKnife(GetHandItem(player, GetRightItemMethod)))
			{
				return IsKnife(GetHandItem(player, GetLeftItemMethod));
			}
			return true;
		}

		internal static bool IsKnifeEquipped(Player player)
		{
			if ((Object)(object)player == (Object)null)
			{
				return false;
			}
			if (IsKnife(GetHandItem(player, GetRightItemMethod)) || IsKnife(GetHandItem(player, GetLeftItemMethod)))
			{
				return true;
			}
			if (((Humanoid)player).GetInventory() == null)
			{
				return false;
			}
			foreach (ItemData equippedItem in ((Humanoid)player).GetInventory().GetEquippedItems())
			{
				if (IsKnife(equippedItem))
				{
					return true;
				}
			}
			return false;
		}

		private static ItemData GetHandItem(Player player, MethodInfo method)
		{
			if (method == null)
			{
				return null;
			}
			object? obj = method.Invoke(player, null);
			return (ItemData)((obj is ItemData) ? obj : null);
		}

		internal static bool IsKnife(ItemData item)
		{
			if (item == null)
			{
				return false;
			}
			if (item.m_shared?.m_name == "$FF_FletchersKnife")
			{
				return true;
			}
			if ((Object)(object)item.m_dropPrefab == (Object)null)
			{
				return false;
			}
			return ArrowAssemblyRegistry.IsKnifePrefab(((Object)item.m_dropPrefab).name);
		}
	}
	internal static class FletchLegacyCleanup
	{
		private static readonly int LegacyContainerPrefabHash = ModConstants.LegacyContainerPrefabHash;

		private static readonly int LegacyUnknownPrefabHash = 555343901;

		private static bool fullPurgeCompleted;

		private static readonly MethodInfo HandleDestroyedZdoMethod = AccessTools.Method(typeof(ZDOMan), "HandleDestroyedZDO", (Type[])null, (Type[])null);

		internal static void RunAfterWorldZdosLoaded()
		{
			fullPurgeCompleted = false;
			Run(forceFullPurge: true);
		}

		internal static void Run(bool forceFullPurge = false)
		{
			SanitizeNullZNetViews();
			if (!forceFullPurge && fullPurgeCompleted)
			{
				return;
			}
			int found;
			int remaining;
			int num = PurgeLegacyZdosFromWorldSave(out found, out remaining);
			int num2 = PurgeRuntimeInstances();
			int num3 = PurgeNamedObjects();
			int num4 = SanitizeNullZNetViews();
			if (forceFullPurge || num > 0 || num2 > 0 || num3 > 0)
			{
				fullPurgeCompleted = true;
			}
			ManualLogSource log = FletchersForgePlugin.Log;
			if (log != null)
			{
				log.LogInfo((object)($"Legacy bench cleanup: found {found} ZDO(s), removed {num} from world save, " + $"{remaining} remain in memory, {num2} scene view(s) cleared, {num3} named object(s) destroyed. " + $"Tracked hashes: {LegacyContainerPrefabHash}, {LegacyUnknownPrefabHash}. " + $"IsServer={(Object)(object)ZNet.instance != (Object)null && ZNet.instance.IsServer()}."));
			}
			if (found == 0)
			{
				ManualLogSource log2 = FletchersForgePlugin.Log;
				if (log2 != null)
				{
					log2.LogInfo((object)"No legacy bench ZDOs in world save — phantom bench cleanup is complete for this world.");
				}
			}
			if (num > 0)
			{
				ManualLogSource log3 = FletchersForgePlugin.Log;
				if (log3 != null)
				{
					log3.LogInfo((object)"Run console command 'save' to persist ZDO removal.");
				}
			}
			else if (found > 0)
			{
				ManualLogSource log4 = FletchersForgePlugin.Log;
				if (log4 != null)
				{
					log4.LogWarning((object)"Legacy bench ZDO(s) were found but could not be removed. Load as world host and try fletcher.cleanup again.");
				}
			}
			if (remaining > 0)
			{
				ManualLogSource log5 = FletchersForgePlugin.Log;
				if (log5 != null)
				{
					log5.LogWarning((object)$"{remaining} legacy bench ZDO(s) still in memory after cleanup.");
				}
			}
			if (num4 > 0)
			{
				ManualLogSource log6 = FletchersForgePlugin.Log;
				if (log6 != null)
				{
					log6.LogInfo((object)$"Removed {num4} stale ZNetView entries from ZNetScene.");
				}
			}
		}

		internal static int SanitizeNullZNetViews()
		{
			if ((Object)(object)ZNetScene.instance == (Object)null)
			{
				return 0;
			}
			Dictionary<ZDO, ZNetView> value = Traverse.Create((object)ZNetScene.instance).Field<Dictionary<ZDO, ZNetView>>("m_instances").Value;
			if (value == null)
			{
				return 0;
			}
			List<ZDO> list = new List<ZDO>();
			foreach (KeyValuePair<ZDO, ZNetView> item in value)
			{
				if (item.Key == null || !IsLiveZNetView(item.Value))
				{
					list.Add(item.Key);
				}
			}
			foreach (ZDO item2 in list)
			{
				if (item2 != null)
				{
					value.Remove(item2);
				}
			}
			return list.Count;
		}

		internal static bool IsLiveZNetView(ZNetView view)
		{
			if ((Object)(object)view == (Object)null)
			{
				return false;
			}
			try
			{
				return (Object)(object)((Component)view).gameObject != (Object)null;
			}
			catch (NullReferenceException)
			{
				return false;
			}
		}

		private static int PurgeLegacyZdosFromWorldSave(out int found, out int remaining)
		{
			found = 0;
			remaining = 0;
			if (ZDOMan.instance == null)
			{
				return 0;
			}
			HashSet<ZDO> hashSet = new HashSet<ZDO>();
			CollectZdosByPrefabName("FF_FletchContainer", hashSet);
			CollectZdosByPrefabHash(hashSet);
			found = hashSet.Count;
			int num = 0;
			foreach (ZDO item in hashSet)
			{
				if (ForceDestroyZdo(item))
				{
					num++;
				}
			}
			remaining = CountLegacyZdos();
			return num;
		}

		private static int CountLegacyZdos()
		{
			HashSet<ZDO> hashSet = new HashSet<ZDO>();
			CollectZdosByPrefabName("FF_FletchContainer", hashSet);
			CollectZdosByPrefabHash(hashSet);
			return hashSet.Count;
		}

		private static void CollectZdosByPrefabName(string prefabName, HashSet<ZDO> output)
		{
			if (ZDOMan.instance == null || string.IsNullOrEmpty(prefabName))
			{
				return;
			}
			List<ZDO> list = new List<ZDO>();
			int num = 0;
			while (!ZDOMan.instance.GetAllZDOsWithPrefabIterative(prefabName, list, ref num))
			{
				foreach (ZDO item in list)
				{
					if (item != null)
					{
						output.Add(item);
					}
				}
				list.Clear();
			}
			foreach (ZDO item2 in list)
			{
				if (item2 != null)
				{
					output.Add(item2);
				}
			}
		}

		private static void CollectZdosByPrefabHash(HashSet<ZDO> output)
		{
			foreach (ZDO item in EnumerateAllZdos())
			{
				if (item != null)
				{
					int prefab = item.GetPrefab();
					if (prefab == LegacyContainerPrefabHash || prefab == LegacyUnknownPrefabHash)
					{
						output.Add(item);
					}
				}
			}
		}

		private static IEnumerable<ZDO> EnumerateAllZdos()
		{
			if (ZDOMan.instance == null)
			{
				return new List<ZDO>();
			}
			HashSet<ZDO> seen = new HashSet<ZDO>();
			List<ZDO> list = new List<ZDO>();
			Traverse val = Traverse.Create((object)ZDOMan.instance);
			if ((val.Field("m_objectsByID").GetValue() ?? val.Field("m_objectsById").GetValue()) is IDictionary dictionary)
			{
				foreach (object value in dictionary.Values)
				{
					AddUniqueZdo(list, seen, (ZDO)((value is ZDO) ? value : null));
				}
			}
			else
			{
				ManualLogSource log = FletchersForgePlugin.Log;
				if (log != null)
				{
					log.LogWarning((object)"Legacy cleanup could not read ZDOMan m_objectsByID.");
				}
			}
			if (val.Field("m_objectsByOutsideSector").GetValue() is IDictionary dictionary2)
			{
				foreach (object value2 in dictionary2.Values)
				{
					CollectZdosFromBucket(list, seen, value2);
				}
			}
			if (val.Field("m_objectsBySector").GetValue() is List<ZDO>[] array)
			{
				List<ZDO>[] array2 = array;
				foreach (List<ZDO> bucket in array2)
				{
					CollectZdosFromBucket(list, seen, bucket);
				}
			}
			return list;
		}

		private static void CollectZdosFromBucket(List<ZDO> all, HashSet<ZDO> seen, object bucket)
		{
			if (!(bucket is List<ZDO> list))
			{
				return;
			}
			foreach (ZDO item in list)
			{
				AddUniqueZdo(all, seen, item);
			}
		}

		private static void AddUniqueZdo(List<ZDO> all, HashSet<ZDO> seen, ZDO zdo)
		{
			if (zdo != null && !seen.Contains(zdo))
			{
				seen.Add(zdo);
				all.Add(zdo);
			}
		}

		private static int PurgeRuntimeInstances()
		{
			if ((Object)(object)ZNetScene.instance == (Object)null)
			{
				return 0;
			}
			Dictionary<ZDO, ZNetView> value = Traverse.Create((object)ZNetScene.instance).Field<Dictionary<ZDO, ZNetView>>("m_instances").Value;
			if (value == null)
			{
				return 0;
			}
			int num = 0;
			List<ZDO> list = new List<ZDO>();
			foreach (KeyValuePair<ZDO, ZNetView> item in value)
			{
				ZDO key = item.Key;
				ZNetView value2 = item.Value;
				if ((Object)(object)value2 == (Object)null || (Object)(object)((Component)value2).gameObject == (Object)null)
				{
					if (key != null)
					{
						list.Add(key);
					}
					num++;
				}
				else if (key != null && (key.GetPrefab() == LegacyContainerPrefabHash || key.GetPrefab() == LegacyUnknownPrefabHash))
				{
					Object.Destroy((Object)(object)((Component)value2).gameObject);
					list.Add(key);
					num++;
				}
			}
			foreach (ZDO item2 in list)
			{
				value.Remove(item2);
			}
			return num;
		}

		private static int PurgeNamedObjects()
		{
			int num = 0;
			GameObject[] array = Resources.FindObjectsOfTypeAll<GameObject>();
			foreach (GameObject val in array)
			{
				if (!((Object)(object)val == (Object)null))
				{
					string name = ((Object)val).name;
					if (name == "FF_FletchContainer" || name == "FF_FletchWorkbenchRuntime")
					{
						Object.Destroy((Object)(object)val);
						num++;
					}
				}
			}
			return num;
		}

		private static bool ForceDestroyZdo(ZDO zdo)
		{
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e2: Unknown result type (might be due to invalid IL or missing references)
			//IL_0097: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ae: Unknown result type (might be due to invalid IL or missing references)
			if (zdo == null || ZDOMan.instance == null)
			{
				return false;
			}
			if ((Object)(object)ZNetScene.instance != (Object)null)
			{
				GameObject val = ZNetScene.instance.FindInstance(zdo.m_uid);
				if ((Object)(object)val != (Object)null)
				{
					Object.Destroy((Object)(object)val);
				}
				Traverse.Create((object)ZNetScene.instance).Field<Dictionary<ZDO, ZNetView>>("m_instances").Value?.Remove(zdo);
			}
			if ((Object)(object)ZNet.instance != (Object)null && ZNet.instance.IsServer() && HandleDestroyedZdoMethod != null)
			{
				HandleDestroyedZdoMethod.Invoke(ZDOMan.instance, new object[1] { zdo.m_uid });
				return ZDOMan.instance.GetZDO(zdo.m_uid) == null;
			}
			if (zdo.IsOwner())
			{
				ZDOMan.instance.DestroyZDO(zdo);
				return true;
			}
			ManualLogSource log = FletchersForgePlugin.Log;
			if (log != null)
			{
				log.LogWarning((object)$"Could not remove legacy bench ZDO {zdo.m_uid} (not owner; load world as host).");
			}
			return false;
		}
	}
	internal static class FletchOperations
	{
		internal static bool TryReforge(Player player, Inventory inv, out string message)
		{
			message = string.Empty;
			if ((Object)(object)player == (Object)null || inv == null)
			{
				message = "No workbench.";
				return false;
			}
			ItemData itemAt = inv.GetItemAt(0, 0);
			ItemData itemAt2 = inv.GetItemAt(1, 0);
			if (itemAt == null)
			{
				message = "Place a shaft or arrow in the first slot.";
				return false;
			}
			string prefabName = (((Object)(object)itemAt.m_dropPrefab != (Object)null) ? ((Object)itemAt.m_dropPrefab).name : string.Empty);
			if (ArrowAssemblyRegistry.IsArrowPrefab(prefabName))
			{
				return TryRehead(player, inv, itemAt, itemAt2, out message);
			}
			if (ArrowAssemblyRegistry.IsShaftPrefab(prefabName))
			{
				return TryAssemble(player, inv, itemAt, itemAt2, out message);
			}
			message = "Invalid item in first slot.";
			return false;
		}

		internal static bool TrySplit(Player player, Inventory inv, out string message)
		{
			message = string.Empty;
			if ((Object)(object)player == (Object)null || inv == null)
			{
				message = "No workbench.";
				return false;
			}
			ItemData itemAt = inv.GetItemAt(0, 0);
			ItemData itemAt2 = inv.GetItemAt(1, 0);
			if (itemAt == null)
			{
				message = "Place arrows in the first slot.";
				return false;
			}
			if (itemAt2 != null)
			{
				message = "Clear the head slot before splitting.";
				return false;
			}
			if (!ArrowAssemblyRegistry.TryGetParts(((Object)(object)itemAt.m_dropPrefab != (Object)null) ? ((Object)itemAt.m_dropPrefab).name : string.Empty, out var shaftPrefab, out var headPrefab))
			{
				message = "That item cannot be split.";
				return false;
			}
			int num = Mathf.Min(20, itemAt.m_stack);
			if (!TryGiveComponents(player, shaftPrefab, headPrefab, num))
			{
				message = "Inventory full.";
				return false;
			}
			itemAt.m_stack -= num;
			if (itemAt.m_stack <= 0)
			{
				inv.RemoveItem(itemAt);
			}
			message = $"Split {num} arrows.";
			return true;
		}

		private static bool TryAssemble(Player player, Inventory inv, ItemData shaftItem, ItemData headItem, out string message)
		{
			message = string.Empty;
			string name = ((Object)shaftItem.m_dropPrefab).name;
			string headPrefab = (((Object)(object)headItem?.m_dropPrefab != (Object)null) ? ((Object)headItem.m_dropPrefab).name : null);
			if (!ArrowAssemblyRegistry.TryGetArrow(name, headPrefab, out var arrowPrefab))
			{
				if (headItem == null)
				{
					message = "Place an arrowhead in the second slot.";
				}
				else
				{
					message = "Those parts do not match.";
				}
				return false;
			}
			int num = Mathf.Min(20, shaftItem.m_stack);
			if (headItem != null)
			{
				num = Mathf.Min(num, headItem.m_stack);
			}
			if (!GiveArrows(player, arrowPrefab, num))
			{
				message = "Inventory full.";
				return false;
			}
			shaftItem.m_stack -= num;
			if (shaftItem.m_stack <= 0)
			{
				inv.RemoveItem(shaftItem);
			}
			if (headItem != null)
			{
				headItem.m_stack -= num;
				if (headItem.m_stack <= 0)
				{
					inv.RemoveItem(headItem);
				}
			}
			message = $"Reforged {num} arrows.";
			return true;
		}

		private static bool TryRehead(Player player, Inventory inv, ItemData arrowItem, ItemData newHeadItem, out string message)
		{
			message = string.Empty;
			if (newHeadItem == null)
			{
				message = "Place a new arrowhead in the second slot.";
				return false;
			}
			if (!ArrowAssemblyRegistry.TryGetParts(((Object)arrowItem.m_dropPrefab).name, out var shaftPrefab, out var headPrefab))
			{
				message = "That arrow cannot be reforged.";
				return false;
			}
			string name = ((Object)newHeadItem.m_dropPrefab).name;
			if (!ArrowAssemblyRegistry.TryGetArrow(shaftPrefab, name, out var arrowPrefab))
			{
				message = "That head does not fit this arrow.";
				return false;
			}
			int num = Mathf.Min(new int[3] { 20, arrowItem.m_stack, newHeadItem.m_stack });
			if (!GiveArrows(player, arrowPrefab, num))
			{
				message = "Inventory full.";
				return false;
			}
			if (!string.IsNullOrEmpty(headPrefab) && !GiveComponents(player, headPrefab, num))
			{
				message = "Inventory full.";
				return false;
			}
			arrowItem.m_stack -= num;
			newHeadItem.m_stack -= num;
			if (arrowItem.m_stack <= 0)
			{
				inv.RemoveItem(arrowItem);
			}
			if (newHeadItem.m_stack <= 0)
			{
				inv.RemoveItem(newHeadItem);
			}
			message = $"Reforged {num} arrows.";
			return true;
		}

		private static bool TryGiveComponents(Player player, string shaftPrefab, string headPrefab, int count)
		{
			if (!GiveComponents(player, shaftPrefab, count))
			{
				return false;
			}
			if (!string.IsNullOrEmpty(headPrefab) && !GiveComponents(player, headPrefab, count))
			{
				return false;
			}
			return true;
		}

		private static bool GiveComponents(Player player, string prefabName, int count)
		{
			GameObject itemPrefab = ObjectDB.instance.GetItemPrefab(prefabName);
			if ((Object)(object)itemPrefab == (Object)null)
			{
				return false;
			}
			return ((Humanoid)player).GetInventory().AddItem(itemPrefab, count);
		}

		private static bool GiveArrows(Player player, string arrowPrefabName, int count)
		{
			GameObject itemPrefab = ObjectDB.instance.GetItemPrefab(arrowPrefabName);
			if ((Object)(object)itemPrefab == (Object)null)
			{
				ManualLogSource log = FletchersForgePlugin.Log;
				if (log != null)
				{
					log.LogError((object)("Arrow prefab missing: " + arrowPrefabName));
				}
				return false;
			}
			return ((Humanoid)player).GetInventory().AddItem(itemPrefab, count);
		}
	}
	internal static class FletchSlotRules
	{
		internal static bool CanAccept(int gridX, int gridY, string prefabName)
		{
			if (string.IsNullOrEmpty(prefabName))
			{
				return true;
			}
			if (gridX == 0 && gridY == 0)
			{
				if (!ArrowAssemblyRegistry.IsShaftPrefab(prefabName))
				{
					return ArrowAssemblyRegistry.IsArrowPrefab(prefabName);
				}
				return true;
			}
			if (gridX == 1 && gridY == 0)
			{
				return ArrowAssemblyRegistry.IsHeadPrefab(prefabName);
			}
			return false;
		}
	}
	internal sealed class FletchUiBehaviour : MonoBehaviour
	{
		private void Update()
		{
			QuiverTombstoneDump.ProcessDeferredRestore();
			QuiverTombstoneDump.ProcessDeferredEquip();
			QuiverHud.Update();
			QuiverBackVisual.UpdateAll();
		}

		private void OnGUI()
		{
			FletchUiService.DrawBenchOverlay();
		}
	}
	internal static class FletchUiService
	{
		private sealed class RectState
		{
			private RectTransform rt;

			private Vector2 anchored;

			private Vector2 size;

			private Vector2 anchorMin;

			private Vector2 anchorMax;

			private Vector2 pivot;

			private Vector3 scale;

			private bool saved;

			public void Capture(RectTransform target)
			{
				//IL_001f: Unknown result type (might be due to invalid IL or missing references)
				//IL_0024: Unknown result type (might be due to invalid IL or missing references)
				//IL_002b: Unknown result type (might be due to invalid IL or missing references)
				//IL_0030: Unknown result type (might be due to invalid IL or missing references)
				//IL_0037: Unknown result type (might be due to invalid IL or missing references)
				//IL_003c: Unknown result type (might be due to invalid IL or missing references)
				//IL_0043: Unknown result type (might be due to invalid IL or missing references)
				//IL_0048: Unknown result type (might be due to invalid IL or missing references)
				//IL_004f: Unknown result type (might be due to invalid IL or missing references)
				//IL_0054: Unknown result type (might be due to invalid IL or missing references)
				//IL_005b: Unknown result type (might be due to invalid IL or missing references)
				//IL_0060: Unknown result type (might be due to invalid IL or missing references)
				rt = target;
				saved = (Object)(object)target != (Object)null;
				if (saved)
				{
					anchored = target.anchoredPosition;
					size = target.sizeDelta;
					anchorMin = target.anchorMin;
					anchorMax = target.anchorMax;
					pivot = target.pivot;
					scale = ((Transform)target).localScale;
				}
			}

			public void Restore()
			{
				//IL_001e: Unknown result type (might be due to invalid IL or missing references)
				//IL_002f: Unknown result type (might be due to invalid IL or missing references)
				//IL_0040: Unknown result type (might be due to invalid IL or missing references)
				//IL_0051: Unknown result type (might be due to invalid IL or missing references)
				//IL_0062: Unknown result type (might be due to invalid IL or missing references)
				//IL_0073: Unknown result type (might be due to invalid IL or missing references)
				if (saved && !((Object)(object)rt == (Object)null))
				{
					rt.anchorMin = anchorMin;
					rt.anchorMax = anchorMax;
					rt.pivot = pivot;
					rt.sizeDelta = size;
					rt.anchoredPosition = anchored;
					((Transform)rt).localScale = scale;
				}
			}
		}

		private static bool benchUiOpen;

		private static string statusMessage = string.Empty;

		private static float statusUntil;

		private static bool benchPanelSaved;

		private static readonly RectState panelState = new RectState();

		private static readonly RectState gridState = new RectState();

		private static readonly RectState gridRootState = new RectState();

		private static readonly RectState takeAllState = new RectState();

		private static readonly RectState stackAllState = new RectState();

		internal static bool IsBenchUiOpen => benchUiOpen;

		internal static bool IsFletchContainerOpen
		{
			get
			{
				if (benchUiOpen && (Object)(object)InventoryGui.instance != (Object)null)
				{
					return InventoryGui.IsVisible();
				}
				return false;
			}
		}

		internal static bool IsFletchInventory(Inventory inventory)
		{
			Inventory inventory2 = FletchBenchInventory.Inventory;
			if (inventory2 != null)
			{
				return inventory2 == inventory;
			}
			return false;
		}

		internal static void Open(Player player)
		{
			if (!FletchersKnifeHelper.IsKnifeInHand(player) || IsFletchContainerOpen)
			{
				return;
			}
			FletchBenchInventory.Initialize();
			if (FletchBenchInventory.Inventory == null)
			{
				ManualLogSource log = FletchersForgePlugin.Log;
				if (log != null)
				{
					log.LogError((object)"Virtual Fletcher bench is not ready.");
				}
				return;
			}
			if ((Object)(object)InventoryGui.instance == (Object)null)
			{
				ManualLogSource log2 = FletchersForgePlugin.Log;
				if (log2 != null)
				{
					log2.LogError((object)"InventoryGui not available.");
				}
				return;
			}
			InventoryGui instance = InventoryGui.instance;
			FletchBenchInventory.ClearSlots();
			if (!InventoryGui.IsVisible())
			{
				instance.Show((Container)null, 1);
			}
			InventoryGuiAccess.SetHiddenFrames(instance, 0);
			InventoryGuiAccess.SetActiveGroup(instance, 1);
			InventoryGuiAccess.SetFirstContainerUpdate(instance, value: true);
			benchUiOpen = true;
			ApplyCompactBenchPanel(instance);
			FletchBenchButtonUi.Update(instance, benchOpen: true);
			ManualLogSource log3 = FletchersForgePlugin.Log;
			if (log3 != null)
			{
				log3.LogInfo((object)"Opened virtual Fletcher bench UI.");
			}
		}

		internal static void NotifyGuiClosed()
		{
			benchUiOpen = false;
			FletchBenchInventory.ClearSlots();
			RestoreBenchPanel();
		}

		internal static void Close()
		{
			if (benchUiOpen || IsFletchContainerOpen)
			{
				InventoryGui instance = InventoryGui.instance;
				benchUiOpen = false;
				FletchBenchInventory.ClearSlots();
				RestoreBenchPanel();
				if ((Object)(object)instance?.m_container != (Object)null)
				{
					((Component)instance.m_container).gameObject.SetActive(false);
				}
				FletchBenchButtonUi.Update(instance, benchOpen: false);
			}
		}

		internal static void ApplyCompactBenchPanel(InventoryGui gui)
		{
			//IL_0125: 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_012e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0133: Unknown result type (might be due to invalid IL or missing references)
			//IL_0137: Unknown result type (might be due to invalid IL or missing references)
			//IL_013e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0148: 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)
			RectTransform val = gui?.m_container;
			InventoryGrid val2 = ((gui != null) ? gui.ContainerGrid : null);
			if (!((Object)(object)val == (Object)null) && !((Object)(object)val2 == (Object)null))
			{
				Transform transform = ((Component)val2).transform;
				RectTransform target = (RectTransform)(object)((transform is RectTransform) ? transform : null);
				if (!benchPanelSaved)
				{
					panelState.Capture(val);
					gridState.Capture(target);
					gridRootState.Capture(val2.m_gridRoot);
					takeAllState.Capture((RectTransform)(((Object)(object)gui.m_takeAllButton != (Object)null) ? /*isinst with value type is only supported in some contexts*/: null));
					stackAllState.Capture((RectTransform)(((Object)(object)gui.m_stackAllButton != (Object)null) ? /*isinst with value type is only supported in some contexts*/: null));
					benchPanelSaved = true;
				}
				panelState.Restore();
				gridState.Restore();
				gridRootState.Restore();
				takeAllState.Restore();
				stackAllState.Restore();
				float num = ((val2.m_elementSpace > 1f) ? val2.m_elementSpace : 70f);
				float num2 = num * 6.2f;
				float num3 = num * 3.05f;
				Rect rect = val.rect;
				Vector2 size = ((Rect)(ref rect)).size;
				val.sizeDelta += new Vector2(num2 - size.x, num3 - size.y);
				PlaceNativeButtons(gui, num);
				PlaceSlotsBetweenHeaderAndButtons(val, val2, num);
				ClearPlayerInventoryOverlap(gui, val);
			}
		}

		private static void PlaceNativeButtons(InventoryGui gui, float space)
		{
			//IL_0048: 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_0072: Unknown result type (might be due to invalid IL or missing references)
			//IL_007f: 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_00d4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f7: Unknown result type (might be due to invalid IL or missing references)
			float num = Mathf.Max(8f, space * 0.12f);
			RectTransform val = (RectTransform)(((Object)(object)gui.m_takeAllButton != (Object)null) ? /*isinst with value type is only supported in some contexts*/: null);
			if ((Object)(object)val != (Object)null)
			{
				val.anchorMin = new Vector2(0f, 0f);
				val.anchorMax = new Vector2(0f, 0f);
				val.pivot = new Vector2(0f, 0f);
				val.anchoredPosition = new Vector2(num, num);
			}
			RectTransform val2 = (RectTransform)(((Object)(object)gui.m_stackAllButton != (Object)null) ? /*isinst with value type is only supported in some contexts*/: null);
			if ((Object)(object)val2 != (Object)null)
			{
				val2.anchorMin = new Vector2(1f, 0f);
				val2.anchorMax = new Vector2(1f, 0f);
				val2.pivot = new Vector2(1f, 0f);
				val2.anchoredPosition = new Vector2(0f - num, num);
			}
		}

		private static void PlaceSlotsBetweenHeaderAndButtons(RectTransform panel, InventoryGrid grid, float space)
		{
			//IL_0155: Unknown result type (might be due to invalid IL or missing references)
			//IL_020d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0212: Unknown result type (might be due to invalid IL or missing references)
			//IL_0214: Unknown result type (might be due to invalid IL or missing references)
			if (!(Traverse.Create((object)grid).Field("m_elements").GetValue() is IList { Count: not 0 } list))
			{
				return;
			}
			Vector3[] array = (Vector3[])(object)new Vector3[4];
			float num = float.MaxValue;
			float num2 = float.MinValue;
			float num3 = float.MaxValue;
			float num4 = float.MinValue;
			int num5 = 0;
			foreach (object item in list)
			{
				RectTransform val = null;
				InventoryElement val2 = (InventoryElement)((item is InventoryElement) ? item : null);
				if (val2 != null)
				{
					Transform transform = ((Component)val2).transform;
					val = (RectTransform)(object)((transform is RectTransform) ? transform : null);
				}
				else
				{
					GameObject value = Traverse.Create(item).Field("m_go").GetValue<GameObject>();
					val = (RectTransform)(((Object)(object)value != (Object)null) ? /*isinst with value type is only supported in some contexts*/: null);
				}
				if (!((Object)(object)val == (Object)null))
				{
					val.GetWorldCorners(array);
					num = Mathf.Min(num, array[0].x);
					num2 = Mathf.Max(num2, array[2].x);
					num3 = Mathf.Min(num3, array[0].y);
					num4 = Mathf.Max(num4, array[1].y);
					num5++;
				}
			}
			if (num5 != 0)
			{
				Vector3[] array2 = (Vector3[])(object)new Vector3[4];
				panel.GetWorldCorners(array2);
				float num6 = Mathf.Abs(((Transform)panel).lossyScale.y);
				float num7 = space * num6 * 0.55f;
				float num8 = space * num6 * 0.95f;
				float num9 = (array2[0].x + array2[3].x) * 0.5f;
				float num10 = (array2[1].y - num7 + (array2[0].y + num8)) * 0.5f;
				Vector3 val3 = default(Vector3);
				((Vector3)(ref val3))..ctor(num9 - (num + num2) * 0.5f, num10 - (num3 + num4) * 0.5f, 0f);
				object obj = (((Object)(object)grid.m_gridRoot != (Object)null) ? ((object)grid.m_gridRoot) : ((object)((Component)grid).transform));
				((Transform)obj).position = ((Transform)obj).position + val3;
			}
		}

		private static void ClearPlayerInventoryOverlap(InventoryGui gui, RectTransform panel)
		{
			//IL_0060: Unknown result type (might be due to invalid IL or missing references)
			//IL_0071: Unknown result type (might be due to invalid IL or missing references)
			//IL_0076: Unknown result type (might be due to invalid IL or missing references)
			RectTransform player = gui.m_player;
			if (!((Object)(object)player == (Object)null) && !((Object)(object)panel == (Object)null))
			{
				Vector3[] array = (Vector3[])(object)new Vector3[4];
				Vector3[] array2 = (Vector3[])(object)new Vector3[4];
				player.GetWorldCorners(array);
				panel.GetWorldCorners(array2);
				float num = array2[1].y - (array[0].y - 12f);
				if (num > 0.5f)
				{
					((Transform)panel).position = ((Transform)panel).position + new Vector3(0f, 0f - num, 0f);
				}
			}
		}

		private static void RestoreBenchPanel()
		{
			if (benchPanelSaved)
			{
				panelState.Restore();
				gridState.Restore();
				gridRootState.Restore();
				takeAllState.Restore();
				stackAllState.Restore();
				benchPanelSaved = false;
			}
		}

		internal static void TryReforge(Player player)
		{
			if (IsFletchContainerOpen && FletchBenchInventory.Inventory != null)
			{
				FletchOperations.TryReforge(player, FletchBenchInventory.Inventory, out var message);
				SetStatus(message);
			}
		}

		internal static void TrySplit(Player player)
		{
			if (IsFletchContainerOpen && FletchBenchInventory.Inventory != null)
			{
				FletchOperations.TrySplit(player, FletchBenchInventory.Inventory, out var message);
				SetStatus(message);
			}
		}

		internal static void DrawBenchOverlay()
		{
			//IL_005d: Unknown result type (might be due to invalid IL or missing references)
			if (IsFletchContainerOpen && TryGetContainerScreenRect(out var rect) && Time.time < statusUntil && !string.IsNullOrEmpty(statusMessage))
			{
				GUI.Label(new Rect(((Rect)(ref rect)).x + 12f, ((Rect)(ref rect)).y + ((Rect)(ref rect)).height - 52f, ((Rect)(ref rect)).width - 24f, 20f), statusMessage);
			}
		}

		internal static void SetStatus(string message)
		{
			statusMessage = message;
			statusUntil = Time.time + 3f;
		}

		private static bool TryGetContainerScreenRect(out Rect rect)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_005a: Unknown result type (might be due to invalid IL or missing references)
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0064: Unknown result type (might be due to invalid IL or missing references)
			//IL_0069: Unknown result type (might be due to invalid IL or missing references)
			//IL_006e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0073: Unknown result type (might be due to invalid IL or missing references)
			//IL_0075: Unknown result type (might be due to invalid IL or missing references)
			//IL_0084: Unknown result type (might be due to invalid IL or missing references)
			//IL_008e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0095: Unknown result type (might be due to invalid IL or missing references)
			//IL_009f: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00be: Unknown result type (might be due to invalid IL or missing references)
			//IL_0049: Unknown result type (might be due to invalid IL or missing references)
			rect = default(Rect);
			InventoryGui instance = InventoryGui.instance;
			if ((Object)(object)instance?.m_container == (Object)null)
			{
				return false;
			}
			RectTransform container = instance.m_container;
			Vector3[] array = (Vector3[])(object)new Vector3[4];
			container.GetWorldCorners(array);
			Canvas componentInParent = ((Component)container).GetComponentInParent<Canvas>();
			Camera val = null;
			if ((Object)(object)componentInParent != (Object)null && (int)componentInParent.renderMode != 0)
			{
				val = componentInParent.worldCamera;
			}
			Vector2 val2 = RectTransformUtility.WorldToScreenPoint(val, array[0]);
			Vector2 val3 = RectTransformUtility.WorldToScreenPoint(val, array[2]);
			float x = val2.x;
			float num = (float)Screen.height - val3.y;
			float num2 = val3.x - val2.x;
			float num3 = val3.y - val2.y;
			rect = new Rect(x, num, num2, num3);
			if (num2 > 0f)
			{
				return num3 > 0f;
			}
			return false;
		}
	}
	internal static class HeadIconAssets
	{
		private const string IconFolderName = "Icons";

		private const string EmbeddedIconFolder = "EmbeddedIcons";

		private static readonly Dictionary<string, Sprite> Cache = new Dictionary<string, Sprite>();

		private static readonly Dictionary<string, string> SourceCache = new Dictionary<string, string>();

		private static MethodInfo imageConversionLoadImage;

		private static bool loggedEmbeddedResources;

		internal static void ClearCache()
		{
			Cache.Clear();
			SourceCache.Clear();
		}

		internal static bool TryApplyCustomHeadIcon(CustomItem item)
		{
			if ((Object)(object)((item != null) ? item.ItemDrop : null) == (Object)null)
			{
				return false;
			}
			string text = (((Object)(object)item.ItemPrefab != (Object)null) ? ((Object)item.ItemPrefab).name : ((Object)((Component)item.ItemDrop).gameObject).name);
			Sprite orLoad = GetOrLoad(text);
			if ((Object)(object)orLoad == (Object)null)
			{
				return false;
			}
			item.ItemDrop.m_itemData.m_shared.m_icons = (Sprite[])(object)new Sprite[1] { orLoad };
			IconRigUtility.SyncIconsToObjectDb(text, item.ItemDrop.m_itemData.m_shared.m_icons);
			string text2 = "custom";
			if (SourceCache.TryGetValue(text, out var value))
			{
				text2 = value;
			}
			ManualLogSource log = FletchersForgePlugin.Log;
			if (log != null)
			{
				log.LogInfo((object)$"Applied {text2} icon for {text} ({((Texture)orLoad.texture).width}x{((Texture)orLoad.texture).height}).");
			}
			return true;
		}

		internal static string GetIconsFolderPath()
		{
			return Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location) ?? Paths.PluginPath, "Icons");
		}

		private static Sprite GetOrLoad(string prefabName)
		{
			if (Cache.TryGetValue(prefabName, out var value))
			{
				return value;
			}
			Sprite val = null;
			string value2 = "none";
			if (ModConfig.UseEmbeddedHeadIcons.Value)
			{
				val = LoadEmbeddedSprite(prefabName);
				if ((Object)(object)val != (Object)null)
				{
					value2 = "embedded DLL";
				}
			}
			if ((Object)(object)val == (Object)null && ModConfig.AllowExternalHeadIconOverrides.Value)
			{
				val = LoadFilesystemSprite(prefabName);
				if ((Object)(object)val != (Object)null)
				{
					value2 = "external Icons folder";
				}
			}
			Cache[prefabName] = val;
			SourceCache[prefabName] = value2;
			return val;
		}

		private static Sprite LoadEmbeddedSprite(string prefabName)
		{
			Assembly assembly = typeof(FletchersForgePlugin).Assembly;
			string value = prefabName + ".png";
			string text = null;
			string[] manifestResourceNames = assembly.GetManifestResourceNames();
			foreach (string text2 in manifestResourceNames)
			{
				if (text2.EndsWith(value, StringComparison.OrdinalIgnoreCase))
				{
					text = text2;
					break;
				}
			}
			if (text == null)
			{
				if (!loggedEmbeddedResources)
				{
					loggedEmbeddedResources = true;
					ManualLogSource log = FletchersForgePlugin.Log;
					if (log != null)
					{
						log.LogInfo((object)("Embedded icon resources: " + string.Join(", ", assembly.GetManifestResourceNames())));
					}
				}
				return null;
			}
			using Stream stream = assembly.GetManifestResourceStream(text);
			if (stream == null)
			{
				return null;
			}
			return CreateSpriteFromPng(ReadAllBytes(stream), prefabName);
		}

		private static Sprite LoadFilesystemSprite(string prefabName)
		{
			string text = Path.Combine(GetIconsFolderPath(), prefabName + ".png");
			if (!File.Exists(text))
			{
				return null;
			}
			try
			{
				return CreateSpriteFromPng(File.ReadAllBytes(text), prefabName);
			}
			catch (IOException ex)
			{
				ManualLogSource log = FletchersForgePlugin.Log;
				if (log != null)
				{
					log.LogWarning((object)("Failed to load icon " + text + ": " + ex.Message));
				}
				return null;
			}
		}

		private static Sprite CreateSpriteFromPng(byte[] bytes, string prefabName)
		{
			//IL_0004: Unknown result type (might be due to invalid IL or missing references)
			//IL_000a: Expected O, but got Unknown
			//IL_005c: Unknown result type (might be due to invalid IL or missing references)
			//IL_006b: Unknown result type (might be due to invalid IL or missing references)
			Texture2D val = new Texture2D(2, 2, (TextureFormat)4, false);
			if (!TryLoadPng(val, bytes))
			{
				ManualLogSource log = FletchersForgePlugin.Log;
				if (log != null)
				{
					log.LogWarning((object)("Could not decode PNG for " + prefabName + "."));
				}
				return null;
			}
			((Texture)val).wrapMode = (TextureWrapMode)1;
			((Texture)val).filterMode = (FilterMode)1;
			return Sprite.Create(val, new Rect(0f, 0f, (float)((Texture)val).width, (float)((Texture)val).height), new Vector2(0.5f, 0.5f), 100f, 0u, (SpriteMeshType)0);
		}

		private static byte[] ReadAllBytes(Stream stream)
		{
			using MemoryStream memoryStream = new MemoryStream();
			stream.CopyTo(memoryStream);
			return memoryStream.ToArray();
		}

		private static bool TryLoadPng(Texture2D texture, byte[] bytes)
		{
			MethodInfo methodInfo = GetImageConversionLoadImage();
			if (methodInfo == null)
			{
				ManualLogSource log = FletchersForgePlugin.Log;
				if (log != null)
				{
					log.LogWarning((object)"ImageConversion.LoadImage is unavailable; cannot load PNG icons.");
				}
				return false;
			}
			object[] parameters = ((methodInfo.GetParameters().Length != 3) ? new object[2] { texture, bytes } : new object[3] { texture, bytes, false });
			return (bool)methodInfo.Invoke(null, parameters);
		}

		private static MethodInfo GetImageConversionLoadImage()
		{
			if (imageConversionLoadImage != null)
			{
				return imageConversionLoadImage;
			}
			Type type = Type.GetType("UnityEngine.ImageConversion, UnityEngine.ImageConversionModule");
			if (type == null)
			{
				return null;
			}
			imageConversionLoadImage = type.GetMethod("LoadImage", BindingFlags.Static | BindingFlags.Public, null, new Type[3]
			{
				typeof(Texture2D),
				typeof(byte[]),
				typeof(bool)
			}, null);
			if (imageConversionLoadImage == null)
			{
				imageConversionLoadImage = type.GetMethod("LoadImage", BindingFlags.Static | BindingFlags.Public, null, new Type[2]
				{
					typeof(Texture2D),
					typeof(byte[])
				}, null);
			}
			return imageConversionLoadImage;
		}
	}
	internal static class HeadIconGenerator
	{
		private static readonly Dictionary<string, Color> ArrowTipColors = new Dictionary<string, Color>
		{
			{
				"ArrowFire",
				new Color(0.95f, 0.45f, 0.12f)
			},
			{
				"ArrowFlint",
				new Color(0.55f, 0.52f, 0.48f)
			},
			{
				"ArrowBronze",
				new Color(0.78f, 0.48f, 0.22f)
			},
			{
				"ArrowIron",
				new Color(0.62f, 0.66f, 0.72f)
			},
			{
				"ArrowSilver",
				new Color(0.82f, 0.86f, 0.92f)
			},
			{
				"ArrowObsidian",
				new Color(0.22f, 0.2f, 0.28f)
			},
			{
				"ArrowPoison",
				new Color(0.42f, 0.72f, 0.28f)
			},
			{
				"ArrowFrost",
				new Color(0.45f, 0.78f, 0.95f)
			},
			{
				"ArrowNeedle",
				new Color(0.68f, 0.7f, 0.74f)
			},
			{
				"ArrowCarapace",
				new Color(0.58f, 0.32f, 0.62f)
			},
			{
				"ArrowCharred",
				new Color(0.18f, 0.18f, 0.2f)
			}
		};

		internal static Sprite CreateForArrow(string sourceArrow)
		{
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			if (!ArrowTipColors.TryGetValue(sourceArrow, out var value))
			{
				((Color)(ref value))..ctor(0.65f, 0.65f, 0.65f);
			}
			return CreateArrowheadSprite(value);
		}

		private static Sprite CreateArrowheadSprite(Color tipColor)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Expected O, but got Unknown
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_0041: 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_0148: 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_00ec: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e9: Unknown result type (might be due to invalid IL or missing references)
			Texture2D val = new Texture2D(64, 64, (TextureFormat)4, false);
			Color val2 = default(Color);
			((Color)(ref val2))..ctor(0f, 0f, 0f, 0f);
			Color val3 = default(Color);
			((Color)(ref val3))..ctor(tipColor.r * 0.55f, tipColor.g * 0.55f, tipColor.b * 0.55f, 1f);
			for (int i = 0; i < 64; i++)
			{
				for (int j = 0; j < 64; j++)
				{
					float num = (float)j / 64f;
					float num2 = (float)i / 64f;
					bool flag = num >= 0.38f && num2 >= 0.22f && num <= 0.92f && num2 <= 0.88f && num - 0.38f >= (num2 - 0.22f) * 0.55f;
					bool flag2 = flag && num >= 0.38f && num <= 0.5f;
					val.SetPixel(j, i, flag2 ? val3 : (flag ? tipColor : val2));
				}
			}
			val.Apply();
			((Texture)val).wrapMode = (TextureWrapMode)1;
			((Texture)val).filterMode = (FilterMode)1;
			return Sprite.Create(val, new Rect(0f, 0f, 64f, 64f), new Vector2(0.5f, 0.5f), 100f, 0u, (SpriteMeshType)0);
		}
	}
	internal static class IconRigGuard
	{
		internal static int Depth;

		internal static bool IsActive => Depth > 0;

		internal static void Enter()
		{
			Depth++;
		}

		internal static void Leave()
		{
			if (Depth > 0)
			{
				Depth--;
			}
		}
	}
	internal static class IconRigUtility
	{
		private static readonly string[] HeadNameTokens = new string[17]
		{
			"head", "tip", "flint", "iron", "bronze", "silver", "obsidian", "fire", "poison", "frost",
			"needle", "carapace", "charred", "resin", "stone", "metal", "arrowhead"
		};

		private static readonly string[] ShaftNameTokens = new string[5] { "shaft", "stick", "wood", "body", "arrowwood" };

		private static readonly string[] FeatherNameTokens = new string[3] { "feather", "fletch", "vane" };

		internal static void ApplyShaftIcon(CustomItem item, string sourceArrow, bool ashTint = false)
		{
			GameObject target = BuildShaftIconRig(sourceArrow, ashTint);
			ApplyRenderedIcon(item, target);
		}

		internal static void ApplyHeadIcon(CustomItem item, string sourceArrow)
		{
			GameObject target = BuildHeadIconRig(sourceArrow);
			ApplyRenderedIcon(item, target);
		}

		internal static void ApplyRenderedIcon(CustomItem item, GameObject target)
		{
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)((item != null) ? item.ItemDrop : null) == (Object)null || (Object)(object)target == (Object)null)
			{
				return;
			}
			try
			{
				Sprite val = RenderManager.Instance.Render(target, RenderManager.IsometricRotation);
				if ((Object)(object)val != (Object)null)
				{
					item.ItemDrop.m_itemData.m_shared.m_icons = (Sprite[])(object)new Sprite[1] { val };
					SyncIconsToObjectDb(((Object)item.ItemPrefab).name, item.ItemDrop.m_itemData.m_shared.m_icons);
					return;
				}
				ManualLogSource log = FletchersForgePlugin.Log;
				if (log != null)
				{
					log.LogWarning((object)("Icon render returned null for " + ((Object)target).name + "."));
				}
			}
			catch (Exception ex)
			{
				ManualLogSource log2 = FletchersForgePlugin.Log;
				if (log2 != null)
				{
					log2.LogWarning((object)("Icon render failed for " + ((Object)target).name + ": " + ex.Message));
				}
			}
			finally
			{
				if ((Object)(object)target != (Object)(object)((Component)item.ItemDrop).gameObject)
				{
					Object.Destroy((Object)(object)target);
				}
			}
		}

		internal static bool HasUsableIcons(Sprite[] icons)
		{
			if (icons == null || icons.Length == 0)
			{
				return false;
			}
			foreach (Sprite val in icons)
			{
				if ((Object)(object)val != (Object)null && (Object)(object)val.texture != (Object)null)
				{
					return true;
				}
			}
			return false;
		}

		internal static void ApplyHeadIconFromTip(CustomItem item, string sourceArrow)
		{
			if (HeadIconAssets.TryApplyCustomHeadIcon(item))
			{
				return;
			}
			Sprite val = HeadIconGenerator.CreateForArrow(sourceArrow);
			if ((Object)(object)val != (Object)null)
			{
				item.ItemDrop.m_itemData.m_shared.m_icons = (Sprite[])(object)new Sprite[1] { val };
				SyncIconsToObjectDb(((Object)item.ItemPrefab).name, item.ItemDrop.m_itemData.m_shared.m_icons);
			}
			else if (!ApplyCroppedArrowTipIcon(item, sourceArrow))
			{
				GameObject val2 = BuildHeadIconRig(sourceArrow);
				if ((Object)(object)val2 != (Object)null)
				{
					ApplyRenderedIcon(item, val2);
					SyncIconsToObjectDb(((Object)item.ItemPrefab).name, item.ItemDrop.m_itemData.m_shared.m_icons);
				}
			}
		}

		internal static bool ApplyCroppedArrowTipIcon(CustomItem item, string sourceArrow)
		{
			if ((Object)(object)((item != null) ? item.ItemDrop : null) == (Object)null)
			{
				return false;
			}
			GameObject val = (((Object)(object)ObjectDB.instance != (Object)null) ? ObjectDB.instance.GetItemPrefab(sourceArrow) : PrefabManager.Instance.GetPrefab(sourceArrow));
			ItemDrop val2 = (((Object)(object)val != (Object)null) ? val.GetComponent<ItemDrop>() : null);
			if (val2?.m_itemData?.m_shared?.m_icons == null || val2.m_itemData.m_shared.m_icons.Length == 0)
			{
				ManualLogSource log = FletchersForgePlugin.Log;
				if (log != null)
				{
					log.LogWarning((object)("No arrow icon to crop for " + sourceArrow + "."));
				}
				return false;
			}
			Sprite val3 = CropSpriteToArrowTip(val2.m_itemData.m_shared.m_icons[0], sourceArrow);
			if ((Object)(object)val3 == (Object)null)
			{
				return false;
			}
			item.ItemDrop.m_itemData.m_shared.m_icons = (Sprite[])(object)new Sprite[1] { val3 };
			SyncIconsToObjectDb(((Object)item.ItemPrefab).name, item.ItemDrop.m_itemData.m_shared.m_icons);
			return true;
		}

		internal static Sprite CropSpriteToArrowTip(Sprite source, string sourceArrow)
		{
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ba: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c6: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)source == (Object)null || (Object)(object)source.texture == (Object)null)
			{
				return null;
			}
			Rect rect = source.rect;
			int num;
			float num2;
			if (sourceArrow != null)
			{
				num = ((sourceArrow.IndexOf("Needle", StringComparison.OrdinalIgnoreCase) >= 0) ? 1 : 0);
				if (num != 0)
				{
					num2 = 0.52f;
					goto IL_0047;
				}
			}
			else
			{
				num = 0;
			}
			num2 = 0.42f;
			goto IL_0047;
			IL_0047:
			float num3 = num2;
			float num4 = ((num != 0) ? 0.22f : 0.3f);
			float num5 = ((num != 0) ? 0.46f : 0.56f);
			float num6 = ((num != 0) ? 0.72f : 0.62f);
			Rect val = default(Rect);
			((Rect)(ref val))..ctor(((Rect)(ref rect)).x + ((Rect)(ref rect)).width * num3, ((Rect)(ref rect)).y + ((Rect)(ref rect)).height * num4, ((Rect)(ref rect)).width * num5, ((Rect)(ref rect)).height * num6);
			return Sprite.Create(source.texture, val, new Vector2(0.5f, 0.5f), source.pixelsPerUnit, 0u, (SpriteMeshType)0);
		}

		internal static void SyncIconsToObjectDb(string prefabName, Sprite[] icons)
		{
			if (!((Object)(object)ObjectDB.instance == (Object)null) && icons != null && icons.Length != 0)
			{
				GameObject itemPrefab = ObjectDB.instance.GetItemPrefab(prefabName);
				ItemDrop val = (((Object)(object)itemPrefab != (Object)null) ? itemPrefab.GetComponent<ItemDrop>() : null);
				if (val?.m_itemData?.m_shared != null)
				{
					val.m_itemData.m_shared.m_icons = icons;
				}
			}
		}

		internal static GameObject BuildShaftIconRig(string sourceArrow, bool ashTint)
		{
			//IL_009f: Unknown result type (might be due to invalid IL or missing references)
			GameObject prefab = PrefabManager.Instance.GetPrefab(sourceArrow);
			if ((Object)(object)prefab == (Object)null)
			{
				return null;
			}
			IconRigGuard.Enter();
			GameObject val;
			try
			{
				val = Object.Instantiate<GameObject>(prefab);
				((Object)val).name = "IconRig_Shaft_" + sourceArrow;
				PrepareIconRig(val);
			}
			finally
			{
				IconRigGuard.Leave();
			}
			Transform[] componentsInChildren = val.GetComponentsInChildren<Transform>(true);
			foreach (Transform val2 in componentsInChildren)
			{
				if (!((Object)(object)val2 == (Object)(object)val.transform) && IsHeadPart(((Object)val2).name))
				{
					((Component)val2).gameObject.SetActive(false);
				}
			}
			if (ashTint)
			{
				TintRenderers(val, new Color(0.38f, 0.38f, 0.42f, 1f));
			}
			return val;
		}

		internal static GameObject BuildHeadIconRig(string sourceArrow, float headScale = 1.5f)
		{
			//IL_0180: Unknown result type (might be due to invalid IL or missing references)
			//IL_0186: Unknown result type (might be due to invalid IL or missing references)
			GameObject prefab = PrefabManager.Instance.GetPrefab(sourceArrow);
			if ((Object)(object)prefab == (Object)null)
			{
				return null;
			}
			IconRigGuard.Enter();
			GameObject val;
			try
			{
				val = Object.Instantiate<GameObject>(prefab);
				((Object)val).name = "IconRig_Head_" + sourceArrow;
				PrepareIconRig(val);
			}
			finally
			{
				IconRigGuard.Leave();
			}
			Transform[] componentsInChildren = val.GetComponentsInChildren<Transform>(true);
			foreach (Transform val2 in componentsInChildren)
			{
				if (!((Object)(object)val2 == (Object)(object)val.transform) && (IsShaftPart(((Object)val2).name) || IsFeatherPart(((Object)val2).name)))
				{
					((Component)val2).gameObject.SetActive(false);
				}
			}
			Renderer[] componentsInChildren2 = val.GetComponentsInChildren<Renderer>(true);
			List<Renderer> list = new List<Renderer>();
			Renderer[] array = componentsInChildren2;
			foreach (Renderer val3 in array)
			{
				if ((Object)(object)val3 != (Object)null && ((Component)val3).gameObject.activeInHierarchy)
				{
					list.Add(val3);
				}
			}
			if (list.Count > 1)
			{
				IsolateTipRenderers(list);
			}
			list.Clear();
			array = val.GetComponentsInChildren<Renderer>(true);
			foreach (Renderer val4 in array)
			{
				if ((Object)(object)val4 != (Object)null && ((Component)val4).gameObject.activeInHierarchy)
				{
					list.Add(val4);
				}
			}
			if (list.Count == 0)
			{
				Object.Destroy((Object)(object)val);
				return null;
			}
			array = val.GetComponentsInChildren<Renderer>(true);
			foreach (Renderer val5 in array)
			{
				if (!((Object)(object)val5 == (Object)null) && ((Component)val5).gameObject.activeInHierarchy)
				{
					Transform transform = ((Component)val5).transform;
					transform.localScale *= headScale;
				}
			}
			return val;
		}

		private static void IsolateTipRenderers(List<Renderer> renderers)
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: 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_003d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0042: Unknown result type (might be due to invalid IL or missing references)
			//IL_0060: Unknown result type (might be due to invalid IL or missing references)
			//IL_0065: Unknown result type (might be due to invalid IL or missing references)
			//IL_0069: Unknown result type (might be due to invalid IL or missing references)
			//IL_0070: Unknown result type (might be due to invalid IL or missing references)
			//IL_0075: Unknown result type (might be due to invalid IL or missing references)
			//IL_007a: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cf: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00df: Unknown result t