Decompiled source of CraftingBrowser v1.0.0

CraftingBrowser.dll

Decompiled 2 weeks ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Text;
using BepInEx;
using BepInEx.Configuration;
using HarmonyLib;
using Jotunn;
using Microsoft.CodeAnalysis;
using Newtonsoft.Json;
using UnityEngine;

[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("CraftingBrowser")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0+901b84ab23f2f10926b13865f9b40bb283490874")]
[assembly: AssemblyProduct("CraftingBrowser")]
[assembly: AssemblyTitle("CraftingBrowser")]
[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 CraftingBrowser
{
	public class BrowserGUI : MonoBehaviour
	{
		private bool m_open;

		private bool m_isFullscreen;

		private int m_tabIndex;

		private int m_subIndex;

		private string m_search = "";

		private VisibilityMode m_mode;

		private readonly List<RecipeEntry> m_visible = new List<RecipeEntry>();

		private readonly Dictionary<int, int> m_subCounts = new Dictionary<int, int>();

		private readonly List<ItemData> m_ownedCopies = new List<ItemData>();

		private RecipeEntry m_selected;

		private int m_selectedCopy;

		private Vector2 m_sidebarScroll;

		private Vector2 m_detailsScroll;

		private int m_gridRow;

		private int m_gridCols = 8;

		private float m_lastClickTime;

		private int m_lastClickedIndex = -1;

		private string m_status = "";

		private float m_statusTimer;

		private bool m_wasCrafting;

		private string m_pendingCraftName;

		private string m_recentlyCrafted;

		private Texture2D m_whiteTex;

		private static readonly Color ColBackdrop = new Color(0f, 0f, 0f, 0.8f);

		private static readonly Color ColWindowBg = new Color(0.08f, 0.1f, 0.14f, 0.99f);

		private static readonly Color ColWindowBorder = new Color(0.74f, 0.58f, 0.28f, 1f);

		private static readonly Color ColWindowBorderInner = new Color(0.18f, 0.23f, 0.32f, 0.85f);

		private static readonly Color ColCardBg = new Color(0.09f, 0.11f, 0.16f, 0.96f);

		private static readonly Color ColCardBorder = new Color(0.22f, 0.28f, 0.38f, 0.85f);

		private static readonly Color ColCardHeaderBg = new Color(0.12f, 0.16f, 0.22f, 1f);

		private static readonly Color ColGoldText = new Color(1f, 0.84f, 0.38f, 1f);

		private static readonly Color ColWhiteText = new Color(0.92f, 0.95f, 0.98f, 1f);

		private static readonly Color ColMutedText = new Color(0.6f, 0.66f, 0.75f, 1f);

		private static readonly Color ColCyanText = new Color(0.4f, 0.8f, 1f, 1f);

		private static readonly Color ColGreenText = new Color(0.38f, 0.88f, 0.48f, 1f);

		private static readonly Color ColRedText = new Color(0.95f, 0.38f, 0.38f, 1f);

		private static readonly Color ColSlotEmptyBg = new Color(0.06f, 0.07f, 0.1f, 0.9f);

		private static readonly Color ColSlotEmptyBorder = new Color(0.2f, 0.24f, 0.32f, 0.9f);

		private static readonly Color ColSlotHoverBorder = new Color(0.45f, 0.8f, 1f, 1f);

		private static readonly Color ColSlotSelectedBorder = new Color(1f, 0.84f, 0.38f, 1f);

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

		private static GUIStyle s_textFieldStyle;

		private static readonly Color ColScrollbar = new Color(0.2f, 0.25f, 0.35f, 0.8f);

		private float m_lastGridHeight = 400f;

		private float m_lastCell = 54f;

		public static BrowserGUI Instance { get; private set; }

		public static bool IsOpen
		{
			get
			{
				if ((Object)(object)Instance != (Object)null)
				{
					return Instance.m_open;
				}
				return false;
			}
		}

		private void Awake()
		{
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			//IL_0013: Expected O, but got Unknown
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			Instance = this;
			m_whiteTex = new Texture2D(1, 1);
			m_whiteTex.SetPixel(0, 0, Color.white);
			m_whiteTex.Apply();
		}

		private void OnDestroy()
		{
			if ((Object)(object)Instance == (Object)(object)this)
			{
				Instance = null;
			}
		}

		public void Open()
		{
			Player localPlayer = Player.m_localPlayer;
			if (!((Object)(object)localPlayer == (Object)null))
			{
				if (!RecipeIndex.Built)
				{
					RecipeIndex.Build(localPlayer);
				}
				if (!RecipeIndex.Built)
				{
					m_status = "No recipes loaded yet. Open a crafting station again in a moment.";
					m_statusTimer = 5f;
				}
				Refilter();
				m_open = true;
				m_wasCrafting = false;
				Cursor.visible = true;
				Cursor.lockState = (CursorLockMode)0;
			}
		}

		public void Close()
		{
			if (m_open)
			{
				m_open = false;
				m_selected = null;
				Cursor.visible = false;
				Cursor.lockState = (CursorLockMode)1;
			}
		}

		private void Update()
		{
			if (m_statusTimer > 0f)
			{
				m_statusTimer -= Time.deltaTime;
			}
			if (!m_open)
			{
				return;
			}
			Player localPlayer = Player.m_localPlayer;
			if ((Object)(object)localPlayer == (Object)null || ((Character)localPlayer).IsDead())
			{
				Close();
				return;
			}
			float progress;
			if (Input.GetKeyDown((KeyCode)27))
			{
				if (CraftingBridge.IsCrafting(out progress))
				{
					CraftingBridge.Cancel();
					SetStatus("Craft cancelled.");
				}
				else
				{
					Close();
				}
			}
			bool flag = CraftingBridge.IsCrafting(out progress);
			if (m_wasCrafting && !flag)
			{
				m_wasCrafting = false;
				if (m_pendingCraftName != null)
				{
					m_recentlyCrafted = m_pendingCraftName;
					m_pendingCraftName = null;
				}
			}
			m_wasCrafting = flag;
			RecipeIndex.Refresh(localPlayer);
		}

		private void Refilter()
		{
			RecipeIndex.Filter(m_visible, m_search, m_tabIndex, m_subIndex, m_mode);
			if (m_selected != null && !m_visible.Contains(m_selected))
			{
				m_selected = null;
				m_selectedCopy = 0;
			}
			ClampGridScroll();
		}

		private void ClampGridScroll()
		{
			int num = RowCount();
			int num2 = Mathf.Max(1, GridVisibleRows());
			m_gridRow = Mathf.Clamp(m_gridRow, 0, Mathf.Max(0, num - num2));
		}

		private int RowCount()
		{
			return Mathf.CeilToInt((float)m_visible.Count / (float)Mathf.Max(1, m_gridCols));
		}

		private void SetStatus(string text, float seconds = 4f)
		{
			m_status = text;
			m_statusTimer = seconds;
		}

		private void OnGUI()
		{
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_00cb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d0: Unknown result type (might be due to invalid IL or missing references)
			//IL_0120: 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_0188: 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)
			if (m_open)
			{
				DrawRect(new Rect(0f, 0f, (float)Screen.width, (float)Screen.height), ColBackdrop);
				float num = (m_isFullscreen ? ((float)Screen.width - 24f) : Mathf.Min(1180f, (float)Screen.width - 32f));
				float num2 = (m_isFullscreen ? ((float)Screen.height - 24f) : Mathf.Min(700f, (float)Screen.height - 32f));
				Rect r = default(Rect);
				((Rect)(ref r))..ctor(((float)Screen.width - num) * 0.5f, ((float)Screen.height - num2) * 0.5f, num, num2);
				DrawBox(r, ColWindowBg, ColWindowBorder, 2f);
				DrawBorder(Shrink(r, 3f), ColWindowBorderInner);
				float num3 = ((Rect)(ref r)).y + 8f;
				float num4 = 10f;
				float num5 = ((Rect)(ref r)).width - num4 * 2f;
				Rect r2 = default(Rect);
				((Rect)(ref r2))..ctor(((Rect)(ref r)).x + num4, num3, num5, 46f);
				DrawHeader(r2);
				num3 = ((Rect)(ref r2)).yMax + 8f;
				Rect r3 = default(Rect);
				((Rect)(ref r3))..ctor(((Rect)(ref r)).x + num4, num3, num5, 32f);
				DrawTopTabs(r3);
				num3 = ((Rect)(ref r3)).yMax + 8f;
				Rect r4 = default(Rect);
				((Rect)(ref r4))..ctor(((Rect)(ref r)).x + num4, num3, num5, ((Rect)(ref r)).yMax - num3 - 40f);
				DrawBody(r4);
				DrawFooter(new Rect(((Rect)(ref r)).x + num4, ((Rect)(ref r)).yMax - 34f, num5, 26f));
			}
		}

		private void DrawHeader(Rect r)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0002: 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_0059: 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_009a: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fd: Unknown result type (might be due to invalid IL or missing references)
			//IL_0112: Unknown result type (might be due to invalid IL or missing references)
			//IL_0117: Unknown result type (might be due to invalid IL or missing references)
			//IL_0126: Unknown result type (might be due to invalid IL or missing references)
			//IL_012c: Unknown result type (might be due to invalid IL or missing references)
			//IL_017c: Unknown result type (might be due to invalid IL or missing references)
			//IL_019a: 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_01b8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c0: Unknown result type (might be due to invalid IL or missing references)
			//IL_0238: Unknown result type (might be due to invalid IL or missing references)
			//IL_0277: Unknown result type (might be due to invalid IL or missing references)
			//IL_025c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0290: Unknown result type (might be due to invalid IL or missing references)
			//IL_0295: Unknown result type (might be due to invalid IL or missing references)
			//IL_029d: Unknown result type (might be due to invalid IL or missing references)
			//IL_02f2: 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_0338: Unknown result type (might be due to invalid IL or missing references)
			//IL_033d: Unknown result type (might be due to invalid IL or missing references)
			//IL_038a: Unknown result type (might be due to invalid IL or missing references)
			//IL_03a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_03c1: Unknown result type (might be due to invalid IL or missing references)
			//IL_03c6: Unknown result type (might be due to invalid IL or missing references)
			//IL_03ce: Unknown result type (might be due to invalid IL or missing references)
			DrawBox(r, ColCardHeaderBg, ColCardBorder);
			string text = RecipeIndex.CurrentStationName(Player.m_localPlayer);
			string text2 = (CraftingBridge.Ready ? "craft engine: bound" : "craft engine: UNAVAILABLE");
			GUI.Label(new Rect(((Rect)(ref r)).x + 14f, ((Rect)(ref r)).y + 5f, 380f, 22f), "? CRAFTING BROWSER", GetTextStyle(15, bold: true, (TextAnchor)3, ColGoldText));
			GUI.Label(new Rect(((Rect)(ref r)).x + 14f, ((Rect)(ref r)).y + 25f, 460f, 16f), "Station: <color=#FFD760>" + text + "</color>   \ufffd   " + text2, GetTextStyle(11, bold: false, (TextAnchor)3, CraftingBridge.Ready ? ColMutedText : ColRedText));
			Rect r2 = default(Rect);
			((Rect)(ref r2))..ctor(((Rect)(ref r)).x + 360f, ((Rect)(ref r)).y + 9f, 250f, 28f);
			DrawBox(r2, new Color(0.04f, 0.05f, 0.08f, 1f), ColCardBorder);
			string text3 = GUI.TextField(Shrink(r2, 5f), m_search, GetTextFieldStyle());
			if (text3 != m_search)
			{
				m_search = text3;
				Refilter();
			}
			if (CustomButton(new Rect(((Rect)(ref r2)).xMax + 4f, ((Rect)(ref r2)).y, 26f, 28f), "?", new Color(0.24f, 0.12f, 0.12f, 0.9f), new Color(0.55f, 0.15f, 0.15f, 1f), ColWhiteText, 11, bold: true, ColRedText))
			{
				m_search = "";
				Refilter();
			}
			float num = 128f;
			float num2 = ((Rect)(ref r)).xMax - 36f - num;
			string text4 = ((m_mode == VisibilityMode.Unlocked) ? "Unlocked" : ((m_mode == VisibilityMode.CraftableHere) ? "Craftable here" : "All recipes"));
			if (CustomButton(new Rect(num2, ((Rect)(ref r)).y + 9f, num, 28f), text4, (m_mode == VisibilityMode.All) ? new Color(0.24f, 0.2f, 0.1f, 0.95f) : new Color(0.12f, 0.16f, 0.24f, 0.95f), new Color(0.2f, 0.28f, 0.4f, 1f), ColGoldText, 11, bold: true, ColWindowBorder))
			{
				m_mode = ((m_mode == VisibilityMode.Unlocked) ? VisibilityMode.CraftableHere : ((m_mode == VisibilityMode.CraftableHere) ? VisibilityMode.All : VisibilityMode.Unlocked));
				Refilter();
			}
			if (CustomButton(new Rect(num2 - 34f, ((Rect)(ref r)).y + 9f, 30f, 28f), m_isFullscreen ? "?" : "?", new Color(0.12f, 0.15f, 0.2f, 0.9f), new Color(0.2f, 0.26f, 0.34f, 1f), ColWhiteText, 13))
			{
				m_isFullscreen = !m_isFullscreen;
			}
			if (CustomButton(new Rect(((Rect)(ref r)).xMax - 36f, ((Rect)(ref r)).y + 9f, 30f, 28f), "?", new Color(0.24f, 0.12f, 0.12f, 0.9f), new Color(0.55f, 0.15f, 0.15f, 1f), ColWhiteText, 13, bold: true, ColRedText))
			{
				Close();
			}
		}

		private void DrawTopTabs(Rect r)
		{
			//IL_0099: 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_009e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ab: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a4: 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_00bd: 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_00c2: 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_00d8: 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)
			//IL_00f2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fb: Unknown result type (might be due to invalid IL or missing references)
			//IL_0100: Unknown result type (might be due to invalid IL or missing references)
			//IL_0124: Unknown result type (might be due to invalid IL or missing references)
			//IL_0129: Unknown result type (might be due to invalid IL or missing references)
			CategoryTable table = CraftingCategories.Table;
			if (table == null)
			{
				return;
			}
			int count = table.tabs.Count;
			float num = (((Rect)(ref r)).width - (float)(count - 1) * 4f) / (float)count;
			Rect r2 = default(Rect);
			for (int i = 0; i < count; i++)
			{
				((Rect)(ref r2))..ctor(((Rect)(ref r)).x + (float)i * (num + 4f), ((Rect)(ref r)).y, num, ((Rect)(ref r)).height);
				bool flag = m_tabIndex == i;
				Color val = (flag ? new Color(0.22f, 0.28f, 0.38f, 1f) : new Color(0.1f, 0.13f, 0.18f, 0.85f));
				Color value = (flag ? ColWindowBorder : ColCardBorder);
				Color textColor = (flag ? ColGoldText : ColWhiteText);
				if (CustomButton(r2, table.tabs[i].label, val, (Color)(flag ? val : new Color(0.16f, 0.21f, 0.29f, 0.95f)), textColor, 11, bold: true, value))
				{
					m_tabIndex = i;
					m_subIndex = 0;
					m_gridRow = 0;
					m_sidebarScroll = Vector2.zero;
					Refilter();
				}
			}
		}

		private void DrawBody(Rect r)
		{
			//IL_00b0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c0: Unknown result type (might be due to invalid IL or missing references)
			float num = 8f;
			float num2 = Mathf.Clamp(((Rect)(ref r)).width * 0.16f, 130f, 190f);
			float num3 = Mathf.Clamp(((Rect)(ref r)).width * 0.3f, 250f, 340f);
			float num4 = ((Rect)(ref r)).width - num2 - num3 - num * 2f;
			Rect r2 = default(Rect);
			((Rect)(ref r2))..ctor(((Rect)(ref r)).x, ((Rect)(ref r)).y, num2, ((Rect)(ref r)).height);
			Rect r3 = default(Rect);
			((Rect)(ref r3))..ctor(((Rect)(ref r2)).xMax + num, ((Rect)(ref r)).y, num4, ((Rect)(ref r)).height);
			Rect r4 = default(Rect);
			((Rect)(ref r4))..ctor(((Rect)(ref r3)).xMax + num, ((Rect)(ref r)).y, num3, ((Rect)(ref r)).height);
			DrawSidebar(r2);
			DrawGrid(r3);
			DrawDetails(r4);
		}

		private void DrawSidebar(Rect r)
		{
			//IL_0001: 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_00b9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e6: 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)
			//IL_0061: Unknown result type (might be due to invalid IL or missing references)
			//IL_006b: Unknown result type (might be due to invalid IL or missing references)
			//IL_015f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0196: Unknown result type (might be due to invalid IL or missing references)
			//IL_017b: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ce: 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_01de: 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_01f1: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ea: Unknown result type (might be due to invalid IL or missing references)
			DrawCard(r, "CATEGORIES", (m_tabIndex > 0) ? null : "all");
			Rect val = default(Rect);
			((Rect)(ref val))..ctor(((Rect)(ref r)).x + 6f, ((Rect)(ref r)).y + 34f, ((Rect)(ref r)).width - 12f, ((Rect)(ref r)).height - 42f);
			if (m_tabIndex <= 0)
			{
				GUI.Label(val, "Every recipe the player has discovered, newest categories included.\n\nPick a top tab to narrow by subcategory.", GetTextStyle(11, bold: false, (TextAnchor)0, ColMutedText));
				return;
			}
			RecipeIndex.CountBySubcategory(m_tabIndex, m_mode, m_subCounts);
			int num = CraftingCategories.Table.SubCount(m_tabIndex);
			float num2 = 30f;
			Color backgroundColor = GUI.backgroundColor;
			GUI.backgroundColor = ColScrollbar;
			m_sidebarScroll = GUI.BeginScrollView(val, m_sidebarScroll, new Rect(0f, 0f, ((Rect)(ref val)).width - 16f, (float)num * (num2 + 2f)));
			GUI.backgroundColor = backgroundColor;
			Rect r2 = default(Rect);
			for (int i = 0; i < num; i++)
			{
				((Rect)(ref r2))..ctor(0f, (float)i * (num2 + 2f), ((Rect)(ref val)).width - 18f, num2);
				bool flag = m_subIndex == i;
				m_subCounts.TryGetValue(i, out var value);
				string text = $"{CraftingCategories.Table.SubLabel(m_tabIndex, i)}  ({value})";
				if (CustomButton(r2, text, flag ? new Color(0.24f, 0.2f, 0.1f, 0.98f) : new Color(0.1f, 0.13f, 0.18f, 0.7f), flag ? new Color(0.3f, 0.25f, 0.12f, 1f) : new Color(0.16f, 0.21f, 0.29f, 0.9f), flag ? ColGoldText : ColWhiteText, 11, bold: true, flag ? ColWindowBorder : ColCardBorder))
				{
					m_subIndex = i;
					m_gridRow = 0;
					Refilter();
				}
			}
			GUI.EndScrollView();
		}

		private int GridVisibleRows()
		{
			return Mathf.Max(1, (int)(m_lastGridHeight / (m_lastCell + 4f)));
		}

		private void DrawGrid(Rect r)
		{
			//IL_0001: 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_00a2: Invalid comparison between Unknown and I4
			//IL_006e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ab: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c3: 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_0212: Unknown result type (might be due to invalid IL or missing references)
			//IL_0263: Unknown result type (might be due to invalid IL or missing references)
			//IL_02a1: Unknown result type (might be due to invalid IL or missing references)
			DrawCard(r, "RECIPES", $"{m_visible.Count} shown");
			Rect val = default(Rect);
			((Rect)(ref val))..ctor(((Rect)(ref r)).x + 6f, ((Rect)(ref r)).y + 34f, ((Rect)(ref r)).width - 12f, ((Rect)(ref r)).height - 42f);
			if (m_visible.Count == 0)
			{
				GUI.Label(val, (m_mode == VisibilityMode.Unlocked) ? "Nothing here yet. Switch the header toggle to All recipes to see everything, including what you have not discovered." : "No recipe matches that search.", GetTextStyle(11, bold: false, (TextAnchor)0, ColMutedText));
				return;
			}
			if ((int)Event.current.type == 6 && ((Rect)(ref val)).Contains(Event.current.mousePosition))
			{
				m_gridRow += ((Event.current.delta.y > 0f) ? 1 : (-1));
				ClampGridScroll();
				Event.current.Use();
			}
			float num = 4f;
			float num2 = Mathf.Floor((((Rect)(ref val)).width - (float)(m_gridCols - 1) * num) / (float)m_gridCols);
			num2 = (m_lastCell = Mathf.Clamp(num2, 34f, m_isFullscreen ? 66f : 56f));
			m_lastGridHeight = ((Rect)(ref val)).height;
			m_gridCols = Mathf.Max(1, (int)((((Rect)(ref val)).width + num) / (num2 + num)));
			num2 = (m_lastCell = Mathf.Floor((((Rect)(ref val)).width - (float)(m_gridCols - 1) * num) / (float)m_gridCols));
			int num3 = RowCount();
			ClampGridScroll();
			int num4 = m_gridRow * m_gridCols;
			int num5 = Mathf.Min(m_visible.Count, num4 + m_gridCols * (num3 - m_gridRow));
			int num6 = 0;
			Rect cell = default(Rect);
			for (int i = num4; i < num5; i++)
			{
				int num7 = num6 % m_gridCols;
				int num8 = num6 / m_gridCols;
				((Rect)(ref cell))..ctor(((Rect)(ref val)).x + (float)num7 * (num2 + num), ((Rect)(ref val)).y + (float)num8 * (num2 + num), num2, num2);
				DrawRecipeCell(cell, m_visible[i], i);
				num6++;
			}
			if (num3 > GridVisibleRows())
			{
				GUI.Label(new Rect(((Rect)(ref val)).x, ((Rect)(ref val)).yMax - 18f, ((Rect)(ref val)).width, 16f), $"Rows {m_gridRow + 1}-{Mathf.Min(num3, m_gridRow + GridVisibleRows())} of {num3}", GetTextStyle(10, bold: false, (TextAnchor)4, ColMutedText));
			}
		}

		private void DrawRecipeCell(Rect cell, RecipeEntry entry, int index)
		{
			//IL_0011: 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_0085: 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_00bd: Unknown result type (might be due to invalid IL or missing references)
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c2: 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_00c6: 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_00af: 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_00f2: 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_0182: Unknown result type (might be due to invalid IL or missing references)
			//IL_013f: Unknown result type (might be due to invalid IL or missing references)
			//IL_016e: 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_01bc: 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)
			bool flag = entry == m_selected;
			bool flag2 = ((Rect)(ref cell)).Contains(Event.current.mousePosition);
			Color bg = (Color)(flag ? new Color(0.24f, 0.2f, 0.1f, 0.98f) : (entry.CanCraftNow ? new Color(0.11f, 0.16f, 0.13f, 0.95f) : (entry.Unlocked ? ColSlotEmptyBg : new Color(0.05f, 0.05f, 0.07f, 0.9f))));
			Color border = (Color)(flag ? ColSlotSelectedBorder : (flag2 ? ColSlotHoverBorder : (entry.Unlocked ? ColSlotEmptyBorder : new Color(0.14f, 0.15f, 0.18f, 0.8f))));
			DrawBox(cell, bg, border, flag ? 2f : 1f);
			float num = (entry.Unlocked ? 1f : 0.38f);
			DrawIcon(Shrink(cell, 4f), entry.Icon, num);
			if (entry.Amount > 1)
			{
				GUI.Label(new Rect(((Rect)(ref cell)).x + 2f, ((Rect)(ref cell)).yMax - 14f, ((Rect)(ref cell)).width - 4f, 12f), "x" + entry.Amount, GetTextStyle(9, bold: true, (TextAnchor)5, new Color(1f, 1f, 1f, num)));
			}
			if ((int)Event.current.type != 0 || !((Rect)(ref cell)).Contains(Event.current.mousePosition))
			{
				return;
			}
			m_selected = entry;
			m_selectedCopy = 0;
			m_ownedCopies.Clear();
			m_detailsScroll = Vector2.zero;
			Event.current.Use();
			if (Event.current.button == 0)
			{
				float unscaledTime = Time.unscaledTime;
				if (m_lastClickedIndex == index && unscaledTime - m_lastClickTime < 0.35f)
				{
					TryCraft();
					m_lastClickTime = 0f;
					m_lastClickedIndex = -1;
				}
				else
				{
					m_lastClickTime = unscaledTime;
					m_lastClickedIndex = index;
				}
			}
		}

		private void DrawDetails(Rect r)
		{
			//IL_0001: 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_006d: 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_009c: 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_00a6: Unknown result type (might be due to invalid IL or missing references)
			//IL_011c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0148: 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_0183: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01cc: Unknown result type (might be due to invalid IL or missing references)
			//IL_025b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0265: Unknown result type (might be due to invalid IL or missing references)
			DrawCard(r, "DETAILS", (m_selected != null) ? m_selected.StationName : null);
			Rect val = default(Rect);
			((Rect)(ref val))..ctor(((Rect)(ref r)).x + 8f, ((Rect)(ref r)).y + 34f, ((Rect)(ref r)).width - 16f, ((Rect)(ref r)).height - 42f);
			Color backgroundColor = GUI.backgroundColor;
			GUI.backgroundColor = ColScrollbar;
			m_detailsScroll = GUI.BeginScrollView(val, m_detailsScroll, new Rect(0f, 0f, ((Rect)(ref val)).width - 16f, Mathf.Max(((Rect)(ref val)).height, 420f)));
			GUI.backgroundColor = backgroundColor;
			if (m_selected == null)
			{
				GUI.Label(new Rect(0f, 0f, ((Rect)(ref val)).width - 16f, 60f), "Pick a recipe to see its ingredients and craft it.", GetTextStyle(11, bold: false, (TextAnchor)0, ColMutedText));
				GUI.EndScrollView();
				return;
			}
			float num = 0f;
			float num2 = ((Rect)(ref val)).width - 16f;
			DrawIcon(new Rect(0f, num, 40f, 40f), m_selected.Icon, 1f);
			GUI.Label(new Rect(46f, num, num2 - 46f, 20f), m_selected.DisplayName, GetTextStyle(13, bold: true, (TextAnchor)3, ColGoldText));
			GUI.Label(new Rect(46f, num + 19f, num2 - 46f, 18f), (m_selected.Amount > 1) ? $"Produces {m_selected.Amount}   \ufffd   {m_selected.StationName}" : m_selected.StationName, GetTextStyle(10, bold: false, (TextAnchor)3, ColMutedText));
			num += 46f;
			string text = ((!m_selected.Unlocked) ? "<color=#F26262>Not yet discovered</color>" : ((!m_selected.StationOk) ? ("<color=#F2B262>Needs a " + m_selected.StationName + "</color>") : (m_selected.CanCraftNow ? $"<color=#63E07A>You can craft {m_selected.MaxCraftable}</color>" : "<color=#E0C063>Missing materials</color>")));
			GUI.Label(new Rect(0f, num, num2, 18f), text, GetTextStyle(11, bold: true, (TextAnchor)3, ColWhiteText));
			num += 24f;
			num = DrawRequirementList(0f, num, num2);
			num = DrawUpgradeStrip(0f, num, num2);
			num = DrawCraftButton(0f, num, num2);
			GUI.EndScrollView();
		}

		private float DrawRequirementList(float x, float y, float w)
		{
			//IL_0020: 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_005f: 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_0129: Unknown result type (might be due to invalid IL or missing references)
			//IL_013f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0144: 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_01be: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d3: Unknown result type (might be due to invalid IL or missing references)
			//IL_0200: Unknown result type (might be due to invalid IL or missing references)
			//IL_022c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0225: Unknown result type (might be due to invalid IL or missing references)
			Requirement[] resources = m_selected.Recipe.m_resources;
			if (resources == null || resources.Length == 0)
			{
				GUI.Label(new Rect(x, y, w, 18f), "No materials required.", GetTextStyle(11, bold: false, (TextAnchor)3, ColMutedText));
				return y + 24f;
			}
			if (m_selected.Recipe.m_requireOnlyOneIngredient)
			{
				GUI.Label(new Rect(x, y, w, 16f), "Only one ingredient set is needed.", GetTextStyle(10, bold: false, (TextAnchor)3, ColCyanText));
				y += 18f;
			}
			Player localPlayer = Player.m_localPlayer;
			Inventory val = (((Object)(object)localPlayer != (Object)null) ? ((Humanoid)localPlayer).GetInventory() : null);
			Rect r = default(Rect);
			foreach (Requirement val2 in resources)
			{
				if (val2 != null && !((Object)(object)val2.m_resItem == (Object)null) && val2.m_resItem.m_itemData != null)
				{
					SharedData shared = val2.m_resItem.m_itemData.m_shared;
					int num = Mathf.Max(1, val2.GetAmount(1));
					int num2 = ((val != null) ? val.CountItems(shared.m_name, -1, true) : 0);
					bool flag = num2 >= num;
					((Rect)(ref r))..ctor(x, y, w, 24f);
					DrawBox(r, new Color(0.06f, 0.08f, 0.11f, 0.8f), ColCardBorder);
					DrawIcon(new Rect(((Rect)(ref r)).x + 2f, ((Rect)(ref r)).y + 2f, 20f, 20f), val2.m_resItem.m_itemData.GetIcon(), 1f);
					GUI.Label(new Rect(((Rect)(ref r)).x + 26f, ((Rect)(ref r)).y, ((Rect)(ref r)).width - 90f, 24f), RecipeIndex.Localize(shared.m_name), GetTextStyle(10, bold: false, (TextAnchor)3, ColWhiteText));
					GUI.Label(new Rect(((Rect)(ref r)).xMax - 62f, ((Rect)(ref r)).y, 58f, 24f), $"{num2} / {num}", GetTextStyle(11, bold: true, (TextAnchor)5, flag ? ColGreenText : ColRedText));
					y += 26f;
				}
			}
			return y + 6f;
		}

		private float DrawUpgradeStrip(float x, float y, float w)
		{
			//IL_0090: 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_00e0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ee: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b6: 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_017a: 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_01bc: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e7: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e0: Unknown result type (might be due to invalid IL or missing references)
			//IL_0202: Unknown result type (might be due to invalid IL or missing references)
			//IL_0209: Unknown result type (might be due to invalid IL or missing references)
			//IL_0251: Unknown result type (might be due to invalid IL or missing references)
			//IL_027b: Unknown result type (might be due to invalid IL or missing references)
			//IL_028f: Unknown result type (might be due to invalid IL or missing references)
			//IL_029d: Unknown result type (might be due to invalid IL or missing references)
			SharedData shared = m_selected.Recipe.m_item.m_itemData.m_shared;
			if (shared.m_maxQuality <= 1)
			{
				return y;
			}
			Player localPlayer = Player.m_localPlayer;
			Inventory val = (((Object)(object)localPlayer != (Object)null) ? ((Humanoid)localPlayer).GetInventory() : null);
			if (val == null)
			{
				return y;
			}
			if (m_ownedCopies.Count == 0)
			{
				m_ownedCopies.Clear();
				val.GetAllItems(shared.m_name, m_ownedCopies);
				if (m_selectedCopy >= m_ownedCopies.Count)
				{
					m_selectedCopy = 0;
				}
			}
			GUI.Label(new Rect(x, y, w, 18f), $"Upgrade target ({m_ownedCopies.Count} owned)", GetTextStyle(11, bold: true, (TextAnchor)3, ColCyanText));
			y += 20f;
			if (m_ownedCopies.Count == 0)
			{
				GUI.Label(new Rect(x, y, w, 16f), "You do not own any to upgrade.", GetTextStyle(10, bold: false, (TextAnchor)3, ColMutedText));
				return y + 22f;
			}
			float num = Mathf.Min(38f, (w - 6f) / (float)Mathf.Min(m_ownedCopies.Count, 6));
			Rect r = default(Rect);
			for (int i = 0; i < m_ownedCopies.Count; i++)
			{
				if (i >= 6)
				{
					GUI.Label(new Rect(x + 6f * (num + 2f), y, 40f, 34f), "+" + (m_ownedCopies.Count - 6), GetTextStyle(11, bold: true, (TextAnchor)3, ColMutedText));
					break;
				}
				((Rect)(ref r))..ctor(x + (float)i * (num + 2f), y, num, 34f);
				bool flag = m_selectedCopy == i;
				DrawBox(r, (Color)(flag ? new Color(0.24f, 0.2f, 0.1f, 0.98f) : ColSlotEmptyBg), flag ? ColWindowBorder : ColSlotEmptyBorder, flag ? 2f : 1f);
				DrawIcon(Shrink(r, 3f), m_ownedCopies[i].m_shared.m_icons[0], 1f);
				GUI.Label(new Rect(((Rect)(ref r)).x, ((Rect)(ref r)).yMax - 13f, ((Rect)(ref r)).width, 12f), "?" + m_ownedCopies[i].m_quality, GetTextStyle(9, bold: true, (TextAnchor)4, ColGoldText));
				if ((int)Event.current.type == 0 && ((Rect)(ref r)).Contains(Event.current.mousePosition))
				{
					m_selectedCopy = i;
					Event.current.Use();
				}
			}
			return y + 40f;
		}

		private float DrawCraftButton(float x, float y, float w)
		{
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0083: 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_00a6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fe: 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_011c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0124: Unknown result type (might be due to invalid IL or missing references)
			//IL_016d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0183: 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_0197: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ad: Unknown result type (might be due to invalid IL or missing references)
			//IL_01cb: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e9: Unknown result type (might be due to invalid IL or missing references)
			//IL_0202: Unknown result type (might be due to invalid IL or missing references)
			//IL_0207: Unknown result type (might be due to invalid IL or missing references)
			//IL_020f: Unknown result type (might be due to invalid IL or missing references)
			//IL_023c: Unknown result type (might be due to invalid IL or missing references)
			//IL_025a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0273: Unknown result type (might be due to invalid IL or missing references)
			//IL_0278: Unknown result type (might be due to invalid IL or missing references)
			//IL_0280: Unknown result type (might be due to invalid IL or missing references)
			//IL_034e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0353: Unknown result type (might be due to invalid IL or missing references)
			//IL_035e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0365: Unknown result type (might be due to invalid IL or missing references)
			//IL_037b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0333: Unknown result type (might be due to invalid IL or missing references)
			//IL_038d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0386: Unknown result type (might be due to invalid IL or missing references)
			//IL_03a2: Unknown result type (might be due to invalid IL or missing references)
			//IL_039b: Unknown result type (might be due to invalid IL or missing references)
			if (CraftingBridge.IsCrafting(out var progress))
			{
				Rect val = default(Rect);
				((Rect)(ref val))..ctor(x, y + 4f, w, 16f);
				DrawBox(val, new Color(0.05f, 0.06f, 0.09f, 1f), ColCardBorder);
				DrawRect(new Rect(((Rect)(ref val)).x + 1f, ((Rect)(ref val)).y + 1f, (((Rect)(ref val)).width - 2f) * progress, ((Rect)(ref val)).height - 2f), new Color(0.35f, 0.75f, 0.45f, 0.95f));
				GUI.Label(val, $"Crafting {progress * 100f:F0}%", GetTextStyle(10, bold: true, (TextAnchor)4, ColWhiteText));
				if (CustomButton(new Rect(x, y + 24f, w, 30f), "Cancel", new Color(0.32f, 0.14f, 0.14f, 0.95f), new Color(0.55f, 0.18f, 0.18f, 1f), ColWhiteText, 12, bold: true, ColRedText))
				{
					CraftingBridge.Cancel();
					SetStatus("Craft cancelled.");
				}
				return y + 60f;
			}
			if (m_recentlyCrafted != null)
			{
				Rect val2 = default(Rect);
				((Rect)(ref val2))..ctor(x, y, w, 30f);
				DrawBox(val2, new Color(0.12f, 0.26f, 0.16f, 0.95f), ColGreenText);
				GUI.Label(val2, "? Crafted " + m_recentlyCrafted, GetTextStyle(12, bold: true, (TextAnchor)4, ColGreenText));
				if (CustomButton(new Rect(x, y + 34f, w, 26f), "View inventory", new Color(0.12f, 0.16f, 0.24f, 0.95f), new Color(0.2f, 0.28f, 0.4f, 1f), ColWhiteText, 11, bold: true, ColCyanText))
				{
					m_recentlyCrafted = null;
					Close();
				}
				if (CustomButton(new Rect(x, y + 62f, w, 24f), "Dismiss", new Color(0.1f, 0.12f, 0.16f, 0.9f), new Color(0.16f, 0.2f, 0.26f, 1f), ColMutedText, 10, bold: false, ColCardBorder))
				{
					m_recentlyCrafted = null;
				}
				return y + 92f;
			}
			bool ready = CraftingBridge.Ready;
			bool stationOk = m_selected.StationOk;
			bool canCraftNow = m_selected.CanCraftNow;
			bool flag = m_selected.Unlocked && stationOk && canCraftNow;
			string text = ((!ready) ? "Craft unavailable" : ((!m_selected.Unlocked) ? "Not discovered" : ((!stationOk) ? ("Needs a " + m_selected.StationName) : ((!canCraftNow) ? "Missing materials" : "Craft"))));
			Color bg = ((!flag || !ready) ? new Color(0.12f, 0.13f, 0.16f, 0.9f) : new Color(0.16f, 0.34f, 0.2f, 0.95f));
			if (CustomButton(new Rect(x, y, w, 32f), text, bg, new Color(0.22f, 0.48f, 0.28f, 1f), (flag && ready) ? ColWhiteText : ColMutedText, 12, bold: true, (flag && ready) ? ColGreenText : ColCardBorder))
			{
				TryCraft();
			}
			return y + 38f;
		}

		private void TryCraft()
		{
			if (m_selected == null)
			{
				return;
			}
			if (!CraftingBridge.Ready)
			{
				SetStatus("The crafting engine is not bound on this game build; browsing still works.");
				return;
			}
			if (!m_selected.Unlocked)
			{
				SetStatus("You have not discovered that recipe yet.");
				return;
			}
			if (!m_selected.StationOk)
			{
				SetStatus("That recipe needs a different crafting station.");
				return;
			}
			if (!m_selected.CanCraftNow)
			{
				SetStatus("You are missing materials for that recipe.");
				return;
			}
			ItemData val = null;
			if (m_selected.Recipe.m_item.m_itemData.m_shared.m_maxQuality > 1 && m_ownedCopies.Count > 0)
			{
				val = m_ownedCopies[Mathf.Clamp(m_selectedCopy, 0, m_ownedCopies.Count - 1)];
			}
			if (CraftingBridge.TryStartCraft(Player.m_localPlayer, m_selected.Recipe, val, out var error))
			{
				m_pendingCraftName = m_selected.DisplayName;
				m_recentlyCrafted = null;
				SetStatus((val != null) ? ("Upgrading " + m_selected.DisplayName + "...") : ("Crafting " + m_selected.DisplayName + "..."));
			}
			else
			{
				SetStatus("Could not start: " + error);
			}
		}

		private void DrawFooter(Rect r)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0046: Unknown result type (might be due to invalid IL or missing references)
			//IL_004c: 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_0063: 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_007f: Unknown result type (might be due to invalid IL or missing references)
			//IL_008d: Unknown result type (might be due to invalid IL or missing references)
			DrawBox(r, new Color(0.06f, 0.07f, 0.1f, 0.95f), ColCardBorder);
			string text = ((m_statusTimer > 0f) ? m_status : BuildFooterSummary());
			GUI.Label(Shrink(r, 8f), text, GetTextStyle(10, bold: false, (TextAnchor)3, (m_statusTimer > 0f) ? ColCyanText : ColMutedText));
			GUI.Label(Shrink(r, 8f), "Esc close / cancel   \ufffd   double-click to craft", GetTextStyle(10, bold: false, (TextAnchor)5, ColMutedText));
		}

		private string BuildFooterSummary()
		{
			StringBuilder stringBuilder = new StringBuilder();
			stringBuilder.Append($"{RecipeIndex.All.Count} recipes indexed   \ufffd   ");
			stringBuilder.Append($"{CraftingCategories.LastTotal - CraftingCategories.LastUnmatched} categorised");
			if (CraftingCategories.LastUnmatched > 0)
			{
				stringBuilder.Append($", {CraftingCategories.LastUnmatched} in Other");
			}
			int untranslatedCount = RecipeIndex.UntranslatedCount;
			if (untranslatedCount > 0)
			{
				stringBuilder.Append($"   \ufffd   <color=#F2B262>{untranslatedCount} names untranslated</color>");
			}
			return stringBuilder.ToString();
		}

		private void DrawRect(Rect r, Color c)
		{
			//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_0012: Unknown result type (might be due to invalid IL or missing references)
			GUI.color = c;
			GUI.DrawTexture(r, (Texture)(object)m_whiteTex);
			GUI.color = Color.white;
		}

		private void DrawBorder(Rect r, Color c, float thickness = 1f)
		{
			//IL_0000: 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_0044: 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_00a6: 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)
			GUI.color = c;
			GUI.DrawTexture(new Rect(((Rect)(ref r)).x, ((Rect)(ref r)).y, ((Rect)(ref r)).width, thickness), (Texture)(object)m_whiteTex);
			GUI.DrawTexture(new Rect(((Rect)(ref r)).x, ((Rect)(ref r)).yMax - thickness, ((Rect)(ref r)).width, thickness), (Texture)(object)m_whiteTex);
			GUI.DrawTexture(new Rect(((Rect)(ref r)).x, ((Rect)(ref r)).y + thickness, thickness, ((Rect)(ref r)).height - thickness * 2f), (Texture)(object)m_whiteTex);
			GUI.DrawTexture(new Rect(((Rect)(ref r)).xMax - thickness, ((Rect)(ref r)).y + thickness, thickness, ((Rect)(ref r)).height - thickness * 2f), (Texture)(object)m_whiteTex);
			GUI.color = Color.white;
		}

		private void DrawBox(Rect r, Color bg, Color border, float thickness = 1f)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: 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_0020: Unknown result type (might be due to invalid IL or missing references)
			DrawRect(r, bg);
			if (thickness > 0f && border.a > 0.01f)
			{
				DrawBorder(r, border, thickness);
			}
		}

		private void DrawCard(Rect r, string title, string badge = null)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0002: 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_0038: 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_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0079: Unknown result type (might be due to invalid IL or missing references)
			//IL_0083: Unknown result type (might be due to invalid IL or missing references)
			//IL_00be: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c8: Unknown result type (might be due to invalid IL or missing references)
			DrawBox(r, ColCardBg, ColCardBorder);
			Rect r2 = default(Rect);
			((Rect)(ref r2))..ctor(((Rect)(ref r)).x, ((Rect)(ref r)).y, ((Rect)(ref r)).width, 28f);
			DrawBox(r2, ColCardHeaderBg, ColCardBorder);
			GUI.Label(new Rect(((Rect)(ref r2)).x + 10f, ((Rect)(ref r2)).y + 4f, ((Rect)(ref r2)).width - 20f, 20f), title, GetTextStyle(12, bold: true, (TextAnchor)3, ColGoldText));
			if (!string.IsNullOrEmpty(badge))
			{
				GUI.Label(new Rect(((Rect)(ref r2)).xMax - 170f, ((Rect)(ref r2)).y + 4f, 160f, 20f), badge, GetTextStyle(11, bold: true, (TextAnchor)5, ColCyanText));
			}
		}

		private bool CustomButton(Rect r, string text, Color bg, Color hoverBg, Color textColor, int fontSize = 12, bool bold = true, Color? border = null)
		{
			//IL_0007: 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_0015: 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_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)
			//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_006b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0076: Unknown result type (might be due to invalid IL or missing references)
			//IL_007d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0089: 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_003e: Unknown result type (might be due to invalid IL or missing references)
			bool flag = ((Rect)(ref r)).Contains(Event.current.mousePosition);
			Color bg2 = (flag ? hoverBg : bg);
			Color border2 = (Color)(((??)border) ?? (flag ? new Color(0.4f, 0.75f, 1f, 0.9f) : new Color(0.24f, 0.3f, 0.4f, 0.85f)));
			DrawBox(r, bg2, border2);
			GUI.Label(r, text, GetTextStyle(fontSize, bold, (TextAnchor)4, textColor));
			return GUI.Button(r, GUIContent.none, GUIStyle.none);
		}

		private static Rect Shrink(Rect r, float amount)
		{
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			return new Rect(((Rect)(ref r)).x + amount, ((Rect)(ref r)).y + amount, ((Rect)(ref r)).width - amount * 2f, ((Rect)(ref r)).height - amount * 2f);
		}

		private void DrawIcon(Rect r, Sprite sprite, float alpha)
		{
			//IL_001c: 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_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_012f: 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_014e: 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)
			if ((Object)(object)sprite == (Object)null)
			{
				return;
			}
			Texture texture = (Texture)(object)sprite.texture;
			if ((Object)(object)texture == (Object)null)
			{
				return;
			}
			Rect textureRect = sprite.textureRect;
			float num = texture.width;
			float num2 = texture.height;
			if (num <= 0f || num2 <= 0f)
			{
				return;
			}
			Rect val = default(Rect);
			((Rect)(ref val))..ctor(((Rect)(ref textureRect)).x / num, ((Rect)(ref textureRect)).y / num2, ((Rect)(ref textureRect)).width / num, ((Rect)(ref textureRect)).height / num2);
			Rect val2 = r;
			if (((Rect)(ref val)).width > 0f && ((Rect)(ref val)).height > 0f)
			{
				float num3 = ((Rect)(ref val)).width / ((Rect)(ref val)).height;
				if (((Rect)(ref r)).width / ((Rect)(ref r)).height > num3)
				{
					float num4 = ((Rect)(ref r)).height * num3;
					((Rect)(ref val2))..ctor(((Rect)(ref r)).x + (((Rect)(ref r)).width - num4) * 0.5f, ((Rect)(ref r)).y, num4, ((Rect)(ref r)).height);
				}
				else
				{
					float num5 = ((Rect)(ref r)).width / num3;
					((Rect)(ref val2))..ctor(((Rect)(ref r)).x, ((Rect)(ref r)).y + (((Rect)(ref r)).height - num5) * 0.5f, ((Rect)(ref r)).width, num5);
				}
			}
			Color color = GUI.color;
			GUI.color = new Color(1f, 1f, 1f, alpha);
			GUI.DrawTextureWithTexCoords(val2, texture, val, true);
			GUI.color = color;
		}

		private static GUIStyle GetTextStyle(int fontSize, bool bold, TextAnchor anchor, Color color)
		{
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: Expected I4, but got Unknown
			//IL_002b: 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_0047: Unknown result type (might be due to invalid IL or missing references)
			//IL_0055: Unknown result type (might be due to invalid IL or missing references)
			//IL_0080: Unknown result type (might be due to invalid IL or missing references)
			//IL_0085: 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_0099: 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_00a0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00af: Expected O, but got Unknown
			//IL_00b5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cd: Unknown result type (might be due to invalid IL or missing references)
			string key = $"{fontSize}_{(bold ? 1 : 0)}_{(int)anchor}_{color.r:F2}_{color.g:F2}_{color.b:F2}_{color.a:F2}";
			if (!s_styleCache.TryGetValue(key, out var value))
			{
				value = new GUIStyle(GUI.skin.label)
				{
					fontSize = fontSize,
					fontStyle = (FontStyle)(bold ? 1 : 0),
					alignment = anchor,
					clipping = (TextClipping)1,
					wordWrap = true
				};
				value.normal.textColor = color;
				value.hover.textColor = color;
				value.active.textColor = color;
				s_styleCache[key] = value;
			}
			return value;
		}

		private static GUIStyle GetTextFieldStyle()
		{
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: Expected O, but got Unknown
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			if (s_textFieldStyle == null)
			{
				s_textFieldStyle = new GUIStyle(GUI.skin.textField)
				{
					fontSize = 12,
					alignment = (TextAnchor)3
				};
				s_textFieldStyle.normal.textColor = ColWhiteText;
			}
			return s_textFieldStyle;
		}
	}
	public static class CraftingBridge
	{
		private const BindingFlags AnyInstance = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic;

		private static FieldInfo f_selectedRecipe;

		private static FieldInfo f_selectedVariant;

		private static FieldInfo f_craftRecipe;

		private static FieldInfo f_craftUpgradeItem;

		private static FieldInfo f_craftVariant;

		private static FieldInfo f_multiCrafting;

		private static FieldInfo f_craftTimer;

		private static MethodInfo m_onCraftCancelPressed;

		private static ConstructorInfo c_pair;

		private static Type t_pair;

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

		public static bool Ready { get; private set; }

		public static string MissingReport
		{
			get
			{
				if (s_missing.Count != 0)
				{
					return string.Join(", ", s_missing.ToArray());
				}
				return "none";
			}
		}

		public static Recipe CurrentCraft
		{
			get
			{
				if (f_craftRecipe == null)
				{
					return null;
				}
				try
				{
					InventoryGui instance = InventoryGui.instance;
					return (Recipe)(((Object)(object)instance == (Object)null) ? null : /*isinst with value type is only supported in some contexts*/);
				}
				catch (Exception)
				{
					return null;
				}
			}
		}

		public static void Init()
		{
			s_missing.Clear();
			t_pair = typeof(InventoryGui).GetNestedType("RecipeDataPair", BindingFlags.Public | BindingFlags.NonPublic);
			if (t_pair == null)
			{
				s_missing.Add("InventoryGui+RecipeDataPair");
			}
			else
			{
				c_pair = t_pair.GetConstructor(new Type[4]
				{
					typeof(Recipe),
					typeof(ItemData),
					typeof(GameObject),
					typeof(bool)
				});
				if (c_pair == null)
				{
					s_missing.Add("RecipeDataPair(Recipe,ItemData,GameObject,bool)");
				}
			}
			f_selectedRecipe = Field("m_selectedRecipe");
			f_selectedVariant = Field("m_selectedVariant");
			f_craftRecipe = Field("m_craftRecipe");
			f_craftUpgradeItem = Field("m_craftUpgradeItem");
			f_craftVariant = Field("m_craftVariant");
			f_multiCrafting = Field("m_multiCrafting");
			f_craftTimer = Field("m_craftTimer");
			m_onCraftCancelPressed = Method("OnCraftCancelPressed");
			Ready = s_missing.Count == 0;
			if (Ready)
			{
				Logger.LogInfo((object)"Crafting Browser: crafting engine bound to the vanilla InventoryGui.");
			}
			else
			{
				Logger.LogError((object)("Crafting Browser: could not bind the crafting engine (" + MissingReport + "). The browser will open read-only and Craft is disabled. Run verify_patches.ps1 to see which member moved."));
			}
		}

		private static FieldInfo Field(string name)
		{
			FieldInfo? field = typeof(InventoryGui).GetField(name, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
			if (field == null)
			{
				s_missing.Add("InventoryGui." + name);
			}
			return field;
		}

		private static MethodInfo Method(string name, params Type[] args)
		{
			MethodInfo? method = typeof(InventoryGui).GetMethod(name, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, args, null);
			if (method == null)
			{
				s_missing.Add("InventoryGui." + name);
			}
			return method;
		}

		public static bool TryStartCraft(Player player, Recipe recipe, ItemData upgradeItem, out string error)
		{
			error = null;
			if (!Ready)
			{
				error = "crafting engine unavailable";
				return false;
			}
			if ((Object)(object)player == (Object)null || (Object)(object)recipe == (Object)null)
			{
				error = "no player or recipe";
				return false;
			}
			InventoryGui instance = InventoryGui.instance;
			if ((Object)(object)instance == (Object)null)
			{
				error = "inventory panel is not open";
				return false;
			}
			if (IsCrafting(out var _))
			{
				error = "already crafting";
				return false;
			}
			if (!player.HaveRequirements(recipe, false, 1, 1))
			{
				error = "missing materials";
				return false;
			}
			try
			{
				if (c_pair != null)
				{
					object value = c_pair.Invoke(new object[4] { recipe, upgradeItem, null, true });
					f_selectedRecipe.SetValue(instance, value);
				}
				f_selectedVariant.SetValue(instance, 0);
				f_craftRecipe.SetValue(instance, recipe);
				f_craftUpgradeItem.SetValue(instance, upgradeItem);
				f_craftVariant.SetValue(instance, 0);
				f_multiCrafting.SetValue(instance, false);
				f_craftTimer.SetValue(instance, 0f);
				return true;
			}
			catch (Exception ex)
			{
				error = ex.GetBaseException().Message;
				Logger.LogError((object)("Crafting Browser: failed to arm a craft: " + ex));
				return false;
			}
		}

		public static bool IsCrafting(out float progress)
		{
			progress = 0f;
			if (f_craftTimer == null)
			{
				return false;
			}
			try
			{
				InventoryGui instance = InventoryGui.instance;
				if ((Object)(object)instance == (Object)null)
				{
					return false;
				}
				if (!(f_craftTimer.GetValue(instance) is float num))
				{
					return false;
				}
				if (num < 0f)
				{
					return false;
				}
				progress = Mathf.Clamp01(num);
				return true;
			}
			catch (Exception)
			{
				return false;
			}
		}

		public static void Cancel()
		{
			if (m_onCraftCancelPressed == null)
			{
				return;
			}
			try
			{
				InventoryGui instance = InventoryGui.instance;
				if ((Object)(object)instance != (Object)null)
				{
					m_onCraftCancelPressed.Invoke(instance, null);
				}
			}
			catch (Exception ex)
			{
				Logger.LogError((object)("Crafting Browser: cancel failed: " + ex));
			}
		}
	}
	[BepInPlugin("com.dfg.craftingbrowser", "Crafting Browser", "1.0.0")]
	public class CraftingBrowserPlugin : BaseUnityPlugin
	{
		[HarmonyPatch(typeof(CraftingStation), "Interact")]
		private static class CraftingStationInteractPatch
		{
			private static void Postfix()
			{
				if (Enabled == null || !Enabled.Value || !OpenOnStation.Value)
				{
					return;
				}
				Player localPlayer = Player.m_localPlayer;
				if (!((Object)(object)localPlayer == (Object)null) && !((Object)(object)localPlayer.GetCurrentCraftingStation() == (Object)null))
				{
					s_openQueued = true;
					if (!s_openLogged)
					{
						s_openLogged = true;
						Logger.LogInfo((object)"Crafting Browser: station interaction detected, browser will open.");
					}
				}
			}
		}

		[HarmonyPatch(typeof(InventoryGui), "Hide")]
		private static class InventoryGuiHidePatch
		{
			private static bool Prefix()
			{
				return !BrowserGUI.IsOpen;
			}
		}

		[HarmonyPatch(typeof(PlayerController), "InInventoryEtc")]
		private static class InInventoryEtcPatch
		{
			private static void Postfix(ref bool __result)
			{
				if (BrowserGUI.IsOpen)
				{
					__result = true;
				}
			}
		}

		public const string PluginGUID = "com.dfg.craftingbrowser";

		public const string PluginName = "Crafting Browser";

		public const string PluginVersion = "1.0.0";

		internal static ConfigEntry<bool> Enabled;

		internal static ConfigEntry<bool> OpenOnStation;

		internal static ConfigEntry<KeyCode> OpenKey;

		internal static ConfigEntry<bool> HotReloadCategories;

		private Harmony m_harmony;

		private static bool s_openQueued;

		private static bool s_openLogged;

		private float s_nextHotReloadCheck;

		private void Awake()
		{
			//IL_00a4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ae: Expected O, but got Unknown
			Enabled = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "Enabled", true, "Master switch for the crafting browser.");
			OpenOnStation = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "OpenOnStationInteract", true, "Open the browser when you interact with a crafting station. The vanilla inventory panel still opens underneath; the browser is drawn over it, because the game itself is what actually performs the craft.");
			OpenKey = ((BaseUnityPlugin)this).Config.Bind<KeyCode>("General", "OpenKey", (KeyCode)290, "Hotkey that opens the browser from anywhere, whether or not you are at a station. Crafting still requires a valid station.");
			HotReloadCategories = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "HotReloadCategories", true, "Re-read categories.json when it changes on disk, without a restart.");
			CraftingCategories.Load(Path.GetDirectoryName(((BaseUnityPlugin)this).Info.Location));
			CraftingBridge.Init();
			m_harmony = new Harmony("com.dfg.craftingbrowser");
			try
			{
				m_harmony.PatchAll();
			}
			catch (Exception ex)
			{
				Logger.LogError((object)("Crafting Browser: Harmony patching failed: " + ex));
			}
			((Component)this).gameObject.AddComponent<BrowserGUI>();
			Logger.LogInfo((object)"Crafting Browser 1.0.0 loading.");
		}

		private void Update()
		{
			//IL_004e: 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)
			if (!Enabled.Value)
			{
				if (BrowserGUI.IsOpen)
				{
					BrowserGUI.Instance.Close();
				}
				return;
			}
			if (s_openQueued)
			{
				s_openQueued = false;
				if ((Object)(object)BrowserGUI.Instance != (Object)null && !BrowserGUI.IsOpen)
				{
					BrowserGUI.Instance.Open();
				}
			}
			if ((int)OpenKey.Value != 0 && Input.GetKeyDown(OpenKey.Value))
			{
				if (BrowserGUI.IsOpen)
				{
					BrowserGUI.Instance.Close();
				}
				else
				{
					BrowserGUI.Instance.Open();
				}
			}
			if (!HotReloadCategories.Value || !(Time.unscaledTime >= s_nextHotReloadCheck))
			{
				return;
			}
			s_nextHotReloadCheck = Time.unscaledTime + 2f;
			if (CraftingCategories.PollForEdit())
			{
				Player localPlayer = Player.m_localPlayer;
				if ((Object)(object)localPlayer != (Object)null && RecipeIndex.Built)
				{
					RecipeIndex.Build(localPlayer);
				}
				Logger.LogInfo((object)"Crafting Browser: categories.json changed, recipe categories rebuilt.");
			}
		}

		private void OnDestroy()
		{
			Harmony harmony = m_harmony;
			if (harmony != null)
			{
				harmony.UnpatchSelf();
			}
		}
	}
	public sealed class CategoryDef
	{
		public string id = "";

		public string label = "";

		public string[] match = Array.Empty<string>();

		public string[] itemTypes = Array.Empty<string>();

		public bool Matches(string internalName, ItemType itemType)
		{
			//IL_0057: 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)
			if (match != null)
			{
				for (int i = 0; i < match.Length; i++)
				{
					string value = match[i];
					if (!string.IsNullOrEmpty(value) && internalName.IndexOf(value, StringComparison.OrdinalIgnoreCase) >= 0)
					{
						return true;
					}
				}
			}
			if (itemTypes != null)
			{
				for (int j = 0; j < itemTypes.Length; j++)
				{
					if (Enum.TryParse<ItemType>(itemTypes[j], ignoreCase: true, out ItemType result) && result == itemType)
					{
						return true;
					}
				}
			}
			return false;
		}
	}
	public sealed class TopTabDef
	{
		public string id = "";

		public string label = "";

		public List<CategoryDef> categories = new List<CategoryDef>();

		[JsonIgnore]
		public int OtherSubIndex => categories.Count;
	}
	public sealed class CategoryTable
	{
		public List<TopTabDef> tabs = new List<TopTabDef>();

		public const string AllTabId = "all";

		public int RealTabStart => 1;

		public int SubCount(int tabIndex)
		{
			if (tabIndex < 0 || tabIndex >= tabs.Count)
			{
				return 0;
			}
			return tabs[tabIndex].categories.Count + 1;
		}

		public string SubLabel(int tabIndex, int subIndex)
		{
			if (tabIndex == 0)
			{
				return "All";
			}
			TopTabDef topTabDef = tabs[tabIndex];
			if (subIndex < topTabDef.categories.Count)
			{
				return topTabDef.categories[subIndex].label;
			}
			return "Other";
		}

		public void Resolve(string internalName, ItemType itemType, out int tabIndex, out int subIndex)
		{
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			for (int i = RealTabStart; i < tabs.Count; i++)
			{
				TopTabDef topTabDef = tabs[i];
				for (int j = 0; j < topTabDef.categories.Count; j++)
				{
					if (topTabDef.categories[j].Matches(internalName, itemType))
					{
						tabIndex = i;
						subIndex = j;
						return;
					}
				}
			}
			if (tabs.Count > RealTabStart)
			{
				tabIndex = RealTabStart;
				subIndex = tabs[RealTabStart].OtherSubIndex;
			}
			else
			{
				tabIndex = 0;
				subIndex = 0;
			}
		}
	}
	public static class CraftingCategories
	{
		private static string s_path;

		private static DateTime s_writtenUtc = DateTime.MinValue;

		private static int s_lastUnmatched;

		private static int s_lastTotal;

		public static CategoryTable Table { get; private set; }

		public static int LastUnmatched => s_lastUnmatched;

		public static int LastTotal => s_lastTotal;

		public static void Load(string pluginDirectory)
		{
			s_path = Path.Combine(pluginDirectory ?? ".", "categories.json");
			if (!File.Exists(s_path))
			{
				Table = BuildDefault();
				Save();
				Logger.LogInfo((object)("Crafting Browser: no categories.json found, wrote the default table to " + s_path));
				return;
			}
			try
			{
				s_writtenUtc = File.GetLastWriteTimeUtc(s_path);
				Table = JsonConvert.DeserializeObject<CategoryTable>(File.ReadAllText(s_path));
			}
			catch (Exception ex)
			{
				Logger.LogWarning((object)("Crafting Browser: categories.json is unreadable (" + ex.Message + "). Rewriting the default table."));
				Table = BuildDefault();
				Save();
				return;
			}
			if (Table == null || Table.tabs == null || Table.tabs.Count == 0)
			{
				Logger.LogWarning((object)"Crafting Browser: categories.json has no tabs. Rewriting the default table.");
				Table = BuildDefault();
				Save();
			}
			else if (Table.tabs[0].id != "all")
			{
				Logger.LogWarning((object)"Crafting Browser: categories.json must keep tabs[0].id = \"all\". Inserting a synthetic All tab.");
				Table.tabs.Insert(0, new TopTabDef
				{
					id = "all",
					label = "All"
				});
			}
		}

		public static void Save()
		{
			if (s_path == null || Table == null)
			{
				return;
			}
			try
			{
				File.WriteAllText(s_path, JsonConvert.SerializeObject((object)Table, (Formatting)1));
				s_writtenUtc = File.GetLastWriteTimeUtc(s_path);
			}
			catch (Exception ex)
			{
				Logger.LogWarning((object)("Crafting Browser: could not write categories.json: " + ex.Message));
			}
		}

		public static bool PollForEdit()
		{
			if (s_path == null || Table == null)
			{
				return false;
			}
			try
			{
				if (!File.Exists(s_path))
				{
					return false;
				}
				DateTime lastWriteTimeUtc = File.GetLastWriteTimeUtc(s_path);
				if (lastWriteTimeUtc <= s_writtenUtc)
				{
					return false;
				}
				s_writtenUtc = lastWriteTimeUtc;
				Table = JsonConvert.DeserializeObject<CategoryTable>(File.ReadAllText(s_path));
				if (Table != null && Table.tabs != null && Table.tabs.Count > 0 && Table.tabs[0].id == "all")
				{
					return true;
				}
				Logger.LogWarning((object)"Crafting Browser: edited categories.json is missing tabs, keeping the previous table.");
			}
			catch (Exception ex)
			{
				Logger.LogWarning((object)("Crafting Browser: could not re-read categories.json: " + ex.Message));
			}
			return false;
		}

		public static void ReportMatchRate(int total, int unmatched)
		{
			s_lastTotal = total;
			s_lastUnmatched = unmatched;
			if (total > 0)
			{
				Logger.LogInfo((object)($"Crafting Browser: {total - unmatched}/{total} recipes matched a category" + ((unmatched > 0) ? $"; {unmatched} filed under Other (edit categories.json to place them)" : ".")));
			}
		}

		public static CategoryTable BuildDefault()
		{
			CategoryTable categoryTable = new CategoryTable();
			categoryTable.tabs.Add(new TopTabDef
			{
				id = "all",
				label = "All"
			});
			categoryTable.tabs.Add(new TopTabDef
			{
				id = "weapons",
				label = "Weapons",
				categories = new List<CategoryDef>
				{
					ByName("polearms", "Polearms & Spears", "poleaxe", "spear", "atgeir", "pike", "halberd", "glaive"),
					ByName("hammers", "Hammers & Maces", "hammer", "mace", "maul", "club", "sledge"),
					ByName("swords", "Swords", "sword", "blade", "sabre", "rapier", "katana", "katana_"),
					ByName("axes", "Axes", "axe", "hatchet"),
					ByName("bows", "Bows & Crossbows", "bow", "crossbow", "ballista"),
					ByName("shields", "Shields", "shield", "buckler"),
					ByName("ammo", "Ammunition", "arrow", "bolt", "ammo")
				}
			});
			categoryTable.tabs.Add(new TopTabDef
			{
				id = "tools",
				label = "Tools",
				categories = new List<CategoryDef>
				{
					ByName("pickaxes", "Pickaxes", "pickaxe"),
					ByName("hammers", "Hammers", "hammer"),
					ByName("axes", "Axes", "axe"),
					ByName("shovels", "Shovels", "shovel"),
					ByName("rods", "Fishing Rods", "fishingrod", "rod")
				}
			});
			categoryTable.tabs.Add(new TopTabDef
			{
				id = "armor",
				label = "Armor",
				categories = new List<CategoryDef>
				{
					ByName("helmets", "Helmets", "helmet", "hood"),
					ByName("body", "Body", "armor", "hauberk", "plate", "tunic", "jacket", "robe", "harness", "mail"),
					ByName("legs", "Legs", "pants", "trousers", "skirt", "greaves", "boots", "leggings"),
					ByName("hands", "Hands", "gloves", "gauntlet", "mittens", "bracer"),
					ByName("cloaks", "Cloaks & Capes", "cape", "cloak", "mantle", "shawl")
				}
			});
			categoryTable.tabs.Add(new TopTabDef
			{
				id = "food",
				label = "Food & Drink",
				categories = new List<CategoryDef>
				{
					ByName("mead", "Meads", "mead"),
					ByName("drinks", "Drinks & Potions", "drink", "potion", "juice", "tea", "coffee", "ale", "wine", "sake"),
					ByName("fish", "Fish & Seafood", "fish", "seafood", "crab", "lobster", "shrimp", "squid", "eel"),
					ByName("cooked", "Cooked Food", "sausage", "stew", "soup", "pie", "cake", "bread", "pancake", "skewer"),
					ByItemType("food", "Raw & Basic Food", "Consumable")
				}
			});
			categoryTable.tabs.Add(new TopTabDef
			{
				id = "materials",
				label = "Materials",
				categories = new List<CategoryDef>
				{
					ByItemType("trophy", "Trophies", "Trophy"),
					ByName("relic", "Relics & Tinkering", "relic", "tinkering", "crystal", "rune"),
					ByItemType("trinket", "Trinkets", "Trinket"),
					ByItemType("crafting", "Crafting Materials", "Material"),
					ByItemType("misc", "Miscellaneous", "Misc")
				}
			});
			categoryTable.tabs.Add(new TopTabDef
			{
				id = "furniture",
				label = "Furniture",
				categories = new List<CategoryDef>
				{
					ByName("seating", "Seating", "chair", "stool", "bench", "throne", "bed"),
					ByName("tables", "Tables", "table", "shelf", "rack"),
					ByName("storage", "Storage", "chest", "backpack", "bag", "pouch", "bundle"),
					ByName("lighting", "Lighting", "candle", "torch", "lantern", "lamp", "brazier", "sconce"),
					ByName("decoration", "Decoration", "banner", "rug", "painting", "ornament", "sign", "carving", "loom", "weaver")
				}
			});
			return categoryTable;
		}

		private static CategoryDef ByName(string id, string label, params string[] keywords)
		{
			return new CategoryDef
			{
				id = id,
				label = label,
				match = (keywords ?? Array.Empty<string>())
			};
		}

		private static CategoryDef ByItemType(string id, string label, params string[] itemTypes)
		{
			return new CategoryDef
			{
				id = id,
				label = label,
				itemTypes = (itemTypes ?? Array.Empty<string>())
			};
		}
	}
	public enum VisibilityMode
	{
		Unlocked,
		CraftableHere,
		All
	}
	public sealed class RecipeEntry
	{
		public Recipe Recipe;

		public string InternalName = "";

		public string DisplayName = "";

		public Sprite Icon;

		public int Amount = 1;

		public int TopTab;

		public int SubCategory;

		public string StationName = "";

		public bool Unlocked;

		public bool StationOk;

		public bool CanCraftNow;

		public bool NameIsFallback;

		public int MaxCraftable;

		public bool MatchesSearch(string needle)
		{
			if (string.IsNullOrEmpty(needle))
			{
				return true;
			}
			if (InternalName.IndexOf(needle, StringComparison.OrdinalIgnoreCase) >= 0)
			{
				return true;
			}
			return DisplayName.IndexOf(needle, StringComparison.OrdinalIgnoreCase) >= 0;
		}
	}
	public static class RecipeIndex
	{
		public static readonly List<RecipeEntry> All = new List<RecipeEntry>();

		private const float RefreshInterval = 0.35f;

		private static float s_nextRefresh;

		private static int s_lastRecipeCount = -1;

		private static bool s_namesDirty = true;

		private static bool s_watchingLanguage;

		private static int s_untranslated;

		public static bool Built { get; private set; }

		public static int UntranslatedCount => s_untranslated;

		public static void Build(Player player)
		{
			//IL_019a: Unknown result type (might be due to invalid IL or missing references)
			All.Clear();
			Built = false;
			if ((Object)(object)player == (Object)null || (Object)(object)ObjectDB.instance == (Object)null)
			{
				return;
			}
			List<Recipe> recipes = ObjectDB.instance.m_recipes;
			if (recipes == null)
			{
				return;
			}
			s_lastRecipeCount = recipes.Count;
			SeasonalItemGroup currentSeason = player.CurrentSeason;
			for (int i = 0; i < recipes.Count; i++)
			{
				Recipe val = recipes[i];
				if ((Object)(object)val == (Object)null || (Object)(object)val.m_item == (Object)null)
				{
					continue;
				}
				bool flag = (Object)(object)currentSeason != (Object)null && currentSeason.Recipes != null && currentSeason.Recipes.Contains(val);
				if (val.m_enabled || flag)
				{
					SharedData val2 = ((val.m_item.m_itemData != null) ? val.m_item.m_itemData.m_shared : null);
					if (val2 != null && (string.IsNullOrEmpty(val2.m_dlc) || !((Object)(object)DLCMan.instance != (Object)null) || DLCMan.instance.IsDLCInstalled(val2.m_dlc)))
					{
						RecipeEntry recipeEntry = new RecipeEntry
						{
							Recipe = val,
							InternalName = val2.m_name,
							DisplayName = Localize(val2.m_name),
							Amount = Mathf.Max(1, val.m_amount),
							Icon = val.m_item.m_itemData.GetIcon()
						};
						CraftingStation requiredStation = val.GetRequiredStation(1);
						recipeEntry.StationName = (((Object)(object)requiredStation == (Object)null) ? "Basic" : Localize(requiredStation.m_name));
						CraftingCategories.Table.Resolve(recipeEntry.InternalName, val2.m_itemType, out recipeEntry.TopTab, out recipeEntry.SubCategory);
						All.Add(recipeEntry);
					}
				}
			}
			All.Sort((RecipeEntry a, RecipeEntry b) => string.Compare(a.DisplayName, b.DisplayName, StringComparison.OrdinalIgnoreCase));
			int num = 0;
			for (int num2 = 0; num2 < All.Count; num2++)
			{
				if (All[num2].SubCategory == CraftingCategories.Table.tabs[All[num2].TopTab].OtherSubIndex)
				{
					num++;
				}
			}
			CraftingCategories.ReportMatchRate(All.Count, num);
			WatchLanguage();
			ResolveNames();
			Refresh(player, force: true);
			Built = true;
		}

		private static void ResolveNames()
		{
			if (All.Count == 0)
			{
				return;
			}
			int num = 0;
			for (int i = 0; i < All.Count; i++)
			{
				RecipeEntry recipeEntry = All[i];
				if ((Object)(object)recipeEntry.Recipe == (Object)null || (Object)(object)recipeEntry.Recipe.m_item == (Object)null || recipeEntry.Recipe.m_item.m_itemData == null)
				{
					continue;
				}
				SharedData shared = recipeEntry.Recipe.m_item.m_itemData.m_shared;
				if (shared != null)
				{
					bool flag = shared.m_name != null && shared.m_name.Length > 0 && shared.m_name[0] == '$';
					recipeEntry.DisplayName = Localize(shared.m_name);
					recipeEntry.NameIsFallback = flag && string.Equals(recipeEntry.DisplayName, Prettify(shared.m_name), StringComparison.Ordinal);
					if (recipeEntry.NameIsFallback)
					{
						num++;
					}
					CraftingStation requiredStation = recipeEntry.Recipe.GetRequiredStation(1);
					recipeEntry.StationName = (((Object)(object)requiredStation == (Object)null) ? "Basic" : Localize(requiredStation.m_name));
				}
			}
			All.Sort((RecipeEntry a, RecipeEntry b) => string.Compare(a.DisplayName, b.DisplayName, StringComparison.OrdinalIgnoreCase));
			s_untranslated = num;
			if (num > 0)
			{
				string text = ((All[0] != null) ? All[0].InternalName : "?");
				Logger.LogWarning((object)($"Crafting Browser: {num}/{All.Count} names could not be localized and are " + "shown prettified from the key instead (e.g. '" + text + "'). Set language in the main menu and the names will re-resolve."));
			}
			else
			{
				Logger.LogInfo((object)"Crafting Browser: all recipe names localized.");
			}
		}

		private static void WatchLanguage()
		{
			if (s_watchingLanguage)
			{
				return;
			}
			try
			{
				Localization.OnLanguageChange = (Action)Delegate.Combine(Localization.OnLanguageChange, new Action(OnLanguageChanged));
				s_watchingLanguage = true;
			}
			catch (Exception ex)
			{
				Logger.LogWarning((object)("Crafting Browser: could not watch for language changes: " + ex.Message));
			}
		}

		private static void OnLanguageChanged()
		{
			s_namesDirty = true;
		}

		public static string CurrentStationName(Player player)
		{
			if ((Object)(object)player == (Object)null)
			{
				return "";
			}
			CraftingStation currentCraftingStation = player.GetCurrentCraftingStation();
			if (!((Object)(object)currentCraftingStation == (Object)null))
			{
				return Localize(currentCraftingStation.m_name);
			}
			return "No station";
		}

		public static void Refresh(Player player, bool force = false)
		{
			if (Built && !((Object)(object)player == (Object)null) && (force || !(Time.unscaledTime < s_nextRefresh)))
			{
				s_nextRefresh = Time.unscaledTime + 0.35f;
				if (s_namesDirty)
				{
					s_namesDirty = false;
					ResolveNames();
				}
				CraftingStation currentCraftingStation = player.GetCurrentCraftingStation();
				bool atUpgrader = (Object)(object)currentCraftingStation != (Object)null && currentCraftingStation.m_upgrader;
				Inventory inventory = ((Humanoid)player).GetInventory();
				for (int i = 0; i < All.Count; i++)
				{
					RecipeEntry recipeEntry = All[i];
					Recipe recipe = recipeEntry.Recipe;
					recipeEntry.Unlocked = player.IsRecipeKnown(recipeEntry.InternalName);
					recipeEntry.StationOk = player.RequiredCraftingStation(recipe, 1, true);
					recipeEntry.CanCraftNow = player.HaveRequirements(recipe, false, 1, 1);
					recipeEntry.MaxCraftable = ((inventory != null) ? MaxCraftable(player, recipe, inventory, currentCraftingStation, atUpgrader) : 0);
				}
			}
		}

		private static int MaxCraftable(Player player, Recipe recipe, Inventory inventory, CraftingStation station, bool atUpgrader)
		{
			Requirement[] resources = recipe.m_resources;
			if (resources == null || resources.Length == 0)
			{
				return 0;
			}
			int num = int.MaxValue;
			foreach (Requirement val in resources)
			{
				if (val == null || (Object)(object)val.m_resItem == (Object)null || val.m_resItem.m_itemData == null || (val.m_upgraderResource && ((Object)(object)station == (Object)null || !atUpgrader)))
				{
					continue;
				}
				int num2 = Mathf.Max(1, val.GetAmount(1));
				int num3 = inventory.CountItems(val.m_resItem.m_itemData.m_shared.m_name, -1, true) / num2;
				if (recipe.m_requireOnlyOneIngredient)
				{
					if (num3 > num)
					{
						num = num3;
					}
				}
				else if (num3 < num)
				{
					num = num3;
				}
			}
			if (num == int.MaxValue)
			{
				return 0;
			}
			return Mathf.Max(0, num);
		}

		public static void Filter(List<RecipeEntry> destination, string search, int tabIndex, int subIndex, VisibilityMode mode)
		{
			destination.Clear();
			if (CraftingCategories.Table == null)
			{
				return;
			}
			for (int i = 0; i < All.Count; i++)
			{
				RecipeEntry recipeEntry = All[i];
				if ((mode != VisibilityMode.Unlocked || recipeEntry.Unlocked) && (mode != VisibilityMode.CraftableHere || (recipeEntry.Unlocked && recipeEntry.CanCraftNow)) && (tabIndex <= 0 || recipeEntry.TopTab == tabIndex) && (tabIndex <= 0 || recipeEntry.SubCategory == subIndex) && recipeEntry.MatchesSearch(search))
				{
					destination.Add(recipeEntry);
				}
			}
		}

		public static void CountBySubcategory(int tabIndex, VisibilityMode mode, Dictionary<int, int> counts)
		{
			counts.Clear();
			if (tabIndex <= 0)
			{
				return;
			}
			int num = CraftingCategories.Table.SubCount(tabIndex);
			for (int i = 0; i < num; i++)
			{
				counts[i] = 0;
			}
			for (int j = 0; j < All.Count; j++)
			{
				RecipeEntry recipeEntry = All[j];
				if (recipeEntry.TopTab == tabIndex && (mode != VisibilityMode.Unlocked || recipeEntry.Unlocked) && (mode != VisibilityMode.CraftableHere || (recipeEntry.Unlocked && recipeEntry.CanCraftNow)) && counts.ContainsKey(recipeEntry.SubCategory))
				{
					counts[recipeEntry.SubCategory]++;
				}
			}
		}

		public static string Localize(string key)
		{
			if (string.IsNullOrEmpty(key))
			{
				return "";
			}
			if (key[0] != '$')
			{
				return key;
			}
			string text = null;
			try
			{
				Localization instance = Localization.instance;
				if (instance != null)
				{
					text = instance.Localize(key);
				}
			}
			catch (Exception)
			{
			}
			if (!string.IsNullOrEmpty(text) && text[0] != '$')
			{
				return text;
			}
			return Prettify(key);
		}

		public static string Prettify(string key)
		{
			if (string.IsNullOrEmpty(key))
			{
				return "";
			}
			string text = (key.StartsWith("$") ? key.Substring(1) : key);
			List<string> list = new List<string>(text.Split('_'));
			if (list.Count > 1 && IsKeyNamespace(list[0]))
			{
				list.RemoveAt(0);
			}
			List<string> list2 = new List<string>();
			foreach (string item in list)
			{
				if (!string.IsNullOrEmpty(item))
				{
					list2.AddRange(SplitCamelCase(item));
				}
			}
			if (list2.Count == 0)
			{
				return text;
			}
			StringBuilder stringBuilder = new StringBuilder();
			foreach (string item2 in list2)
			{
				if (stringBuilder.Length > 0)
				{
					stringBuilder.Append(' ');
				}
				stringBuilder.Append(char.ToUpperInvariant(item2[0]));
				if (item2.Length > 1)
				{
					stringBuilder.Append(item2.Substring(1));
				}
			}
			return stringBuilder.ToString();
		}

		private static bool IsKeyNamespace(string segment)
		{
			switch (segment.ToLowerInvariant())
			{
			case "item":
			case "misc":
			case "craft":
			case "enemy":
			case "piece":
			case "builder":
			case "gamenet":
			case "msg":
			case "crafting":
			case "recipe":
				return true;
			default:
				return false;
			}
		}

		private static IEnumerable<string> SplitCamelCase(string part)
		{
			List<string> list = new List<string>();
			StringBuilder stringBuilder = new StringBuilder();
			foreach (char c in part)
			{
				if (char.IsUpper(c) && stringBuilder.Length > 0)
				{
					list.Add(stringBuilder.ToString());
					stringBuilder.Length = 0;
				}
				stringBuilder.Append(c);
			}
			if (stringBuilder.Length > 0)
			{
				list.Add(stringBuilder.ToString());
			}
			return list;
		}
	}
}