Decompiled source of Cosmetics and Scrap Menu v1.1.0

BepInEx/plugins/BonemansCosmeticsScrapMenu/BonemansCosmeticsScrapMenu.dll

Decompiled 5 hours ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Text;
using System.Text.RegularExpressions;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using GameNetcodeStuff;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using MoreCompany;
using MoreCompany.Behaviors;
using MoreCompany.Cosmetics;
using TMPro;
using Unity.Collections;
using Unity.Netcode;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.Events;
using UnityEngine.InputSystem;
using UnityEngine.InputSystem.Controls;
using UnityEngine.UI;

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

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace CosmeticsMenuPlus
{
	internal enum Slot
	{
		Wearing,
		Head,
		Chest,
		Hip,
		RightArm,
		LeftLeg,
		RightLeg,
		All,
		Suits,
		Favorites,
		Outfits,
		Hidden
	}
	internal class CosmeticEntry
	{
		public string Id;

		public string Name;

		public string Pack;

		public Slot Slot;

		public CosmeticInstance Instance;

		private bool? tintable;

		public bool Tintable
		{
			get
			{
				bool valueOrDefault = tintable == true;
				if (!tintable.HasValue)
				{
					valueOrDefault = (Object)(object)Instance != (Object)null && Recolor.CanTint(((Component)Instance).gameObject);
					tintable = valueOrDefault;
					return valueOrDefault;
				}
				return valueOrDefault;
			}
		}
	}
	internal static class CosmeticCatalog
	{
		public static readonly List<CosmeticEntry> Entries = new List<CosmeticEntry>();

		public static readonly Dictionary<string, CosmeticEntry> ById = new Dictionary<string, CosmeticEntry>();

		public static readonly List<string> Packs = new List<string>();

		private static int builtFor = -1;

		public static void Refresh()
		{
			//IL_00b8: Unknown result type (might be due to invalid IL or missing references)
			if (builtFor == CosmeticRegistry.cosmeticInstances.Count)
			{
				return;
			}
			builtFor = CosmeticRegistry.cosmeticInstances.Count;
			Dictionary<string, string> dictionary = ReadPacksFromLog();
			Entries.Clear();
			ById.Clear();
			foreach (KeyValuePair<string, CosmeticInstance> cosmeticInstance in CosmeticRegistry.cosmeticInstances)
			{
				if (!((Object)(object)cosmeticInstance.Value == (Object)null))
				{
					string value;
					CosmeticEntry cosmeticEntry = new CosmeticEntry
					{
						Id = cosmeticInstance.Key,
						Name = PrettyName(cosmeticInstance.Key),
						Pack = (dictionary.TryGetValue(cosmeticInstance.Key, out value) ? value : PackFromId(cosmeticInstance.Key)),
						Slot = SlotOf(cosmeticInstance.Value.cosmeticType),
						Instance = cosmeticInstance.Value
					};
					Entries.Add(cosmeticEntry);
					ById[cosmeticEntry.Id] = cosmeticEntry;
				}
			}
			Entries.Sort((CosmeticEntry a, CosmeticEntry b) => string.Compare(a.Name, b.Name, StringComparison.OrdinalIgnoreCase));
			Packs.Clear();
			Packs.AddRange(from p in Entries.Select((CosmeticEntry e) => e.Pack).Distinct()
				orderby p
				select p);
		}

		public static Slot SlotOf(CosmeticType type)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: Expected I4, but got Unknown
			return (int)type switch
			{
				0 => Slot.Head, 
				2 => Slot.Chest, 
				4 => Slot.Hip, 
				3 => Slot.RightArm, 
				5 => Slot.LeftLeg, 
				6 => Slot.RightLeg, 
				_ => Slot.All, 
			};
		}

		public static string SlotLabel(Slot slot)
		{
			return slot switch
			{
				Slot.Wearing => "Wearing", 
				Slot.RightArm => "Right arm", 
				Slot.LeftLeg => "Left leg", 
				Slot.RightLeg => "Right leg", 
				Slot.All => "All", 
				_ => slot.ToString(), 
			};
		}

		private static Dictionary<string, string> ReadPacksFromLog()
		{
			Dictionary<string, string> dictionary = new Dictionary<string, string>();
			string path = Path.Combine(Paths.BepInExRootPath, "LogOutput.log");
			try
			{
				using FileStream stream = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.ReadWrite | FileShare.Delete);
				using StreamReader streamReader = new StreamReader(stream);
				string text;
				while ((text = streamReader.ReadLine()) != null)
				{
					int num = text.IndexOf("Loaded cosmetic: ");
					if (num < 0)
					{
						continue;
					}
					int num2 = text.IndexOf(" from bundle: ", num);
					if (num2 >= 0)
					{
						string key = text.Substring(num + "Loaded cosmetic: ".Length, num2 - num - "Loaded cosmetic: ".Length).Trim();
						string text2 = PackFromPath(text.Substring(num2 + " from bundle: ".Length).Trim());
						if (text2 != null)
						{
							dictionary[key] = text2;
						}
					}
				}
			}
			catch (Exception ex)
			{
				Plugin.Log.LogWarning((object)("Couldn't read pack names from the log, grouping by id prefix instead: " + ex.Message));
			}
			return dictionary;
		}

		private static string PackFromPath(string bundle)
		{
			if (bundle == "morecompany.cosmetics")
			{
				return "MoreCompany";
			}
			string[] array = bundle.Replace('/', '\\').Split('\\');
			int num = Array.FindLastIndex(array, (string p) => p.Equals("plugins", StringComparison.OrdinalIgnoreCase));
			if (num < 0 || num + 1 >= array.Length)
			{
				return null;
			}
			string text = array[num + 1];
			if (text.EndsWith(".cosmetics") || text.Equals("MoreCompanyCosmetics", StringComparison.OrdinalIgnoreCase))
			{
				return "Loose files";
			}
			int num2 = text.IndexOf('-');
			if (num2 >= 0 && num2 < text.Length - 1)
			{
				text = text.Substring(num2 + 1);
			}
			return SplitWords(text.Replace('_', ' '));
		}

		private static string PackFromId(string id)
		{
			int num = id.IndexOf('.');
			string text = ((num > 0) ? id.Substring(0, num) : "Other");
			if (text.Equals("builtin", StringComparison.OrdinalIgnoreCase))
			{
				return "MoreCompany";
			}
			return Capitalize(text);
		}

		public static string PrettyName(string id)
		{
			string[] array = id.Split('.');
			IEnumerable<string> enumerable2;
			if (array.Length <= 1)
			{
				IEnumerable<string> enumerable = array;
				enumerable2 = enumerable;
			}
			else
			{
				enumerable2 = array.Skip(1);
			}
			IEnumerable<string> values = enumerable2;
			return Capitalize(SplitWords(string.Join(" ", values).Replace('_', ' ').Replace('-', ' ')).Trim());
		}

		private static string SplitWords(string s)
		{
			StringBuilder stringBuilder = new StringBuilder(s.Length + 8);
			for (int i = 0; i < s.Length; i++)
			{
				char c = s[i];
				if (i > 0 && char.IsUpper(c) && char.IsLower(s[i - 1]))
				{
					stringBuilder.Append(' ');
				}
				stringBuilder.Append(c);
			}
			return Regex.Replace(stringBuilder.ToString(), " +", " ");
		}

		private static string Capitalize(string s)
		{
			if (!string.IsNullOrEmpty(s))
			{
				return char.ToUpperInvariant(s[0]) + s.Substring(1);
			}
			return s;
		}
	}
	[HarmonyPatch]
	internal static class DisplayScale
	{
		private static Transform model;

		private static float originalScale;

		private static float Ratio
		{
			get
			{
				//IL_0024: Unknown result type (might be due to invalid IL or missing references)
				if (!((Object)(object)model != (Object)null) || !(originalScale > 0f))
				{
					return 1f;
				}
				return model.lossyScale.x / originalScale;
			}
		}

		public static void Capture(Transform scavengerModel)
		{
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			model = scavengerModel;
			originalScale = (((Object)(object)scavengerModel != (Object)null) ? scavengerModel.lossyScale.x : 0f);
		}

		[HarmonyPatch(typeof(CosmeticRegistry), "SpawnCosmeticGUI")]
		[HarmonyPrefix]
		private static void BeforeSpawnGui()
		{
			model = null;
			originalScale = 0f;
		}

		[HarmonyPatch(typeof(CosmeticRegistry), "UpdateCosmeticsOnDisplayGuy")]
		[HarmonyPostfix]
		private static void AfterDisplayUpdate()
		{
			//IL_0073: 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)
			float ratio = Ratio;
			if (Mathf.Abs(ratio - 1f) < 0.001f || (Object)(object)model == (Object)null)
			{
				return;
			}
			Transform obj = model.Find("metarig");
			CosmeticApplication val = ((obj != null) ? ((Component)obj).GetComponent<CosmeticApplication>() : null);
			if ((Object)(object)val == (Object)null)
			{
				return;
			}
			foreach (CosmeticInstance spawnedCosmetic in val.spawnedCosmetics)
			{
				if ((Object)(object)spawnedCosmetic != (Object)null)
				{
					Transform transform = ((Component)spawnedCosmetic).transform;
					transform.localScale *= ratio;
				}
			}
		}
	}
	[BepInPlugin("kylew.cosmeticsmenuplus", "Boneman's Cosmetics & Scrap Menu", "1.1.0")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	public class Plugin : BaseUnityPlugin
	{
		public const string GUID = "kylew.cosmeticsmenuplus";

		internal static ManualLogSource Log;

		internal static ConfigEntry<bool> Enabled;

		internal static ConfigEntry<bool> ListMode;

		internal static ConfigEntry<string> LastSlot;

		internal static ConfigEntry<string> ActiveOutfit;

		private void Awake()
		{
			//IL_0098: Unknown result type (might be due to invalid IL or missing references)
			//IL_009d: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ad: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bd: Unknown result type (might be due to invalid IL or missing references)
			Log = ((BaseUnityPlugin)this).Logger;
			Enabled = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "Enabled", true, "Replace MoreCompany's cosmetics grid with the slot menu. Turn off to get the original menu back.");
			ListMode = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "List Mode", false, "Show cosmetics as a list instead of an icon grid.");
			LastSlot = ((BaseUnityPlugin)this).Config.Bind<string>("General", "Last Slot", "Wearing", "Slot tab shown when the menu opens.");
			ActiveOutfit = ((BaseUnityPlugin)this).Config.Bind<string>("General", "Active Outfit", "", "Outfit that changes are saved into as you make them. Set by wearing or saving an outfit.");
			Harmony val = new Harmony("kylew.cosmeticsmenuplus");
			val.PatchAll(typeof(Patches));
			val.PatchAll(typeof(TintSync));
			val.PatchAll(typeof(DisplayScale));
			val.PatchAll(typeof(ScrapSpawnFilter));
			Log.LogInfo((object)"Boneman's Cosmetics & Scrap Menu loaded");
		}
	}
	internal static class Patches
	{
		private static bool bypass;

		[HarmonyPatch(typeof(CosmeticRegistry), "PopulateCosmetics")]
		[HarmonyPrefix]
		private static bool PopulatePrefix()
		{
			if (Plugin.Enabled.Value)
			{
				return bypass;
			}
			return true;
		}

		[HarmonyPatch(typeof(CosmeticRegistry), "SpawnCosmeticGUI")]
		[HarmonyPostfix]
		private static void SpawnPostfix(bool mainMenu)
		{
			if (!Plugin.Enabled.Value || (Object)(object)CosmeticRegistry.cosmeticGUIGlobalScale == (Object)null)
			{
				return;
			}
			try
			{
				SlotMenu.Build(CosmeticRegistry.cosmeticGUIGlobalScale, !mainMenu);
			}
			catch (Exception ex)
			{
				Plugin.Log.LogError((object)("Failed to build cosmetics menu, falling back to MoreCompany's: " + ex));
				SlotMenu.RestoreOriginal(CosmeticRegistry.cosmeticGUIGlobalScale);
				bypass = true;
				try
				{
					CosmeticRegistry.PopulateCosmetics();
				}
				finally
				{
					bypass = false;
				}
			}
		}

		[HarmonyPatch(typeof(QuickMenuManager), "OpenQuickMenu")]
		[HarmonyPatch(typeof(QuickMenuManager), "CloseQuickMenu")]
		[HarmonyPostfix]
		private static void QuickMenuToggled(QuickMenuManager __instance)
		{
			if (CosmeticRegistry.menuIsInGame)
			{
				SlotMenu.SyncScrapButton(__instance.isMenuOpen);
			}
		}
	}
	internal class PreviewControls : MonoBehaviour
	{
		public Transform spinTarget;

		public Transform holder;

		public RectTransform space;

		public RectTransform area;

		private Vector3 basePos;

		private Vector3 baseScale;

		private Quaternion baseRotation;

		private float zoom = 1f;

		private bool spinning;

		private bool panning;

		private float spinVelocity;

		private Vector2 lastMouse;

		private Camera cam;

		private const float SpinPerPixel = 0.45f;

		private const float DriftDamping = 2.2f;

		private const float MinZoom = 0.8f;

		private const float MaxZoom = 3f;

		public void Init()
		{
			//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_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0050: Unknown result type (might be due to invalid IL or missing references)
			basePos = holder.localPosition;
			baseScale = holder.localScale;
			baseRotation = spinTarget.localRotation;
			Canvas componentInParent = ((Component)area).GetComponentInParent<Canvas>(true);
			cam = (((Object)(object)componentInParent != (Object)null && (int)componentInParent.rootCanvas.renderMode != 0) ? componentInParent.rootCanvas.worldCamera : null);
		}

		public void ResetView()
		{
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_003f: Unknown result type (might be due to invalid IL or missing references)
			zoom = 1f;
			spinVelocity = 0f;
			holder.localPosition = basePos;
			holder.localScale = baseScale;
			spinTarget.localRotation = baseRotation;
		}

		private void Zoom(float scroll, Vector2 screenPos)
		{
			//IL_0040: Unknown result type (might be due to invalid IL or missing references)
			//IL_0045: Unknown result type (might be due to invalid IL or missing references)
			//IL_0047: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c5: 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_0057: Unknown result type (might be due to invalid IL or missing references)
			//IL_005d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0062: Unknown result type (might be due to invalid IL or missing references)
			//IL_0063: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: Unknown result type (might be due to invalid IL or missing references)
			//IL_0069: Unknown result type (might be due to invalid IL or missing references)
			//IL_006a: 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_0078: 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_0081: Unknown result type (might be due to invalid IL or missing references)
			//IL_0088: 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)
			float num = Mathf.Clamp(zoom * ((scroll > 0f) ? 1.12f : (25f / 28f)), 0.8f, 3f);
			if (!Mathf.Approximately(num, zoom))
			{
				Vector3 localPosition = holder.localPosition;
				if (ToLocal(screenPos, out var local))
				{
					Vector2 val = new Vector2(localPosition.x, localPosition.y) - local;
					Vector2 val2 = local + val * (num / zoom);
					((Vector3)(ref localPosition))..ctor(val2.x, val2.y, localPosition.z);
				}
				zoom = num;
				holder.localScale = baseScale * zoom;
				holder.localPosition = ClampPan(localPosition);
			}
		}

		private void Update()
		{
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0096: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b2: 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_021e: Unknown result type (might be due to invalid IL or missing references)
			//IL_021f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0177: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ec: Unknown result type (might be due to invalid IL or missing references)
			//IL_0103: Unknown result type (might be due to invalid IL or missing references)
			//IL_0108: Unknown result type (might be due to invalid IL or missing references)
			//IL_0111: Unknown result type (might be due to invalid IL or missing references)
			//IL_0113: Unknown result type (might be due to invalid IL or missing references)
			//IL_011a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0122: Unknown result type (might be due to invalid IL or missing references)
			//IL_0129: Unknown result type (might be due to invalid IL or missing references)
			//IL_0136: Unknown result type (might be due to invalid IL or missing references)
			//IL_013b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0140: Unknown result type (might be due to invalid IL or missing references)
			Mouse current = Mouse.current;
			if (current == null)
			{
				return;
			}
			Vector2 val = ((InputControl<Vector2>)(object)((Pointer)current).position).ReadValue();
			float num = Mathf.Max(Time.unscaledDeltaTime, 0.0001f);
			bool num2 = RectTransformUtility.RectangleContainsScreenPoint(area, val, cam);
			if (num2 && (current.leftButton.wasPressedThisFrame || current.rightButton.wasPressedThisFrame))
			{
				spinning = true;
				spinVelocity = 0f;
			}
			if (num2 && current.middleButton.wasPressedThisFrame)
			{
				panning = true;
				spinning = false;
				spinVelocity = 0f;
			}
			float y = ((InputControl<Vector2>)(object)current.scroll).ReadValue().y;
			if (num2 && !Mathf.Approximately(y, 0f))
			{
				Zoom(y, val);
			}
			if (panning)
			{
				Vector2 local;
				Vector2 local2;
				if (!current.middleButton.isPressed)
				{
					panning = false;
				}
				else if (ToLocal(val, out local) && ToLocal(lastMouse, out local2))
				{
					Vector3 localPosition = holder.localPosition;
					holder.localPosition = ClampPan(localPosition + new Vector3(local.x - local2.x, local.y - local2.y, 0f));
				}
			}
			else if (spinning)
			{
				if (!current.leftButton.isPressed && !current.rightButton.isPressed)
				{
					spinning = false;
				}
				else
				{
					float num3 = (0f - (val.x - lastMouse.x)) * 0.45f;
					spinTarget.Rotate(0f, num3, 0f, (Space)0);
					spinVelocity = Mathf.Lerp(spinVelocity, num3 / num, 0.35f);
				}
			}
			if (!spinning && !panning && Mathf.Abs(spinVelocity) > 0.5f)
			{
				spinTarget.Rotate(0f, spinVelocity * num, 0f, (Space)0);
				spinVelocity *= Mathf.Exp(-2.2f * num);
			}
			lastMouse = val;
		}

		private bool ToLocal(Vector2 screen, out Vector2 local)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			return RectTransformUtility.ScreenPointToLocalPointInRectangle(space, screen, cam, ref local);
		}

		private Vector3 ClampPan(Vector3 p)
		{
			//IL_0033: 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_007d: 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)
			float num = Mathf.Max(zoom - 1f, 0f);
			float num2 = 40f + 90f * num;
			float num3 = 40f + 230f * num;
			return new Vector3(Mathf.Clamp(p.x, basePos.x - num2, basePos.x + num2), Mathf.Clamp(p.y, basePos.y - num3, basePos.y + num3), p.z);
		}
	}
	internal static class Recolor
	{
		private class Originals : MonoBehaviour
		{
			public readonly Dictionary<Renderer, Material[]> byRenderer = new Dictionary<Renderer, Material[]>();
		}

		private static readonly string[] ColorProps = new string[3] { "_BaseColor", "_UnlitColor", "_Color" };

		private static readonly string[] TextureProps = new string[3] { "_BaseColorMap", "_UnlitColorMap", "_MainTex" };

		private const int MaxTextureSize = 1024;

		private const int PreviewTextureSize = 256;

		public static bool Preview;

		private static readonly Dictionary<(int, string), Material> materials = new Dictionary<(int, string), Material>();

		private static readonly Dictionary<(int, string), Texture2D> textures = new Dictionary<(int, string), Texture2D>();

		public static string PreviewKey(Tint tint)
		{
			return tint.Key + "@preview";
		}

		private static string CacheKey(Tint tint)
		{
			if (!Preview)
			{
				return tint.Key;
			}
			return PreviewKey(tint);
		}

		public static void Prune(HashSet<string> keysInUse)
		{
			foreach (var item in new List<(int, string)>(materials.Keys))
			{
				if (!keysInUse.Contains(item.Item2))
				{
					if ((Object)(object)materials[item] != (Object)null)
					{
						Object.Destroy((Object)(object)materials[item]);
					}
					materials.Remove(item);
				}
			}
			foreach (var item2 in new List<(int, string)>(textures.Keys))
			{
				if (!keysInUse.Contains(item2.Item2))
				{
					if ((Object)(object)textures[item2] != (Object)null)
					{
						Object.Destroy((Object)(object)textures[item2]);
					}
					textures.Remove(item2);
				}
			}
		}

		public static bool CanTint(GameObject go)
		{
			foreach (Renderer item in Renderers(go))
			{
				Material[] sharedMaterials = item.sharedMaterials;
				for (int i = 0; i < sharedMaterials.Length; i++)
				{
					if (Tintable(sharedMaterials[i]))
					{
						return true;
					}
				}
			}
			return false;
		}

		public static void Apply(GameObject go, Tint tint)
		{
			if ((Object)(object)go == (Object)null)
			{
				return;
			}
			Originals originals = go.GetComponent<Originals>();
			if ((Object)(object)originals == (Object)null)
			{
				if (tint.IsNone)
				{
					return;
				}
				originals = go.AddComponent<Originals>();
			}
			foreach (Renderer item in Renderers(go))
			{
				Material[] sharedMaterials = item.sharedMaterials;
				if (!originals.byRenderer.TryGetValue(item, out var value) || value.Length != sharedMaterials.Length)
				{
					value = sharedMaterials;
					originals.byRenderer[item] = value;
				}
				else
				{
					for (int i = 0; i < sharedMaterials.Length; i++)
					{
						if ((Object)(object)sharedMaterials[i] != (Object)null && (Object)(object)sharedMaterials[i] != (Object)(object)value[i] && !((Object)sharedMaterials[i]).name.Contains("(tint "))
						{
							value[i] = sharedMaterials[i];
						}
					}
				}
				Material[] array = (Material[])(object)new Material[value.Length];
				for (int j = 0; j < value.Length; j++)
				{
					array[j] = ((tint.IsNone || !Tintable(value[j])) ? value[j] : Tinted(value[j], tint));
				}
				item.sharedMaterials = array;
			}
		}

		private static IEnumerable<Renderer> Renderers(GameObject go)
		{
			Renderer[] componentsInChildren = go.GetComponentsInChildren<Renderer>(true);
			foreach (Renderer val in componentsInChildren)
			{
				if (val is MeshRenderer || val is SkinnedMeshRenderer)
				{
					yield return val;
				}
			}
		}

		private static bool Tintable(Material m)
		{
			if ((Object)(object)m == (Object)null)
			{
				return false;
			}
			string[] colorProps = ColorProps;
			foreach (string text in colorProps)
			{
				if (m.HasProperty(text))
				{
					return true;
				}
			}
			colorProps = TextureProps;
			foreach (string text2 in colorProps)
			{
				if (m.HasProperty(text2))
				{
					return true;
				}
			}
			return false;
		}

		private static Material Tinted(Material source, Tint tint)
		{
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			//IL_0056: Expected O, but got Unknown
			//IL_0074: 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_0091: 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_009a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0087: Unknown result type (might be due to invalid IL or missing references)
			//IL_008a: Unknown result type (might be due to invalid IL or missing references)
			(int, string) key = (((Object)source).GetInstanceID(), CacheKey(tint));
			if (materials.TryGetValue(key, out var value) && (Object)(object)value != (Object)null)
			{
				return value;
			}
			Material val = new Material(source)
			{
				name = ((Object)source).name + " (tint " + tint.Key + ")"
			};
			string[] colorProps = ColorProps;
			foreach (string text in colorProps)
			{
				if (val.HasProperty(text))
				{
					Color color = source.GetColor(text);
					val.SetColor(text, (tint.Mode == TintMode.Tint) ? MultiplyRgb(color, tint.TintColor) : Shift(color, tint));
				}
			}
			if (tint.Mode == TintMode.HueShift)
			{
				colorProps = TextureProps;
				foreach (string text2 in colorProps)
				{
					if (val.HasProperty(text2))
					{
						Texture texture = source.GetTexture(text2);
						if ((Object)(object)texture != (Object)null)
						{
							val.SetTexture(text2, ShiftedTexture(texture, tint));
						}
					}
				}
			}
			materials[key] = val;
			return val;
		}

		private static Color MultiplyRgb(Color a, Color b)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			return new Color(a.r * b.r, a.g * b.g, a.b * b.b, a.a);
		}

		private static Color Shift(Color c, Tint t)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_003e: 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_0046: 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)
			float num = default(float);
			float num2 = default(float);
			float num3 = default(float);
			Color.RGBToHSV(c, ref num, ref num2, ref num3);
			Color result = Color.HSVToRGB(Mathf.Repeat(num + t.Hue / 360f, 1f), Mathf.Clamp01(num2 * t.Saturation), Mathf.Clamp01(num3 * t.Brightness));
			result.a = c.a;
			return result;
		}

		private static Texture ShiftedTexture(Texture source, Tint tint)
		{
			//IL_00b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ba: Expected O, but got Unknown
			//IL_00cb: Unknown result type (might be due to invalid IL or missing references)
			//IL_011d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0128: Unknown result type (might be due to invalid IL or missing references)
			//IL_012d: Unknown result type (might be due to invalid IL or missing references)
			//IL_014c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0159: Unknown result type (might be due to invalid IL or missing references)
			(int, string) key = (((Object)source).GetInstanceID(), CacheKey(tint));
			if (textures.TryGetValue(key, out var value) && (Object)(object)value != (Object)null)
			{
				return (Texture)(object)value;
			}
			float num = Mathf.Min(1f, (float)(Preview ? 256 : 1024) / (float)Mathf.Max(source.width, source.height));
			int num2 = Mathf.Max(1, Mathf.RoundToInt((float)source.width * num));
			int num3 = Mathf.Max(1, Mathf.RoundToInt((float)source.height * num));
			RenderTexture temporary = RenderTexture.GetTemporary(num2, num3, 0, (RenderTextureFormat)0, (RenderTextureReadWrite)2);
			RenderTexture active = RenderTexture.active;
			Texture2D val;
			try
			{
				Graphics.Blit(source, temporary);
				RenderTexture.active = temporary;
				val = new Texture2D(num2, num3, (TextureFormat)4, true, false);
				val.ReadPixels(new Rect(0f, 0f, (float)num2, (float)num3), 0, 0, false);
			}
			finally
			{
				RenderTexture.active = active;
				RenderTexture.ReleaseTemporary(temporary);
			}
			Color32[] pixels = val.GetPixels32();
			float dh = tint.Hue / 360f;
			float saturation = tint.Saturation;
			float brightness = tint.Brightness;
			for (int i = 0; i < pixels.Length; i++)
			{
				pixels[i] = ShiftPixel(pixels[i], dh, saturation, brightness);
			}
			val.SetPixels32(pixels);
			((Texture)val).wrapMode = source.wrapMode;
			((Texture)val).filterMode = source.filterMode;
			((Texture)val).anisoLevel = source.anisoLevel;
			((Object)val).name = ((Object)source).name + " (tint " + tint.Key + ")";
			val.Apply(true, true);
			textures[key] = val;
			return (Texture)(object)val;
		}

		private static Color32 ShiftPixel(Color32 c, float dh, float ds, float dv)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01de: Unknown result type (might be due to invalid IL or missing references)
			float num = (float)(int)c.r / 255f;
			float num2 = (float)(int)c.g / 255f;
			float num3 = (float)(int)c.b / 255f;
			float num4 = Mathf.Max(num, Mathf.Max(num2, num3));
			float num5 = Mathf.Min(num, Mathf.Min(num2, num3));
			float num6 = num4 - num5;
			float num7 = 0f;
			if (num6 > 1E-05f)
			{
				num7 = ((num4 == num) ? ((num2 - num3) / num6 / 6f) : ((num4 != num2) ? (((num - num2) / num6 + 4f) / 6f) : (((num3 - num) / num6 + 2f) / 6f)));
				if (num7 < 0f)
				{
					num7 += 1f;
				}
			}
			float num8 = ((num4 > 1E-05f) ? (num6 / num4) : 0f);
			float num9 = num4;
			num7 += dh;
			num7 -= Mathf.Floor(num7);
			num8 = Mathf.Clamp01(num8 * ds);
			num9 = Mathf.Clamp01(num9 * dv);
			float num10 = num7 * 6f;
			int num11 = (int)num10 % 6;
			float num12 = num10 - Mathf.Floor(num10);
			float num13 = num9 * (1f - num8);
			float num14 = num9 * (1f - num8 * num12);
			float num15 = num9 * (1f - num8 * (1f - num12));
			float num16;
			float num17;
			float num18;
			switch (num11)
			{
			case 0:
				num16 = num9;
				num17 = num15;
				num18 = num13;
				break;
			case 1:
				num16 = num14;
				num17 = num9;
				num18 = num13;
				break;
			case 2:
				num16 = num13;
				num17 = num9;
				num18 = num15;
				break;
			case 3:
				num16 = num13;
				num17 = num14;
				num18 = num9;
				break;
			case 4:
				num16 = num15;
				num17 = num13;
				num18 = num9;
				break;
			default:
				num16 = num9;
				num17 = num13;
				num18 = num14;
				break;
			}
			return new Color32((byte)(num16 * 255f + 0.5f), (byte)(num17 * 255f + 0.5f), (byte)(num18 * 255f + 0.5f), c.a);
		}
	}
	internal static class ScrapButtonIcon
	{
		private const int S = 128;

		private static Sprite cached;

		private static readonly Color Frame = new Color(0.16f, 0.78f, 0.32f, 1f);

		private static readonly Color Back = new Color(0.02f, 0.11f, 0.04f, 0.92f);

		private static readonly Color Top = new Color(0.2f, 0.86f, 0.38f, 1f);

		private static readonly Color Left = new Color(0.12f, 0.6f, 0.25f, 1f);

		private static readonly Color Right = new Color(0.08f, 0.44f, 0.18f, 1f);

		private static readonly Color Line = new Color(0.02f, 0.11f, 0.04f, 1f);

		public static Sprite Get()
		{
			//IL_00ed: 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)
			//IL_0103: Unknown result type (might be due to invalid IL or missing references)
			//IL_0108: Unknown result type (might be due to invalid IL or missing references)
			//IL_0119: Unknown result type (might be due to invalid IL or missing references)
			//IL_011e: Unknown result type (might be due to invalid IL or missing references)
			//IL_012f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0134: Unknown result type (might be due to invalid IL or missing references)
			//IL_014c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0151: Unknown result type (might be due to invalid IL or missing references)
			//IL_0162: Unknown result type (might be due to invalid IL or missing references)
			//IL_0167: Unknown result type (might be due to invalid IL or missing references)
			//IL_0178: Unknown result type (might be due to invalid IL or missing references)
			//IL_017d: Unknown result type (might be due to invalid IL or missing references)
			//IL_018e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0193: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ab: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c1: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c6: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d7: Unknown result type (might be due to invalid IL or missing references)
			//IL_01dc: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ed: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01fa: Unknown result type (might be due to invalid IL or missing references)
			//IL_0206: Unknown result type (might be due to invalid IL or missing references)
			//IL_0212: Unknown result type (might be due to invalid IL or missing references)
			//IL_0241: Unknown result type (might be due to invalid IL or missing references)
			//IL_0250: Unknown result type (might be due to invalid IL or missing references)
			//IL_026a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0279: 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_00b0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b2: 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_0087: Unknown result type (might be due to invalid IL or missing references)
			//IL_008c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0299: Unknown result type (might be due to invalid IL or missing references)
			//IL_029e: Unknown result type (might be due to invalid IL or missing references)
			//IL_02a0: Unknown result type (might be due to invalid IL or missing references)
			//IL_02a5: Unknown result type (might be due to invalid IL or missing references)
			//IL_02a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_02aa: Unknown result type (might be due to invalid IL or missing references)
			//IL_02b1: Unknown result type (might be due to invalid IL or missing references)
			//IL_02e0: Unknown result type (might be due to invalid IL or missing references)
			//IL_02e5: Unknown result type (might be due to invalid IL or missing references)
			//IL_02f0: Unknown result type (might be due to invalid IL or missing references)
			//IL_02f7: Unknown result type (might be due to invalid IL or missing references)
			//IL_02fe: Unknown result type (might be due to invalid IL or missing references)
			//IL_0305: Unknown result type (might be due to invalid IL or missing references)
			//IL_031f: Unknown result type (might be due to invalid IL or missing references)
			//IL_032e: Unknown result type (might be due to invalid IL or missing references)
			//IL_033d: Expected O, but got Unknown
			if ((Object)(object)cached != (Object)null)
			{
				return cached;
			}
			Color[] array = (Color[])(object)new Color[16384];
			for (int i = 0; i < 128; i++)
			{
				for (int j = 0; j < 128; j++)
				{
					float num = RoundedBoxDistance((float)j + 0.5f, (float)i + 0.5f, 4f, 4f, 124f, 124f, 14f);
					Color val = Color.clear;
					if (num < 0.5f)
					{
						val = Blend(Back, Frame, Mathf.Clamp01(num + 9.5f));
					}
					val.a *= Mathf.Clamp01(0.5f - num);
					array[Index(j, i)] = val;
				}
			}
			Vector2[] poly = (Vector2[])(object)new Vector2[4]
			{
				new Vector2(64f, 26f),
				new Vector2(100f, 44f),
				new Vector2(64f, 62f),
				new Vector2(28f, 44f)
			};
			Vector2[] poly2 = (Vector2[])(object)new Vector2[4]
			{
				new Vector2(28f, 44f),
				new Vector2(64f, 62f),
				new Vector2(64f, 102f),
				new Vector2(28f, 84f)
			};
			Vector2[] poly3 = (Vector2[])(object)new Vector2[4]
			{
				new Vector2(64f, 62f),
				new Vector2(100f, 44f),
				new Vector2(100f, 84f),
				new Vector2(64f, 102f)
			};
			Fill(array, poly, Top);
			Fill(array, poly2, Left);
			Fill(array, poly3, Right);
			List<(Vector2, Vector2)> list = new List<(Vector2, Vector2)>();
			AddLoop(list, poly);
			AddLoop(list, poly2);
			AddLoop(list, poly3);
			list.Add((new Vector2(28f, 64f), new Vector2(64f, 82f)));
			list.Add((new Vector2(64f, 82f), new Vector2(100f, 64f)));
			foreach (var (a, b) in list)
			{
				Stroke(array, a, b, 5f, Line);
			}
			Texture2D val2 = new Texture2D(128, 128, (TextureFormat)4, false)
			{
				name = "Scrap button",
				filterMode = (FilterMode)1,
				wrapMode = (TextureWrapMode)1
			};
			val2.SetPixels(array);
			val2.Apply();
			cached = Sprite.Create(val2, new Rect(0f, 0f, 128f, 128f), new Vector2(0.5f, 0.5f), 100f);
			((Object)cached).name = "Scrap button";
			return cached;
		}

		private static int Index(int x, int topDownY)
		{
			return (127 - topDownY) * 128 + x;
		}

		private static Color Blend(Color a, Color b, float t)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0003: Unknown result type (might be due to invalid IL or missing references)
			return Color.Lerp(a, b, t);
		}

		private static float RoundedBoxDistance(float x, float y, float x0, float y0, float x1, float y1, float r)
		{
			//IL_0062: Unknown result type (might be due to invalid IL or missing references)
			//IL_0067: Unknown result type (might be due to invalid IL or missing references)
			float num = (x0 + x1) / 2f;
			float num2 = (y0 + y1) / 2f;
			float num3 = (x1 - x0) / 2f - r;
			float num4 = (y1 - y0) / 2f - r;
			float num5 = Mathf.Abs(x - num) - num3;
			float num6 = Mathf.Abs(y - num2) - num4;
			Vector2 val = new Vector2(Mathf.Max(num5, 0f), Mathf.Max(num6, 0f));
			return ((Vector2)(ref val)).magnitude + Mathf.Min(Mathf.Max(num5, num6), 0f) - r;
		}

		private static void AddLoop(List<(Vector2, Vector2)> edges, Vector2[] poly)
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			for (int i = 0; i < poly.Length; i++)
			{
				edges.Add((poly[i], poly[(i + 1) % poly.Length]));
			}
		}

		private static void Fill(Color[] px, Vector2[] poly, Color color)
		{
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			for (int i = 0; i < 128; i++)
			{
				for (int j = 0; j < 128; j++)
				{
					if (Inside(new Vector2((float)j + 0.5f, (float)i + 0.5f), poly))
					{
						px[Index(j, i)] = color;
					}
				}
			}
		}

		private static bool Inside(Vector2 p, Vector2[] poly)
		{
			//IL_001b: 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_0039: 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)
			bool flag = false;
			int num = 0;
			int num2 = poly.Length - 1;
			while (num < poly.Length)
			{
				if (poly[num].y > p.y != poly[num2].y > p.y && p.x < (poly[num2].x - poly[num].x) * (p.y - poly[num].y) / (poly[num2].y - poly[num].y) + poly[num].x)
				{
					flag = !flag;
				}
				num2 = num++;
			}
			return flag;
		}

		private static void Stroke(Color[] px, Vector2 a, Vector2 b, float width, Color color)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: 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_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0053: Unknown result type (might be due to invalid IL or missing references)
			//IL_0059: 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_006e: Unknown result type (might be due to invalid IL or missing references)
			//IL_006f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0074: 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_00b0: 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_00c5: 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_00c9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ce: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d3: 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_0114: Unknown result type (might be due to invalid IL or missing references)
			//IL_0119: Unknown result type (might be due to invalid IL or missing references)
			//IL_011d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0122: Unknown result type (might be due to invalid IL or missing references)
			int num = Mathf.Max(0, (int)(Mathf.Min(a.x, b.x) - width));
			int num2 = Mathf.Min(127, (int)(Mathf.Max(a.x, b.x) + width));
			int num3 = Mathf.Max(0, (int)(Mathf.Min(a.y, b.y) - width));
			int num4 = Mathf.Min(127, (int)(Mathf.Max(a.y, b.y) + width));
			Vector2 val = b - a;
			float num5 = Mathf.Max(((Vector2)(ref val)).sqrMagnitude, 0.0001f);
			for (int i = num3; i <= num4; i++)
			{
				for (int j = num; j <= num2; j++)
				{
					Vector2 val2 = new Vector2((float)j + 0.5f, (float)i + 0.5f);
					float num6 = Mathf.Clamp01(Vector2.Dot(val2 - a, val) / num5);
					Vector2 val3 = val2 - (a + val * num6);
					float magnitude = ((Vector2)(ref val3)).magnitude;
					float num7 = Mathf.Clamp01(width / 2f + 0.5f - magnitude);
					if (!(num7 <= 0f))
					{
						int num8 = Index(j, i);
						px[num8] = Color.Lerp(px[num8], color, num7);
					}
				}
			}
		}
	}
	internal class ScrapEntry
	{
		public Item Item;

		public string Key;

		public string Name;

		public string Source;

		public int MinValue;

		public int MaxValue;

		public int Pounds;

		public bool TwoHanded;

		public bool Metal;

		public string FavoriteKey => "scrap:" + Key;
	}
	internal static class ScrapCatalog
	{
		private static readonly string DisabledPath = Path.Combine(Paths.ConfigPath, "kylew.cosmeticsmenuplus.scrap-disabled.txt");

		public static readonly List<ScrapEntry> Entries = new List<ScrapEntry>();

		public static readonly Dictionary<string, ScrapEntry> ByKey = new Dictionary<string, ScrapEntry>();

		public static readonly List<string> Sources = new List<string>();

		public static readonly HashSet<string> Disabled = new HashSet<string>();

		private static bool loaded;

		public static bool AnyDisabled
		{
			get
			{
				Load();
				return Disabled.Count > 0;
			}
		}

		public static bool IsEnabled(string key)
		{
			Load();
			return !Disabled.Contains(key);
		}

		public static void SetEnabled(string key, bool enabled)
		{
			Load();
			if (enabled)
			{
				Disabled.Remove(key);
			}
			else
			{
				Disabled.Add(key);
			}
			Save();
		}

		public static void SetDisabled(IEnumerable<string> keys)
		{
			Load();
			Disabled.Clear();
			Disabled.UnionWith(keys);
			Save();
		}

		private static void Load()
		{
			if (loaded)
			{
				return;
			}
			loaded = true;
			try
			{
				if (File.Exists(DisabledPath))
				{
					Disabled.UnionWith(from l in File.ReadAllLines(DisabledPath)
						select l.Trim() into l
						where l.Length > 0
						select l);
				}
			}
			catch (Exception ex)
			{
				Plugin.Log.LogWarning((object)("Couldn't read the scrap list: " + ex.Message));
			}
		}

		private static void Save()
		{
			try
			{
				File.WriteAllLines(DisabledPath, Disabled.OrderBy((string k) => k));
			}
			catch (Exception ex)
			{
				Plugin.Log.LogWarning((object)("Couldn't save the scrap list: " + ex.Message));
			}
		}

		public static void Refresh()
		{
			Load();
			List<Item> list = new List<Item>(Resources.FindObjectsOfTypeAll<Item>());
			if ((Object)(object)StartOfRound.Instance != (Object)null && (Object)(object)StartOfRound.Instance.allItemsList != (Object)null)
			{
				list.AddRange(StartOfRound.Instance.allItemsList.itemsList);
			}
			Dictionary<Item, string> dictionary = SourcesFromLevelLoader();
			float num = (((Object)(object)RoundManager.Instance != (Object)null && RoundManager.Instance.scrapValueMultiplier > 0f) ? RoundManager.Instance.scrapValueMultiplier : 0.4f);
			Entries.Clear();
			ByKey.Clear();
			foreach (Item item in list)
			{
				if (!((Object)(object)item == (Object)null) && item.isScrap && !((Object)(object)item.spawnPrefab == (Object)null) && !string.IsNullOrWhiteSpace(item.itemName))
				{
					string text = item.itemName.Trim();
					if (!ByKey.ContainsKey(text))
					{
						string value;
						ScrapEntry scrapEntry = new ScrapEntry
						{
							Item = item,
							Key = text,
							Name = text,
							Source = (dictionary.TryGetValue(item, out value) ? value : "Other"),
							MinValue = Mathf.RoundToInt((float)item.minValue * num),
							MaxValue = Mathf.RoundToInt((float)item.maxValue * num),
							Pounds = Mathf.RoundToInt(Mathf.Clamp(item.weight - 1f, 0f, 10f) * 105f),
							TwoHanded = item.twoHanded,
							Metal = item.isConductiveMetal
						};
						Entries.Add(scrapEntry);
						ByKey[text] = scrapEntry;
					}
				}
			}
			Entries.Sort((ScrapEntry a, ScrapEntry b) => string.Compare(a.Name, b.Name, StringComparison.OrdinalIgnoreCase));
			Sources.Clear();
			Sources.AddRange(from s in Entries.Select((ScrapEntry e) => e.Source).Distinct()
				orderby (!(s == "Lethal Company")) ? s : ""
				select s);
		}

		private static Dictionary<Item, string> SourcesFromLevelLoader()
		{
			Dictionary<Item, string> dictionary = new Dictionary<Item, string>();
			try
			{
				if (!(AccessTools.TypeByName("LethalLevelLoader.PatchedContent")?.GetProperty("ExtendedItems", BindingFlags.Static | BindingFlags.Public)?.GetValue(null) is IEnumerable enumerable))
				{
					return dictionary;
				}
				foreach (object item in enumerable)
				{
					Type type = item.GetType();
					object? obj = type.GetProperty("Item")?.GetValue(item);
					Item val = (Item)((obj is Item) ? obj : null);
					if (val != null)
					{
						string text = type.GetProperty("ContentType")?.GetValue(item)?.ToString();
						string text2 = type.GetProperty("ModName")?.GetValue(item) as string;
						dictionary[val] = ((text == "Vanilla") ? "Lethal Company" : (string.IsNullOrWhiteSpace(text2) ? "Modded" : text2.Trim()));
					}
				}
			}
			catch (Exception ex)
			{
				Plugin.Log.LogWarning((object)("Couldn't read scrap sources from LethalLevelLoader: " + ex.Message));
			}
			return dictionary;
		}
	}
	[HarmonyPatch(typeof(RoundManager), "SpawnScrapInLevel")]
	internal static class ScrapSpawnFilter
	{
		private static readonly List<(SpawnableItemWithRarity entry, int rarity)> changed = new List<(SpawnableItemWithRarity, int)>();

		[HarmonyPrefix]
		[HarmonyPriority(0)]
		private static void Prefix(RoundManager __instance)
		{
			changed.Clear();
			List<SpawnableItemWithRarity> list = __instance.currentLevel?.spawnableScrap;
			if (list == null || !ScrapCatalog.AnyDisabled)
			{
				return;
			}
			int num = 0;
			foreach (SpawnableItemWithRarity item in list)
			{
				if ((Object)(object)item?.spawnableItem != (Object)null && item.rarity > 0 && ScrapCatalog.IsEnabled(item.spawnableItem.itemName?.Trim() ?? ""))
				{
					num += item.rarity;
				}
			}
			if (num <= 0)
			{
				Plugin.Log.LogWarning((object)"Every scrap item on this moon is switched off; spawning the normal scrap instead.");
				return;
			}
			foreach (SpawnableItemWithRarity item2 in list)
			{
				if (!((Object)(object)item2?.spawnableItem == (Object)null) && item2.rarity > 0 && !ScrapCatalog.IsEnabled(item2.spawnableItem.itemName?.Trim() ?? ""))
				{
					changed.Add((item2, item2.rarity));
					item2.rarity = 0;
				}
			}
			if (changed.Count > 0)
			{
				Plugin.Log.LogInfo((object)$"Scrap library: {changed.Count} switched-off item(s) won't spawn this round.");
			}
		}

		[HarmonyFinalizer]
		private static void Finalizer()
		{
			foreach (var item3 in changed)
			{
				SpawnableItemWithRarity item = item3.entry;
				int item2 = item3.rarity;
				item.rarity = item2;
			}
			changed.Clear();
		}
	}
	internal static class ScrapThumbnails
	{
		public const int Size = 128;

		private static readonly string Folder = Path.Combine(Paths.CachePath, "CosmeticsMenuPlus", "scrap-v2");

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

		private static readonly HashSet<string> missing = new HashSet<string>();

		public static bool TryGet(string key, out Texture2D texture)
		{
			//IL_004e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0053: Unknown result type (might be due to invalid IL or missing references)
			//IL_0065: Expected O, but got Unknown
			if (loaded.TryGetValue(key, out texture) && (Object)(object)texture != (Object)null)
			{
				return true;
			}
			texture = null;
			if (missing.Contains(key))
			{
				return false;
			}
			string path = PathFor(key);
			if (!File.Exists(path))
			{
				missing.Add(key);
				return false;
			}
			try
			{
				Texture2D val = new Texture2D(2, 2, (TextureFormat)4, false)
				{
					name = "Scrap thumb " + key
				};
				if (!ImageConversion.LoadImage(val, File.ReadAllBytes(path)))
				{
					Object.Destroy((Object)(object)val);
					return false;
				}
				loaded[key] = (texture = val);
				return true;
			}
			catch (Exception ex)
			{
				Plugin.Log.LogWarning((object)("Couldn't load thumbnail for " + key + ": " + ex.Message));
				return false;
			}
		}

		public static bool Has(string key)
		{
			Texture2D texture;
			return TryGet(key, out texture);
		}

		public static void ClearAll()
		{
			foreach (Texture2D value in loaded.Values)
			{
				if ((Object)(object)value != (Object)null)
				{
					Object.Destroy((Object)(object)value);
				}
			}
			loaded.Clear();
			missing.Clear();
			try
			{
				if (Directory.Exists(Folder))
				{
					string[] files = Directory.GetFiles(Folder, "*.png");
					for (int i = 0; i < files.Length; i++)
					{
						File.Delete(files[i]);
					}
				}
			}
			catch (Exception ex)
			{
				Plugin.Log.LogWarning((object)("Couldn't clear thumbnails: " + ex.Message));
			}
		}

		public static void Capture(string key, Vector2 screenCenter, int side)
		{
			//IL_0034: 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_007e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0084: Expected O, but got Unknown
			//IL_00c1: 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_00d9: Expected O, but got Unknown
			//IL_00fe: Unknown result type (might be due to invalid IL or missing references)
			Texture2D val = ScreenCapture.CaptureScreenshotAsTexture();
			if ((Object)(object)val == (Object)null)
			{
				return;
			}
			try
			{
				side = Mathf.Min(new int[3]
				{
					side,
					((Texture)val).width,
					((Texture)val).height
				});
				int num = Mathf.Clamp(Mathf.RoundToInt(screenCenter.x - (float)side / 2f), 0, ((Texture)val).width - side);
				int num2 = Mathf.Clamp(Mathf.RoundToInt(screenCenter.y - (float)side / 2f), 0, ((Texture)val).height - side);
				Texture2D val2 = new Texture2D(side, side, (TextureFormat)4, false);
				val2.SetPixels(val.GetPixels(num, num2, side, side));
				val2.Apply();
				RenderTexture temporary = RenderTexture.GetTemporary(128, 128, 0, (RenderTextureFormat)0, (RenderTextureReadWrite)2);
				RenderTexture active = RenderTexture.active;
				Texture2D val3 = new Texture2D(128, 128, (TextureFormat)4, false)
				{
					name = "Scrap thumb " + key
				};
				try
				{
					Graphics.Blit((Texture)(object)val2, temporary);
					RenderTexture.active = temporary;
					val3.ReadPixels(new Rect(0f, 0f, 128f, 128f), 0, 0, false);
					val3.Apply();
				}
				finally
				{
					RenderTexture.active = active;
					RenderTexture.ReleaseTemporary(temporary);
					Object.Destroy((Object)(object)val2);
				}
				Directory.CreateDirectory(Folder);
				File.WriteAllBytes(PathFor(key), ImageConversion.EncodeToPNG(val3));
				if (loaded.TryGetValue(key, out var value) && (Object)(object)value != (Object)null)
				{
					Object.Destroy((Object)(object)value);
				}
				loaded[key] = val3;
				missing.Remove(key);
			}
			catch (Exception ex)
			{
				Plugin.Log.LogWarning((object)("Couldn't capture thumbnail for " + key + ": " + ex.Message));
			}
			finally
			{
				Object.Destroy((Object)(object)val);
			}
		}

		private static string PathFor(string key)
		{
			char[] bad = Path.GetInvalidFileNameChars();
			string arg = new string(key.Select((char c2) => (!bad.Contains(c2)) ? c2 : '_').ToArray());
			uint num = 2166136261u;
			foreach (char c in key)
			{
				num = (num ^ c) * 16777619;
			}
			return Path.Combine(Folder, $"{arg}_{num:x8}.png");
		}
	}
	internal static class SlotMenu
	{
		private class RightClick : MonoBehaviour, IPointerClickHandler, IEventSystemHandler
		{
			public Action action;

			public void OnPointerClick(PointerEventData e)
			{
				//IL_000a: Unknown result type (might be due to invalid IL or missing references)
				//IL_0010: Invalid comparison between Unknown and I4
				Mouse current = Mouse.current;
				bool num;
				if (current == null)
				{
					num = (int)e.button == 1;
				}
				else
				{
					if (!current.rightButton.wasReleasedThisFrame)
					{
						return;
					}
					num = !current.leftButton.wasReleasedThisFrame;
				}
				if (num)
				{
					action?.Invoke();
				}
			}
		}

		private class SearchDebounce : MonoBehaviour
		{
			private static string pending;

			private static float applyAt;

			public static void Queue(string text)
			{
				pending = text;
				applyAt = Time.unscaledTime + 0.15f;
			}

			public static void Cancel()
			{
				pending = null;
			}

			private void Update()
			{
				if (pending == null || Time.unscaledTime < applyAt)
				{
					return;
				}
				string text = pending;
				pending = null;
				if (!(text == query))
				{
					query = text;
					if (query.Length > 0)
					{
						suitView = false;
					}
					Refresh();
				}
			}
		}

		private class RefreshOnEnable : MonoBehaviour
		{
			private bool first = true;

			private void OnEnable()
			{
				if (first)
				{
					first = false;
					return;
				}
				Refresh();
				if (inGame)
				{
					ApplySuitToPreview(LocalPlayer()?.currentSuitID ?? (-1));
				}
			}
		}

		private class HistoryState
		{
			public List<string> Worn;

			public Dictionary<string, Tint> Tints;

			public int Suit;

			public HashSet<string> Favorites;

			public HashSet<string> Hidden;

			public string ActiveOutfit;
		}

		private class HistoryKeys : MonoBehaviour
		{
			private void Update()
			{
				Keyboard current = Keyboard.current;
				if (current == null || !current.ctrlKey.isPressed || scrapMode || ((Object)(object)search != (Object)null && search.isFocused))
				{
					return;
				}
				EventSystem current2 = EventSystem.current;
				GameObject val = (((Object)(object)current2 != (Object)null) ? current2.currentSelectedGameObject : null);
				if ((Object)(object)val != (Object)null && (Object)(object)val.GetComponent<TMP_InputField>() != (Object)null)
				{
					return;
				}
				if (((ButtonControl)current.zKey).wasPressedThisFrame)
				{
					if (current.shiftKey.isPressed)
					{
						Redo();
					}
					else
					{
						Undo();
					}
				}
				else if (((ButtonControl)current.yKey).wasPressedThisFrame)
				{
					Redo();
				}
			}
		}

		private enum ScrapFilter
		{
			All,
			Favorites,
			OneHanded,
			TwoHanded,
			Metal,
			Heavy,
			Valuable
		}

		private class CornerButtons : MonoBehaviour
		{
			private void OnEnable()
			{
				Show(visible: false);
			}

			private void OnDisable()
			{
				bool visible = !inGame;
				if (inGame)
				{
					QuickMenuManager val = Object.FindObjectOfType<QuickMenuManager>();
					visible = (Object)(object)val != (Object)null && val.isMenuOpen;
				}
				Show(visible);
			}

			private static void Show(bool visible)
			{
				if ((Object)(object)activateButton != (Object)null)
				{
					activateButton.SetActive(visible);
				}
				if ((Object)(object)scrapButton != (Object)null)
				{
					scrapButton.SetActive(visible);
				}
			}
		}

		private class ThumbnailRunner : MonoBehaviour
		{
			private void OnDisable()
			{
				generating = false;
			}
		}

		private class TintDebounce : MonoBehaviour
		{
			private static bool dirty;

			private static bool settlePending;

			private static bool syncPending;

			private static float lastChange;

			private static float syncAt;

			public static void MarkDirty()
			{
				dirty = true;
				settlePending = true;
				lastChange = Time.unscaledTime;
			}

			public static void FlushNow()
			{
				if (dirty || settlePending)
				{
					Apply();
				}
				if (syncPending)
				{
					Sync();
				}
			}

			private void OnDisable()
			{
				FlushNow();
			}

			private void Update()
			{
				if (dirty)
				{
					ApplyPreview();
				}
				if (settlePending && Time.unscaledTime - lastChange > 0.2f)
				{
					Apply();
				}
				if (syncPending && Time.unscaledTime > syncAt)
				{
					Sync();
				}
			}

			private static void ApplyPreview()
			{
				dirty = false;
				if (tintTarget != null)
				{
					Recolor.Preview = true;
					try
					{
						Tints.ReapplyLocal(tintTarget.Id);
					}
					finally
					{
						Recolor.Preview = false;
					}
					HashSet<string> hashSet = Tints.KeysInUse();
					hashSet.Add(Recolor.PreviewKey(editing));
					Recolor.Prune(hashSet);
				}
			}

			private static void Apply()
			{
				dirty = false;
				settlePending = false;
				Tints.ReapplyLocal();
				Recolor.Prune(Tints.KeysInUse());
				Tints.Save();
				AutoSaveOutfit();
				syncPending = true;
				syncAt = Time.unscaledTime + 0.5f;
			}

			private static void Sync()
			{
				syncPending = false;
				if ((Object)(object)StartOfRound.Instance != (Object)null && (Object)(object)StartOfRound.Instance.localPlayerController != (Object)null)
				{
					TintSync.SendLocal();
				}
			}
		}

		[Serializable]
		[CompilerGenerated]
		private sealed class <>c
		{
			public static readonly <>c <>9 = new <>c();

			public static Func<TMP_Text, TMP_FontAsset> <>9__38_0;

			public static Func<TMP_FontAsset, bool> <>9__38_1;

			public static Action <>9__41_0;

			public static Action <>9__41_1;

			public static UnityAction<string> <>9__41_2;

			public static Action <>9__43_0;

			public static Action <>9__43_1;

			public static Action <>9__45_0;

			public static Func<string, CosmeticEntry> <>9__59_2;

			public static Func<CosmeticEntry, bool> <>9__59_3;

			public static Func<CosmeticEntry, bool> <>9__59_0;

			public static Func<CosmeticEntry, bool> <>9__59_1;

			public static Func<UnlockableSuit, bool> <>9__63_0;

			public static Func<UnlockableSuit, int> <>9__63_1;

			public static Func<IGrouping<int, UnlockableSuit>, UnlockableSuit> <>9__63_2;

			public static Func<UnlockableSuit, int> <>9__63_3;

			public static Func<string, string> <>9__82_0;

			public static Func<Outfit, bool> <>9__91_0;

			public static Func<Outfit, string> <>9__95_0;

			public static Func<string, bool> <>9__97_0;

			public static Func<string, string> <>9__97_1;

			public static Action <>9__101_0;

			public static Action <>9__101_1;

			public static Action <>9__117_0;

			public static Action <>9__117_1;

			public static Action <>9__117_2;

			public static UnityAction <>9__119_0;

			public static UnityAction <>9__119_1;

			public static Func<ScrapEntry, bool> <>9__128_0;

			public static Func<ScrapEntry, bool> <>9__128_1;

			public static Func<ScrapEntry, bool> <>9__128_2;

			public static Func<ScrapEntry, bool> <>9__130_0;

			public static Func<ScrapEntry, bool> <>9__145_0;

			public static Action <>9__169_0;

			public static Action <>9__169_1;

			public static Action<float> <>9__169_2;

			public static Action<float> <>9__169_3;

			public static Action<float> <>9__169_4;

			internal TMP_FontAsset <Build>b__38_0(TMP_Text t)
			{
				return t.font;
			}

			internal bool <Build>b__38_1(TMP_FontAsset f)
			{
				return (Object)(object)f != (Object)null;
			}

			internal void <BuildTabs>b__41_0()
			{
				SetView(wearing: false);
			}

			internal void <BuildTabs>b__41_1()
			{
				SetView(wearing: true);
			}

			internal void <BuildTabs>b__41_2(string v)
			{
				SearchDebounce.Queue(v.Trim());
			}

			internal void <BuildGridArea>b__43_0()
			{
				CyclePack(-1);
			}

			internal void <BuildGridArea>b__43_1()
			{
				CyclePack(1);
			}

			internal void <SetupPreview>b__45_0()
			{
				preview?.ResetView();
			}

			internal CosmeticEntry <ItemsForView>b__59_2(string id)
			{
				return CosmeticCatalog.ById[id];
			}

			internal bool <ItemsForView>b__59_3(CosmeticEntry e)
			{
				return WornInSlot(e, slot);
			}

			internal bool <ItemsForView>b__59_0(CosmeticEntry e)
			{
				if (query.Length <= 0)
				{
					return InSlot(e, slot);
				}
				return !Store.Hidden.Contains(e.Id);
			}

			internal bool <ItemsForView>b__59_1(CosmeticEntry e)
			{
				return e.Pack == pack;
			}

			internal bool <AvailableSuits>b__63_0(UnlockableSuit s)
			{
				return (Object)(object)s != (Object)null;
			}

			internal int <AvailableSuits>b__63_1(UnlockableSuit s)
			{
				return s.syncedSuitID.Value;
			}

			internal UnlockableSuit <AvailableSuits>b__63_2(IGrouping<int, UnlockableSuit> g)
			{
				return g.First();
			}

			internal int <AvailableSuits>b__63_3(UnlockableSuit s)
			{
				return s.syncedSuitID.Value;
			}

			internal string <Capture>b__82_0(string id)
			{
				return id;
			}

			internal bool <get_ActiveOutfit>b__91_0(Outfit o)
			{
				return o.Name == Plugin.ActiveOutfit.Value;
			}

			internal string <NextOutfitName>b__95_0(Outfit o)
			{
				return o.Name;
			}

			internal bool <Snapshot>b__97_0(string id)
			{
				return !CosmeticRegistry.cosmeticInstances.ContainsKey(id);
			}

			internal string <Snapshot>b__97_1(string id)
			{
				return id;
			}

			internal void <ToggleOutfitManager>b__101_0()
			{
				CreateOutfitFromCurrent();
				ClosePopover();
				Refresh();
				ToggleOutfitManager();
			}

			internal void <ToggleOutfitManager>b__101_1()
			{
				ClosePopover();
				UpdateOutfitButton();
			}

			internal void <BuildScrapRail>b__117_0()
			{
				SetVisibleScrap(on: true);
			}

			internal void <BuildScrapRail>b__117_1()
			{
				SetVisibleScrap(on: false);
			}

			internal void <BuildScrapRail>b__117_2()
			{
				if (!generating)
				{
					ScrapThumbnails.ClearAll();
					Refresh();
				}
			}

			internal void <BuildScrapButton>b__119_0()
			{
				SetMode(scrap: false);
			}

			internal void <BuildScrapButton>b__119_1()
			{
				SetMode(scrap: true);
				((Component)screen).gameObject.SetActive(true);
			}

			internal bool <ScrapForView>b__128_0(ScrapEntry e)
			{
				return !ScrapCatalog.IsEnabled(e.Key);
			}

			internal bool <ScrapForView>b__128_1(ScrapEntry e)
			{
				return InScrapFilter(e, scrapFilter);
			}

			internal bool <ScrapForView>b__128_2(ScrapEntry e)
			{
				return e.Source == scrapSource;
			}

			internal bool <RefreshScrapVisuals>b__130_0(ScrapEntry e)
			{
				return !ScrapCatalog.IsEnabled(e.Key);
			}

			internal bool <StartThumbnails>b__145_0(ScrapEntry e)
			{
				return !ScrapThumbnails.Has(e.Key);
			}

			internal void <BuildTintEditor>b__169_0()
			{
				SetMode(TintMode.HueShift);
			}

			internal void <BuildTintEditor>b__169_1()
			{
				SetMode(TintMode.Tint);
			}

			internal void <BuildTintEditor>b__169_2(float v)
			{
				editing.Hue = v;
				Changed();
			}

			internal void <BuildTintEditor>b__169_3(float v)
			{
				editing.Saturation = v;
				Changed();
			}

			internal void <BuildTintEditor>b__169_4(float v)
			{
				editing.Brightness = v;
				Changed();
			}
		}

		private static readonly string[] OriginalParts = new string[7] { "CosmeticsHolderBG", "CosmeticsHolderBorder", "Scrollbar", "CosmeticsHolder", "EnableButton", "DisableButton", "DisableCosmeticsText" };

		private static readonly Slot[] RailSlots = new Slot[9]
		{
			Slot.All,
			Slot.Favorites,
			Slot.Head,
			Slot.Chest,
			Slot.Hip,
			Slot.RightArm,
			Slot.LeftLeg,
			Slot.RightLeg,
			Slot.Hidden
		};

		private const float DesignHalfWidth = 480f;

		private const float DesignHalfHeight = 265f;

		private static readonly Vector2 LeftPos = new Vector2(-160f, 0f);

		private static readonly Vector2 LeftSize = new Vector2(620f, 510f);

		private static readonly Vector2 PreviewPos = new Vector2(315f, 0f);

		private static readonly Vector2 PreviewSize = new Vector2(310f, 510f);

		private static readonly Vector2 GridPos = new Vector2(66f, -19f);

		private static readonly Vector2 GridSize = new Vector2(468f, 370f);

		private const int GridColumns = 5;

		private static bool inGame;

		private static bool wearingView;

		private static bool suitView;

		private static Transform screen;

		private static Transform holder;

		private static RectTransform left;

		private static RectTransform content;

		private static RectTransform popover;

		private static ScrollRect scroll;

		private static TextMeshProUGUI packLabel;

		private static GameObject packRow;

		private static TMP_InputField search;

		private static Button outfitButton;

		private static Button undoButton;

		private static Button redoButton;

		private static TextMeshProUGUI outfitLabel;

		private static Button browseTab;

		private static Button wearingTab;

		private static Button suitButton;

		private static PreviewControls preview;

		private static readonly Dictionary<Slot, (Button button, TextMeshProUGUI count)> railButtons = new Dictionary<Slot, (Button, TextMeshProUGUI)>();

		private static readonly List<Action> itemRefreshers = new List<Action>();

		private static Slot slot = Slot.All;

		private static string pack;

		private static string query = "";

		private static readonly List<string> removedThisSession = new List<string>();

		private static int previewSuitId = -1;

		private const int HistoryLimit = 60;

		private static readonly List<HistoryState> undoStack = new List<HistoryState>();

		private static readonly List<HistoryState> redoStack = new List<HistoryState>();

		private static bool restoring;

		private static readonly (ScrapFilter filter, string label)[] ScrapRail = new(ScrapFilter, string)[7]
		{
			(ScrapFilter.All, "All"),
			(ScrapFilter.Favorites, "Favorites"),
			(ScrapFilter.OneHanded, "One-handed"),
			(ScrapFilter.TwoHanded, "Two-handed"),
			(ScrapFilter.Metal, "Metal"),
			(ScrapFilter.Heavy, "Heavy 30lb+"),
			(ScrapFilter.Valuable, "Worth 80+")
		};

		private static bool scrapMode;

		private static ScrapFilter scrapFilter = ScrapFilter.All;

		private static string scrapSource;

		private static ScrapEntry selectedScrap;

		private static readonly Dictionary<ScrapFilter, (Button button, TextMeshProUGUI count)> scrapRailButtons = new Dictionary<ScrapFilter, (Button, TextMeshProUGUI)>();

		private static GameObject scrapBar;

		private static Button clearButton;

		private static Transform scrapHolder;

		private static Transform scrapSpin;

		private static PreviewControls scrapPreview;

		private static TextMeshProUGUI scrapInfo;

		private static GameObject scrapButton;

		private static GameObject activateButton;

		private static readonly string[] HelperLayers = new string[4] { "ScanNode", "Triggers", "InteractableObject", "Ignore Raycast" };

		private static readonly string[] HelperNames = new string[6] { "scannode", "scan node", "trigger", "collider", "hitbox", "bounds" };

		private static ThumbnailRunner runner;

		private static bool generating;

		private static readonly float[] PresetHues = new float[8] { 0f, 30f, 60f, 120f, 180f, 220f, 280f, 330f };

		private static RectTransform tintPanel;

		private static CosmeticEntry tintTarget;

		private static Tint editing;

		private static Slider hueSlider;

		private static Slider satSlider;

		private static Slider brightSlider;

		private static TextMeshProUGUI hueValue;

		private static TextMeshProUGUI satValue;

		private static TextMeshProUGUI brightValue;

		private static TextMeshProUGUI tintNote;

		private static Button shiftButton;

		private static Button tintModeButton;

		private static GameObject tintControls;

		private static bool settingSliders;

		private static TextMeshProUGUI tintTitle;

		private static readonly Vector2 TintPos = new Vector2(66f, -2f);

		private static readonly Vector2 TintSize = new Vector2(468f, 404f);

		private static bool tintHistoryPushed;

		private static Outfit ActiveOutfit
		{
			get
			{
				if (!string.IsNullOrEmpty(Plugin.ActiveOutfit.Value))
				{
					return Store.Outfits.FirstOrDefault((Outfit o) => o.Name == Plugin.ActiveOutfit.Value);
				}
				return null;
			}
		}

		public static void Build(Transform globalScale, bool isInGame)
		{
			//IL_016a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0179: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ae: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c7: Unknown result type (might be due to invalid IL or missing references)
			inGame = isInGame;
			screen = globalScale.Find("CosmeticsScreen");
			holder = screen.Find("ObjectHolder");
			Ui.Font = (from t in ((Component)globalScale).GetComponentsInChildren<TMP_Text>(true)
				select t.font).FirstOrDefault((Func<TMP_FontAsset, bool>)((TMP_FontAsset f) => (Object)(object)f != (Object)null));
			Store.Load();
			CosmeticCatalog.Refresh();
			railButtons.Clear();
			itemRefreshers.Clear();
			previewSuitId = -1;
			query = "";
			popover = null;
			suitView = false;
			scrapMode = false;
			selectedScrap = null;
			if (!Enum.TryParse<Slot>(Plugin.LastSlot.Value, out slot) || Array.IndexOf(RailSlots, slot) < 0)
			{
				slot = Slot.All;
			}
			string[] originalParts = OriginalParts;
			foreach (string text in originalParts)
			{
				Transform obj = screen.Find(text);
				if (obj != null)
				{
					((Component)obj).gameObject.SetActive(false);
				}
			}
			if (!MainClass.cosmeticsSyncOther.Value)
			{
				MainClass.cosmeticsSyncOther.Value = true;
				MainClass.StaticConfig.Save();
			}
			DisplayScale.Capture(holder.Find("ScavengerModel"));
			FitToScreen();
			RectTransform val = Ui.Rect("CosmeticsMenuPlus", screen, Vector2.zero, new Vector2(960f, 530f));
			((Component)val).gameObject.AddComponent<RefreshOnEnable>();
			((Component)val).gameObject.AddComponent<HistoryKeys>();
			((Component)val).gameObject.AddComponent<SearchDebounce>();
			left = Ui.Rect("Browser", (Transform)(object)val, LeftPos, LeftSize);
			Ui.Image(left, Ui.Panel);
			BuildTabs();
			BuildRail();
			BuildGridArea();
			BuildBottomBar();
			BuildTintEditor(left);
			SetupPreview(val);
			BuildScrapRail();
			SetupScrapPreview();
			BuildScrapButton(globalScale);
			Refresh();
			Tints.ReapplyLocal();
		}

		private static void FitToScreen()
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Expected O, but got Unknown
			//IL_0026: 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_0059: 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_007f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0086: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00eb: Unknown result type (might be due to invalid IL or missing references)
			RectTransform val = (RectTransform)screen;
			Canvas componentInParent = ((Component)screen).GetComponentInParent<Canvas>(true);
			Camera val2 = (((Object)(object)componentInParent != (Object)null && (int)componentInParent.rootCanvas.renderMode != 0) ? componentInParent.rootCanvas.worldCamera : null);
			Vector2 val3 = default(Vector2);
			Vector2 val4 = default(Vector2);
			if (RectTransformUtility.ScreenPointToLocalPointInRectangle(val, Vector2.zero, val2, ref val3) && RectTransformUtility.ScreenPointToLocalPointInRectangle(val, new Vector2((float)Screen.width, (float)Screen.height), val2, ref val4))
			{
				float num = (val4.x - val3.x) / 2f;
				float num2 = (val4.y - val3.y) / 2f;
				float num3 = Mathf.Min(new float[3]
				{
					1f,
					(num - 10f) / 480f,
					(num2 - 5f) / 265f
				});
				if (num3 > 0.2f && num3 < 0.999f)
				{
					Transform obj = screen;
					obj.localScale *= num3;
				}
			}
		}

		public static void RestoreOriginal(Transform globalScale)
		{
			Transform val = globalScale.Find("CosmeticsScreen");
			if ((Object)(object)val == (Object)null)
			{
				return;
			}
			string[] originalParts = OriginalParts;
			foreach (string text in originalParts)
			{
				Transform obj = val.Find(text);
				if (obj != null)
				{
					((Component)obj).gameObject.SetActive(true);
				}
			}
			originalParts = new string[2] { "CosmeticsMenuPlus", "PreviewPanel" };
			foreach (string text2 in originalParts)
			{
				Transform val2 = val.Find(text2);
				if ((Object)(object)val2 != (Object)null)
				{
					Object.Destroy((Object)(object)((Component)val2).gameObject);
				}
			}
		}

		private static void BuildTabs()
		{
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_006f: 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_00c5: 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)
			browseTab = Ui.MakeButton((Transform)(object)left, "Browse", new Vector2(-248f, 225f), new Vector2(104f, 32f), "Browse", delegate
			{
				SetView(wearing: false);
			}, 15f);
			wearingTab = Ui.MakeButton((Transform)(object)left, "Wearing", new Vector2(-138f, 225f), new Vector2(104f, 32f), "Current", delegate
			{
				SetView(wearing: true);
			}, 15f);
			search = Ui.InputField((Transform)(object)left, new Vector2(111f, 225f), new Vector2(378f, 32f), "Search cosmetics", 14f);
			((UnityEvent<string>)(object)search.onValueChanged).AddListener((UnityAction<string>)delegate(string v)
			{
				SearchDebounce.Queue(v.Trim());
			});
		}

		private static void BuildRail()
		{
			//IL_0048: 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_0088: Unknown result type (might be due to invalid IL or missing references)
			//IL_009c: 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)
			//IL_00d1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f9: Unknown result type (might be due to invalid IL or missing references)
			float num = 185f;
			Slot[] railSlots = RailSlots;
			for (int i = 0; i < railSlots.Length; i++)
			{
				Slot slot = railSlots[i];
				Slot captured = slot;
				Button val = Ui.MakeButton((Transform)(object)left, "Rail_" + slot, new Vector2(-239f, num), new Vector2(122f, 32f), null, delegate
				{
					SelectSlot(captured);
				});
				Ui.Label(((Component)val).transform, CosmeticCatalog.SlotLabel(slot), 14f, Ui.Text, (TextAlignmentOptions)513, (Vector2?)new Vector2(-12f, 0f), (Vector2?)new Vector2(90f, 30f));
				TextMeshProUGUI item = Ui.Label(((Component)val).transform, "", 13f, Ui.TextMuted, (TextAlignmentOptions)516, (Vector2?)new Vector2(44f, 0f), (Vector2?)new Vector2(26f, 30f));
				railButtons[slot] = (val, item);
				num -= ((slot == Slot.Favorites || slot == Slot.RightLeg) ? 46f : 38f);
			}
		}

		private static void BuildGridArea()
		{
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			//IL_005a: 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_00b6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c5: Unknown result type (might be due to invalid IL or missing references)
			//IL_010d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0117: Unknown result type (might be due to invalid IL or missing references)
			//IL_012b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0144: Unknown result type (might be due to invalid IL or missing references)
			//IL_0149: Unknown result type (might be due to invalid IL or missing references)
			packRow = ((Component)Ui.Rect("PackFilter", (Transform)(object)left, new Vector2(GridPos.x, 185f), new Vector2(GridSize.x, 32f))).gameObject;
			Ui.MakeButton(packRow.transform, "PrevPack", new Vector2(-218f, 0f), new Vector2(32f, 32f), "<", delegate
			{
				CyclePack(-1);
			}, 16f);
			Ui.MakeButton(packRow.transform, "NextPack", new Vector2(218f, 0f), new Vector2(32f, 32f), ">", delegate
			{
				CyclePack(1);
			}, 16f);
			packLabel = Ui.Label(packRow.transform, "", 14f, Ui.Text, (TextAlignmentOptions)514, (Vector2?)Vector2.zero, (Vector2?)new Vector2(390f, 30f));
			content = Ui.ScrollView((Transform)(object)left, GridPos, GridSize, out scroll);
		}

		private static void BuildBottomBar()
		{
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: 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_00a1: 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)
			//IL_00f8: Unknown result type (might be due to invalid IL or missing references)
			//IL_0107: Unknown result type (might be due to invalid IL or missing references)
			//IL_014f: Unknown result type (might be due to invalid IL or missing references)
			//IL_015e: Unknown result type (might be due to invalid IL or missing references)
			outfitButton = Ui.MakeButton((Transform)(object)left, "Outfits", new Vector2(-215f, -228f), new Vector2(170f, 30f), null, ToggleOutfitManager);
			outfitLabel = Ui.Label(((Component)outfitButton).transform, "", 13f, Ui.Text, (TextAlignmentOptions)514);
			undoButton = Ui.MakeButton((Transform)(object)left, "Undo", new Vector2(-92f, -228f), new Vector2(60f, 30f), "Undo", Undo, 12f);
			redoButton = Ui.MakeButton((Transform)(object)left, "Redo", new Vector2(-26f, -228f), new Vector2(60f, 30f), "Redo", Redo, 12f);
			clearButton = Ui.MakeButton((Transform)(object)left, "ClearAll", new Vector2(270f, -228f), new Vector2(60f, 30f), "Clear", ClearAll, 12f);
			UpdateHistoryButtons();
		}

		private static void SetupPreview(RectTransform root)
		{
			//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_003f: 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_007a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0080: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b4: Unknown result type (might be due to invalid IL or missing references)
			//IL_0103: Unknown result type (might be due to invalid IL or missing references)
			//IL_0112: Unknown result type (might be due to invalid IL or missing references)
			//IL_0188: Unknown result type (might be due to invalid IL or missing references)
			//IL_0193: Unknown result type (might be due to invalid IL or missing references)
			//IL_019d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0254: Unknown result type (might be due to invalid IL or missing references)
			//IL_025e: Expected O, but got Unknown
			Transform val = holder.Find("ScavengerModel");
			RectTransform val2 = Ui.Rect("PreviewPanel", screen, PreviewPos, PreviewSize);
			Ui.Image(val2, new Color(0.05f, 0.03f, 0.02f, 0.6f), raycast: false);
			((Transform)val2).SetSiblingIndex(holder.GetSiblingIndex());
			Vector3 localPosition = holder.localPosition;
			holder.localPosition = new Vector3(PreviewPos.x, 0f, localPosition.z);
			Ui.MakeButton((Transform)(object)root, "ResetView", new Vector2(PreviewPos.x + 95f, -228f), new Vector2(100f, 30f), "Reset view", delegate
			{
				preview?.ResetView();
			}, 12f);
			suitButton = Ui.MakeButton((Transform)(object)root, "ChangeSuit", new Vector2(PreviewPos.x - 23f, -228f), new Vector2(120f, 30f), "Change suit", ToggleSuitPicker, 12f);
			((Component)suitButton).gameObject.SetActive(inGame);
			Transform obj = screen.Find("ExitButton");
			RectTransform val3 = (RectTransform)(object)((obj is RectTransform) ? obj : null);
			if (val3 != null)
			{
				val3.anchoredPosition = new Vector2(PreviewPos.x + 133f, 232f);
				((Transform)val3).localScale = Vector3.one * 0.28f;
				((Transform)val3).SetAsLastSibling();
			}
			if (!((Object)(object)val == (Object)null))
			{
				Transform val4 = screen.Find("SpinAreaButton");
				SpinDragger val5 = (((Object)(object)val4 != (Object)null) ? ((Component)val4).GetComponent<SpinDragger>() : null);
				Transform spinTarget = (((Object)(object)val5 != (Object)null && (Object)(object)val5.target != (Object)null) ? val5.target.transform : val);
				if ((Object)(object)val4 != (Object)null)
				{
					((Component)val4).gameObject.SetActive(false);
				}
				preview = ((Component)val2).gameObject.AddComponent<PreviewControls>();
				preview.spinTarget = spinTarget;
				preview.holder = holder;
				preview.space = (RectTransform)screen;
				preview.area = val2;
				preview.Init();
				if (inGame)
				{
					ApplySuitToPreview(LocalPlayer()?.currentSuitID ?? (-1));
				}
			}
		}

		private static void SetView(bool wearing)
		{
			wearingView = wearing;
			suitView = false;
			Refresh();
		}

		private static void SelectSlot(Slot s)
		{
			slot = s;
			suitView = false;
			Plugin.LastSlot.Value = s.ToString();
			SearchDebounce.Cancel();
			if (query.Length > 0 || search.text.Length > 0)
			{
				search.SetTextWithoutNotify(query = "");
			}
			Refresh();
		}

		private static void CyclePack(int dir)
		{
			if (scrapMode)
			{
				CycleScrapSource(dir);
				return;
			}
			List<string> packs = CosmeticCatalog.Packs;
			if (packs.Count == 0)
			{
				return;
			}
			int num = ((pack == null) ? (-1) : packs.IndexOf(pack));
			for (int i = 0; i <= packs.Count; i++)
			{
				num += dir;
				if (num >= packs.Count)
				{
					num = -1;
				}
				if (num < -1)
				{
					num = packs.Count - 1;
				}
				pack = ((num < 0) ? null : packs[num]);
				if (pack == null || ItemsForView().Count > 0)
				{
					break;
				}
			}
			Refresh();
		}

		private static void Toggle(string id)
		{
			PushHistory();
			CosmeticRegistry.ToggleCosmetic(id);
			AfterEquipChange();
			if (CosmeticRegistry.IsEquipped(id))
			{
				removedThisSession.Remove(id);
			}
			else if (!removedThisSession.Contains(id))
			{
				removedThisSession.Add(id);
			}
			AutoSaveOutfit();
			RefreshVisuals();
		}

		private static void ToggleFavorite(string id)
		{
			PushHistory();
			Store.ToggleFavorite(id);
			if (slot == Slot.Favorites)
			{
				Refresh();
			}
			else
			{
				RefreshVisuals();
			}
		}

		private static void ToggleHidden(string id)
		{
			PushHistory();
			Store.SetHidden(id, !Store.Hidden.Contains(id));
			if (slot == Slot.Hidden && Store.Hidden.Count == 0)
			{
				slot = Slot.All;
			}
			Refresh();
		}

		private static void ClearAll()
		{
			PushHistory();
			SetActiveOutfit(null);
			foreach (string locallySelectedCosmetic in CosmeticRegistry.locallySelectedCosmetics)
			{
				if (!removedThisSession.Contains(locallySelectedCosmetic))
				{
					removedThisSession.Add(locallySelectedCosmetic);
				}
			}
			CosmeticRegistry.locallySelectedCosmetics.Clear();
			AfterEquipChange();
			SyncIfInGame();
			Refresh();
		}

		private static void AfterEquipChange()
		{
			MainClass.WriteCosmeticsToFile();
			CosmeticRegistry.UpdateCosmeticsOnDisplayGuy(true);
		}

		private static void SyncIfInGame()
		{
			if ((Object)(object)StartOfRound.Instance != (Object)null && (Object)(object)StartOfRound.Instance.localPlayerController != (Object)null)
			{
				CosmeticSyncPatch.SyncCosmeticsToOtherClients((PlayerControllerB)null, false, false);
			}
		}

		internal static void Refresh()
		{
			if ((Object)(object)content == (Object)null)
			{
				return;
			}
			HideTintIfOpen();
			ClosePopover();
			CosmeticCatalog.Refresh();
			itemRefreshers.Clear();
			Ui.Clear((Transform)(object)content);
			if (slot == Slot.Hidden && Store.Hidden.Count == 0)
			{
				slot = Slot.All;
			}
			ApplyModeChrome();
			if (scrapMode)
			{
				packRow.SetActive(true);
				BuildScrapView();
				scroll.verticalNormalizedPosition = 1f;
				RefreshVisuals();
				return;
			}
			packRow.SetActive(!suitView);
			((TMP_Text)((Component)suitButton).GetComponentInChildren<TextMeshProUGUI>()).text = (suitView ? "Back" : "Change suit");
			if (suitView)
			{
				BuildSuits();
			}
			else
			{
				List<CosmeticEntry> list = ItemsForView();
				if (list.Count == 0)
				{
					EmptyNote(EmptyText());
				}
				else
				{
					BuildGrid(list);
				}
				((TMP_Text)packLabel).text = (pack ?? "All packs") + "  ·  " + list.Count;
			}
			scroll.verticalNormalizedPosition = 1f;
			UpdateOutfitButton();
			RefreshVisuals();
		}

		private static string EmptyText()
		{
			if (query.Length > 0)
			{
				return "No cosmetics match \"" + query + "\".";
			}
			if (wearingView)
			{
				if (slot != Slot.All)
				{
					return "Nothing on this slot.";
				}
				return "You're not wearing anything yet. Pick some in Browse.";
			}
			if (slot == Slot.Favorites)
			{
				return "No favorites yet. Click the * on any cosmetic.";
			}
			return "No cosmetics here for this pack.";
		}

		private static bool InSlot(CosmeticEntry e, Slot s)
		{
			switch (s)
			{
			case Slot.All:
				return !Store.Hidden.Contains(e.Id);
			case Slot.Favorites:
				if (Store.Favorites.Contains(e.Id))
				{
					return !Store.Hidden.Contains(e.Id);
				}
				return false;
			case Slot.Hidden:
				return Store.Hidden.Contains(e.Id);
			default:
				if (e.Slot == s)
				{
					return !Store.Hidden.Contains(e.Id);
				}
				return false;
			}
		}

		private static bool WornInSlot(CosmeticEntry e, Slot s)
		{
			return s switch
			{
				Slot.All => true, 
				Slot.Favorites => Store.Favorites.Contains(e.Id), 
				Slot.Hidden => Store.Hidden.Contains(e.Id), 
				_ => e.Slot == s, 
			};
		}

		private static List<CosmeticEntry> ItemsForView()
		{
			IEnumerable<CosmeticEntry> source = ((!wearingView) ? CosmeticCatalog.Entries.Where((CosmeticEntry e) => (query.Length <= 0) ? InSlot(e, slot) : (!Store.Hidden.Contains(e.Id))) : (from id in CosmeticRegistry.locallySelectedCosmetics.Concat(removedThisSession).Distinct().Where(CosmeticCatalog.ById.ContainsKey)
				select CosmeticCatalog.ById[id] into e
				where WornInSlot(e, slot)
				select e));
			if (query.Length > 0)
			{
				string q = query.ToLowerInvariant();
				source = source.Where((CosmeticEntry e) => e.Name.ToLowerInvariant().Contains(q) || e.Pack.ToLowerInvariant().Contains(q) || e.Id.ToLowerInvariant().Contains(q));
			}
			if (pack != null)
			{
				source = source.Where((CosmeticEntry e) => e.Pack == pack);
			}
			return source.ToList();
		}

		private static void RefreshVisuals()
		{
			//IL_005f: 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_007c: 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_00e7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ee: Unknown result type (might be due to invalid IL or missing references)
			foreach (Action itemRefresher in itemRefreshers)
			{
				itemRefresher();
			}
			if (scrapMode)
			{
				RefreshScrapVisuals();
				return;
			}
			List<string> locallySelectedCosmetics = CosmeticRegistry.locallySelectedCosmetics;
			Ui.SetIdleColor(browseTab, (wearingView || suitView) ? Ui.Button : Ui.AccentDim);
			Ui.SetIdleColor(wearingTab, (wearingView && !suitView) ? Ui.AccentDim : Ui.Button);
			foreach (KeyValuePair<Slot, (Button, TextMeshProUGUI)> railButton in railButtons)
			{
				Slot s = railButton.Key;
				Ui.SetIdleColor(railButton.Value.Item1, (s == slot && query.Length == 0 && !suitView) ? Ui.AccentDim : Ui.Button);
				int num;
				switch (s)
				{
				case Slot.All:
					num = locallySelectedCosmetics.Count;
					break;
				case Slot.Favorites:
					num = Store.Favorites.Count;
					break;
				case Slot.Hidden:
					num = Store.Hidden.Count;
					((Component)railButton.Value.Item1).gameObject.SetActive(num > 0);
					break;
				default:
				{
					num = locallySelectedCosmetics.Count((string id) => CosmeticCatalog.ById.TryGetValue(id, out var value) && value.Slot == s);
					break;
				}
				}
				((TMP_Text)railButton.Value.Item2).text = ((num > 0) ? num.ToString() : "");
			}
		}

		private static void BuildGrid(List<CosmeticEntry> items)
		{
			//IL_001a: 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_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0048: Expected O, but got Unknown
			//IL_00c7: 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_012a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0144: Unknown result type (might be due to invalid IL or missing references)
			//IL_016e: Unknown result type (might be due to invalid IL or missing references)
			//IL_019d: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b1: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c5: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ef: Unknown result type (might be due to invalid IL or missing references)
			//IL_01fe: Unknown result type (might be due to invalid IL or missing references)
			//IL_0239: Unknown result type (might be due to invalid IL or missing references)
			//IL_026a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0279: Unknown result type (might be due to invalid IL or missing references)
			//IL_02c2: Unknown result type (might be due to invalid IL or missing references)
			//IL_02d1: Unknown result type (might be due to invalid IL or missing references)
			//IL_02e0: Unknown result type (might be due to invalid IL or missing references)
			GridLayoutGroup obj = ((Component)content).gameObject.AddComponent<GridLayoutGroup>();
			obj.cellSize = new Vector2(86f, 98f);
			obj.spacing = new Vector2(6f, 6f);
			((LayoutGroup)obj).padding = new RectOffset(6, 6, 6, 6);
			obj.constraint = (Constraint)1;
			obj.constraintCount = 5;
			foreach (CosmeticEntry entry in items)
			{
				string id = entry.Id;
				bool hiddenView = slot == Slot.Hidden && !wearingView;
				Button cell = Ui.MakeButton((Transform)(object)content, "Item_" + id, Vector2.zero, Vector2.zero, null, delegate
				{
					if (hiddenView)
					{
						ToggleHidden(id);
					}
					else
					{
						Toggle(id);
					}
				});
				((Component)cell).gameObject.AddComponent<RightClick>().action = delegate
				{
					ToggleHidden(id);
				};
				Outline outline = ((Component)cell).gameObject.AddComponent<Outline>();
				((Shadow)outline).effectColor = Ui.Accent;
				((Shadow)outline).effectDistance = new Vector2(2f, -2f);
				Icon(((Component)cell).transform, entry, new Vector2(0f, 9f), 68f);
				Ui.Label(((Component)cell).transform, entry.Name, 11f, Ui.Text, (TextAlignmentOptions)514, (Vector2?)new Vector2(0f, -39f), (Vector2?)new Vector2(84f, 18f));
				Button val = SmallButton(Ui.Rect("Fav", ((Component)cell).transform, new Vector2(-31f, 37f), new Vector2(20f, 20f)), "*", delegate
				{
					ToggleFavorite(id);
				}, 17f);
				Ui.SetIdleColor(val, new Color(0f, 0f, 0f, 0.35f));
				TextMeshProUGUI favText = ((Component)val).GetComponentInChildren<TextMeshProUGUI>();
				Button tint = SmallButton(Ui.Rect("Tint", ((Component)cell).transform, new Vector2(28f, 38f), new Vector2(28f, 18f)), "Tint", delegate
				{
					OpenTint(entry);
				}, 9f);
				RectTransform rt = Ui.Rect("TintDot", ((Component)cell).transform, new Vector2(-1f, 38f), new Vector2(10f, 10f));
				Image dot = Ui.Image(rt, Color.white, raycast: false);
				itemRefreshers.Add(delegate
				{
					//IL_0028: Unknown result type (might be due to invalid IL or missing references)
					//IL_0021: Unknown result type (might be due to invalid IL or missing references)
					//IL_0069: Unknown result type (might be due to invalid IL or missing references)
					//IL_00a5: 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_00db: Unknown result type (might be due to invalid IL or missing references)
					bool flag = CosmeticRegistry.IsEquipped(id);
					((Behaviour)outline).enabled = flag;
					Ui.SetIdleColor(cell, flag ? Ui.AccentDim : Ui.Button);
					((Component)tint).gameObject.SetActive(flag && entry.Tintable && !hiddenView);
					Ui.SetIdleColor(tint, Ui.Button);
					bool flag2 = !Tints.GetLocal(id).IsNone;
					((Behaviour)dot).enabled = flag2;
					if (flag2)
					{
						((Graphic)dot).color = SwatchColor(id);
					}
					((Graphic)favText).color = (Color)(Store.Favorites.Contains(id) ? Ui.Accent : new Color(1f, 1f, 1f, 0.25f));
				});
			}
		}

		private static PlayerControllerB LocalPlayer()
		{
			if (!((Object)(object)GameNetworkManager.Instance != (Object)null))
			{
				return null;
			}
			return GameNetworkManager.Instance.localPlayerController;
		}

		private static List<UnlockableSuit> AvailableSuits()
		{
			if (!inGame || (Object)(object)StartOfRound.Instance == (Object)null)
			{
				return new List<UnlockableSuit>();
			}
			return (from s in Object.FindObjectsOfType<UnlockableSuit>(true)
				where (Object)(object)s != (Object)null
				group s by s.syncedSuitID.Value into g
				select g.First() into s
				orderby s.syncedSuitID.Value
				select s).ToList();
		}

		private static string SuitName(int suitId)
		{
			if ((Object)(object)StartOfRound.Instance == (Object)null || suitId < 0)
			{
				return null;
			}
			List<UnlockableItem> unlockables = StartOfRound.Instance.unlockablesList.unlockables;
			if (suitId >= unlockables.Count)
			{
				return null;
			}
			return unlockables[suitId].unlockableName;
		}

		private static void WearSuit(UnlockableSuit suit, int suitId, bool recordHistory = true)
		{
			PlayerControllerB val = LocalPlayer();
			if (!((Object)(object)val == (Object)null) && !((Object)(object)suit == (Object)null))
			{
				if (recordHistory && val.currentSuitID != suitId)
				{
					PushHistory();
				}
				suit.SwitchSuitToThis(val);
				ApplySuitToPreview(suitId);
				AutoSaveOutfit();
				RefreshVisuals();
			}
		}

		private static void ToggleSuitPicker()
		{
			suitView = !suitView;
			Refresh();
		}

		private static void BuildSuits()
		{
			//IL_0033: 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_0057: Unknown result type (might be due to invalid IL or missing references)
			//IL_0061: Expected O, but got Unknown
			//IL_00fb: Unknown result type (might be due to invalid IL or missing references)
			//IL_0100: Unknown result type (might be due to invalid IL or missing references)
			//IL_0141: Unknown result type (might be due to invalid IL or missing references)
			//IL_015c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0181: Unknown result type (might be due to invalid IL or missing references)
			//IL_0190: Unknown result type (might be due to invalid IL or missing references)
			//IL_01fa: Unknown result type (might be due to invalid IL or missing references)
			//IL_0220: Unknown result type (might be due to invalid IL or m