Decompiled source of RecipeHelper v1.0.0

plugins/RecipeHelper/RecipeHelper.dll

Decompiled a day ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using System.Text;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using BepInEx.Logging;
using Microsoft.CodeAnalysis;
using RiskOfOptions;
using RiskOfOptions.OptionConfigs;
using RiskOfOptions.Options;
using RoR2;
using RoR2.UI;
using TMPro;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.Events;
using UnityEngine.UI;

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

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace RecipeHelper
{
	internal sealed class CraftingPanelWatcher : MonoBehaviour
	{
		private HUD hud;

		private int lastChildCount;

		private void Awake()
		{
			hud = ((Component)this).GetComponent<HUD>();
			Log("watching HUD '" + ((Object)this).name + "'");
		}

		private static void Log(string message)
		{
			if (RecipeHelperPlugin.Settings.DebugLogging.Value)
			{
				RecipeHelperPlugin.Log.LogInfo((object)("Watcher: " + message));
			}
		}

		private void Update()
		{
			Transform val = (Object.op_Implicit((Object)(object)hud) ? hud.mainContainer.transform : null);
			if (!Object.op_Implicit((Object)(object)val) || val.childCount == lastChildCount)
			{
				return;
			}
			lastChildCount = val.childCount;
			CraftingPanel[] componentsInChildren = ((Component)val).GetComponentsInChildren<CraftingPanel>(true);
			foreach (CraftingPanel val2 in componentsInChildren)
			{
				Log($"found CraftingPanel '{((Object)val2).name}' active={((Component)val2).gameObject.activeInHierarchy} sidebar={Object.op_Implicit((Object)(object)((Component)val2).GetComponent<RecipeSidebar>())}");
				if (!Object.op_Implicit((Object)(object)((Component)val2).GetComponent<RecipeSidebar>()))
				{
					((Component)val2).gameObject.AddComponent<RecipeSidebar>().Init(hud);
				}
			}
		}
	}
	internal sealed class CraftPlan
	{
		public PickupIndex Result;

		public List<CraftStep> Steps;
	}
	internal sealed class CraftStep
	{
		public RecipeEntry Recipe;

		public PickupIndex[] Ingredients;

		public PickupIndex Result => Recipe.result;

		public int Amount => Recipe.amountToDrop;
	}
	internal sealed class InventorySnapshot
	{
		private readonly Dictionary<PickupIndex, int> counts;

		public bool IsEmpty => counts.Count == 0;

		public InventorySnapshot(Dictionary<PickupIndex, int> counts)
		{
			this.counts = counts;
		}

		public int Count(PickupIndex pickup)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			if (!counts.TryGetValue(pickup, out var value))
			{
				return 0;
			}
			return value;
		}

		public static InventorySnapshot FromInventory(Inventory inventory)
		{
			//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_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Invalid comparison between Unknown and I4
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0042: Unknown result type (might be due to invalid IL or missing references)
			//IL_0043: 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_0085: 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)
			Dictionary<PickupIndex, int> dictionary = new Dictionary<PickupIndex, int>();
			if (!Object.op_Implicit((Object)(object)inventory))
			{
				return new InventorySnapshot(dictionary);
			}
			EquipmentIndex equipmentIndex = inventory.GetEquipmentIndex();
			if ((int)equipmentIndex != -1)
			{
				dictionary[PickupCatalog.FindPickupIndex(equipmentIndex)] = 1;
			}
			foreach (ItemIndex item in inventory.itemAcquisitionOrder)
			{
				ItemDef itemDef = ItemCatalog.GetItemDef(item);
				int itemCountPermanent = inventory.GetItemCountPermanent(item);
				if (Object.op_Implicit((Object)(object)itemDef) && ((itemDef.canRemove && !itemDef.hidden && itemCountPermanent > 0) || itemDef.ContainsTag((ItemTag)30)) && itemCountPermanent > 0)
				{
					dictionary[PickupCatalog.FindPickupIndex(item)] = itemCountPermanent;
				}
			}
			return new InventorySnapshot(dictionary);
		}

		public InventorySnapshot Apply(CraftStep step)
		{
			//IL_0019: 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_0021: 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_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cf: Unknown result type (might be due to invalid IL or missing references)
			//IL_00de: 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_0066: Invalid comparison between Unknown and I4
			//IL_007e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0083: Unknown result type (might be due to invalid IL or missing references)
			//IL_0085: Unknown result type (might be due to invalid IL or missing references)
			//IL_0094: Unknown result type (might be due to invalid IL or missing references)
			//IL_009a: Invalid comparison between Unknown and I4
			//IL_00c0: 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)
			Dictionary<PickupIndex, int> dictionary = new Dictionary<PickupIndex, int>(counts);
			PickupIndex[] ingredients = step.Ingredients;
			foreach (PickupIndex key in ingredients)
			{
				int num = dictionary[key] - 1;
				if (num > 0)
				{
					dictionary[key] = num;
				}
				else
				{
					dictionary.Remove(key);
				}
			}
			PickupDef pickupDef = PickupCatalog.GetPickupDef(step.Result);
			if (pickupDef != null && (int)pickupDef.equipmentIndex != -1)
			{
				foreach (PickupIndex item in dictionary.Keys.ToList())
				{
					PickupDef pickupDef2 = PickupCatalog.GetPickupDef(item);
					if (pickupDef2 != null && (int)pickupDef2.equipmentIndex != -1)
					{
						dictionary.Remove(item);
					}
				}
				dictionary[step.Result] = 1;
			}
			else
			{
				dictionary.TryGetValue(step.Result, out var value);
				dictionary[step.Result] = value + step.Amount;
			}
			return new InventorySnapshot(dictionary);
		}

		public string Key()
		{
			//IL_0042: Unknown result type (might be due to invalid IL or missing references)
			StringBuilder stringBuilder = new StringBuilder();
			foreach (KeyValuePair<PickupIndex, int> item in counts.OrderBy((KeyValuePair<PickupIndex, int> p) => p.Key.value))
			{
				stringBuilder.Append(item.Key.value).Append(':').Append(item.Value)
					.Append(',');
			}
			return stringBuilder.ToString();
		}

		public override string ToString()
		{
			return string.Join(", ", counts.Select((KeyValuePair<PickupIndex, int> p) => PickupCatalog.GetPickupDef(p.Key)?.internalName + " x" + p.Value));
		}
	}
	internal static class ListView
	{
		public const string Hint = "Click a row to put its first craft in the slots.";

		private const float ResultSize = 44f;

		private const float NextSize = 24f;

		private const int MaxAlternateNames = 3;

		private const float LaterStepAlpha = 0.55f;

		private static readonly Color RowHover = new Color(1f, 1f, 1f, 0.09f);

		private static readonly Color RowInSlots = Color32.op_Implicit(new Color32((byte)143, (byte)163, (byte)199, (byte)41));

		private static readonly Color BadgeInSlots = Color32.op_Implicit(new Color32((byte)195, (byte)210, (byte)238, byte.MaxValue));

		private static readonly Color BadgeDefault = Color32.op_Implicit(new Color32((byte)143, (byte)163, (byte)199, (byte)38));

		private static readonly Color BadgeInSlotsText = Color32.op_Implicit(new Color32((byte)11, (byte)14, (byte)20, byte.MaxValue));

		public static List<SidebarBlock> Blocks(List<CraftPlan> plans, InventorySnapshot start, Func<CraftStep, bool> inSlots, Action<CraftStep> fill)
		{
			List<SidebarBlock> list = new List<SidebarBlock>
			{
				new SidebarBlock
				{
					Build = delegate(RectTransform parent, float width)
					{
						//IL_000b: Unknown result type (might be due to invalid IL or missing references)
						Ui.Text((Transform)(object)parent, "Click a row to put its first craft in the slots.", 12f, Ui.Muted);
					}
				}
			};
			foreach (CraftPlan plan in plans)
			{
				CraftPlan captured = plan;
				list.Add(new SidebarBlock
				{
					Group = GroupLabel(plan.Steps.Count),
					Results = 1,
					Build = delegate(RectTransform parent, float width)
					{
						Row(parent, captured, StepDetail.Build(start, captured), inSlots(captured.Steps[0]), fill);
					}
				});
			}
			return list;
		}

		private static string GroupLabel(int steps)
		{
			if (steps != 1)
			{
				return "IN " + steps + " CRAFTS";
			}
			return "NOW";
		}

		private static void Row(RectTransform parent, CraftPlan plan, List<StepDetail> details, bool inSlots, Action<CraftStep> fill)
		{
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			//IL_004d: Unknown result type (might be due to invalid IL or missing references)
			//IL_004f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0057: 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_00d6: 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)
			//IL_01a7: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b5: Unknown result type (might be due to invalid IL or missing references)
			//IL_01da: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e4: Expected O, but got Unknown
			//IL_01f7: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f8: 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_0200: Unknown result type (might be due to invalid IL or missing references)
			//IL_0208: Unknown result type (might be due to invalid IL or missing references)
			//IL_012c: Unknown result type (might be due to invalid IL or missing references)
			RectTransform val = Ui.Row((Transform)(object)parent, "Recipe", 12f);
			Ui.Pad(val, 8);
			((LayoutGroup)((Component)val).GetComponent<HorizontalLayoutGroup>()).childAlignment = (TextAnchor)3;
			Image val2 = ((Component)val).gameObject.AddComponent<Image>();
			Color val3 = (((Graphic)val2).color = (inSlots ? RowInSlots : Ui.CardBackground));
			Ui.Tile((Transform)(object)val, plan.Result, 44f);
			RectTransform val5 = Ui.Stack((Transform)(object)val, "Body", 5f, (TextAnchor)0);
			Ui.Flexible(val5);
			int amount = plan.Steps[plan.Steps.Count - 1].Amount;
			Ui.Text((Transform)(object)val5, Ui.Name(plan.Result) + ((amount > 1) ? (" x" + amount) : ""), 16f, Ui.TierColor(plan.Result));
			for (int i = 0; i < details.Count; i++)
			{
				Craft(val5, details[i], (details.Count > 1) ? (i + 1) : 0);
				string text = ((i == 0) ? AlternateNames(details[0]) : null);
				if (text != null)
				{
					Ui.Text((Transform)(object)val5, text, 11f, Ui.Muted);
				}
			}
			Badge(val, inSlots ? "In slots" : ((plan.Steps.Count == 1) ? "1 craft" : (plan.Steps.Count + " crafts")), inSlots);
			Button obj = ((Component)val).gameObject.AddComponent<Button>();
			((Selectable)obj).targetGraphic = (Graphic)(object)val2;
			((Selectable)obj).transition = (Transition)0;
			Navigation navigation = default(Navigation);
			((Navigation)(ref navigation)).mode = (Mode)0;
			((Selectable)obj).navigation = navigation;
			CraftStep step = plan.Steps[0];
			((UnityEvent)obj.onClick).AddListener((UnityAction)delegate
			{
				fill(step);
			});
			HoverColor hoverColor = ((Component)val).gameObject.AddComponent<HoverColor>();
			hoverColor.Target = val2;
			hoverColor.Normal = val3;
			hoverColor.Hover = (inSlots ? val3 : RowHover);
		}

		private static void Craft(RectTransform body, StepDetail detail, int number)
		{
			//IL_0038: 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_0090: Unknown result type (might be due to invalid IL or missing references)
			RectTransform val = Ui.Row((Transform)(object)body, "Craft", 4f);
			((LayoutGroup)((Component)val).GetComponent<HorizontalLayoutGroup>()).childAlignment = (TextAnchor)3;
			if (number > 0)
			{
				Ui.Size(((TMP_Text)Ui.Text((Transform)(object)val, number + ".", 11f, Ui.Muted)).rectTransform, 14f, 24f);
			}
			if (number > 1)
			{
				((Component)val).gameObject.AddComponent<CanvasGroup>().alpha = 0.55f;
			}
			for (int i = 0; i < detail.Slots.Length; i++)
			{
				if (i > 0)
				{
					Ui.Glyph((Transform)(object)val, "+", 24f);
				}
				Ui.Tile((Transform)(object)val, detail.Slots[i].Chosen, 24f, detail.Slots[i].MadeByEarlierStep);
			}
			Ui.Glyph((Transform)(object)val, "→", 24f);
			Ui.Tile((Transform)(object)val, detail.Step.Result, 24f);
		}

		private static string AlternateNames(StepDetail next)
		{
			//IL_0024: 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_002c: Unknown result type (might be due to invalid IL or missing references)
			List<string> list = new List<string>();
			SlotDetail[] slots = next.Slots;
			for (int i = 0; i < slots.Length; i++)
			{
				foreach (PickupIndex alternate in slots[i].Alternates)
				{
					list.Add(Ui.Name(alternate));
				}
			}
			if (list.Count == 0)
			{
				return null;
			}
			string text = string.Join(", ", list.GetRange(0, Math.Min(list.Count, 3)));
			return "or " + text + ((list.Count > 3) ? (" +" + (list.Count - 3) + " more") : "");
		}

		private static void Badge(RectTransform row, string text, bool inSlots)
		{
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: Expected O, but got Unknown
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_0049: Unknown result type (might be due to invalid IL or missing references)
			//IL_0042: Unknown result type (might be due to invalid IL or missing references)
			RectTransform obj = Ui.Row((Transform)(object)row, "Badge", 0f);
			((LayoutGroup)((Component)obj).GetComponent<HorizontalLayoutGroup>()).padding = new RectOffset(8, 8, 3, 3);
			Ui.Background(obj, inSlots ? BadgeInSlots : BadgeDefault);
			((TMP_Text)Ui.Text((Transform)(object)obj, text, 11f, inSlots ? BadgeInSlotsText : Ui.Muted)).enableWordWrapping = false;
		}
	}
	internal sealed class HoverColor : MonoBehaviour, IPointerEnterHandler, IEventSystemHandler, IPointerExitHandler
	{
		public Image Target;

		public Color Normal;

		public Color Hover;

		public void OnPointerEnter(PointerEventData eventData)
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			((Graphic)Target).color = Hover;
		}

		public void OnPointerExit(PointerEventData eventData)
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			((Graphic)Target).color = Normal;
		}
	}
	internal static class PickupRarity
	{
		public static int Rank(PickupIndex index)
		{
			//IL_0000: 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: Invalid comparison between Unknown and I4
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			//IL_003e: Invalid comparison between Unknown and I4
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			PickupDef pickupDef = PickupCatalog.GetPickupDef(index);
			if (pickupDef == null)
			{
				return 0;
			}
			if ((int)pickupDef.itemIndex != -1)
			{
				ItemDef itemDef = ItemCatalog.GetItemDef(pickupDef.itemIndex);
				if (!Object.op_Implicit((Object)(object)itemDef))
				{
					return 0;
				}
				return ItemRank(itemDef.tier);
			}
			if ((int)pickupDef.equipmentIndex != -1)
			{
				EquipmentDef equipmentDef = EquipmentCatalog.GetEquipmentDef(pickupDef.equipmentIndex);
				if (!Object.op_Implicit((Object)(object)equipmentDef))
				{
					return 0;
				}
				if (equipmentDef.isBoss)
				{
					return ItemRank((ItemTier)4);
				}
				if (equipmentDef.isLunar)
				{
					return ItemRank((ItemTier)3);
				}
				return 4;
			}
			return 0;
		}

		private static int ItemRank(ItemTier tier)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0032: Expected I4, but got Unknown
			switch ((int)tier)
			{
			case 10:
				return 9;
			case 2:
			case 8:
				return 8;
			case 4:
			case 9:
				return 7;
			case 3:
				return 6;
			case 1:
			case 7:
				return 3;
			case 0:
			case 6:
				return 2;
			default:
				return 1;
			}
		}
	}
	internal sealed class PluginConfig
	{
		public readonly ConfigEntry<bool> Enabled;

		public readonly ConfigEntry<int> MaxChainSteps;

		public readonly ConfigEntry<bool> DebugLogging;

		public readonly ConfigEntry<bool> DebugAlwaysShow;

		public readonly ConfigEntry<KeyboardShortcut> DumpKey;

		public PluginConfig(ConfigFile config)
		{
			//IL_0040: Unknown result type (might be due to invalid IL or missing references)
			//IL_004a: Expected O, but got Unknown
			//IL_009d: Unknown result type (might be due to invalid IL or missing references)
			Enabled = config.Bind<bool>("Sidebar", "Enabled", true, "Show the list of craftable items beside the Wandering CHEF's crafting dialog.");
			MaxChainSteps = config.Bind<int>("Sidebar", "MaxChainSteps", 3, new ConfigDescription("The most crafts in a row to look ahead, counting crafts whose results are used as ingredients in later ones.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 5), Array.Empty<object>()));
			DebugLogging = config.Bind<bool>("Debug", "DebugLogging", false, "Enable the dump key, which logs the recipe catalog size and the plan for your inventory.");
			DebugAlwaysShow = config.Bind<bool>("Debug", "DebugAlwaysShow", false, "List every recipe regardless of your inventory, for testing the layout.");
			DumpKey = config.Bind<KeyboardShortcut>("Debug", "DumpKey", new KeyboardShortcut((KeyCode)289, Array.Empty<KeyCode>()), "With DebugLogging on, press to log the recipe catalog size and the plan for your inventory.");
		}
	}
	internal static class RecipeBook
	{
		private static Run builtFor;

		private static RecipePlanner planner;

		public static RecipePlanner Planner
		{
			get
			{
				if (planner == null || (Object)(object)builtFor != (Object)(object)Run.instance)
				{
					RecipeEntry[] allRecipes = CraftableCatalog.GetAllRecipes();
					if (Object.op_Implicit((Object)(object)Run.instance))
					{
						CraftableCatalog.FilterByEntitlement(ref allRecipes);
					}
					planner = new RecipePlanner(allRecipes);
					builtFor = Run.instance;
				}
				return planner;
			}
		}
	}
	[BepInPlugin("sevenstack.RecipeHelper", "RecipeHelper", "1.0.0")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	public class RecipeHelperPlugin : BaseUnityPlugin
	{
		public const string PluginGUID = "sevenstack.RecipeHelper";

		public const string PluginName = "RecipeHelper";

		public const string PluginVersion = "1.0.0";

		internal static ManualLogSource Log;

		internal static PluginConfig Settings;

		private void Awake()
		{
			Log = ((BaseUnityPlugin)this).Logger;
			Settings = new PluginConfig(((BaseUnityPlugin)this).Config);
			if (RiskOfOptionsCompat.Enabled)
			{
				RiskOfOptionsCompat.Register(Settings);
			}
			HUD.onHudTargetChangedGlobal += OnHudTargetChanged;
		}

		private void OnDestroy()
		{
			HUD.onHudTargetChangedGlobal -= OnHudTargetChanged;
		}

		private static void OnHudTargetChanged(HUD hud)
		{
			if (Settings.Enabled.Value && Object.op_Implicit((Object)(object)hud) && !Object.op_Implicit((Object)(object)((Component)hud).GetComponent<CraftingPanelWatcher>()))
			{
				((Component)hud).gameObject.AddComponent<CraftingPanelWatcher>();
			}
		}

		private void Update()
		{
			//IL_001b: 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)
			if (Settings.DebugLogging.Value)
			{
				KeyboardShortcut value = Settings.DumpKey.Value;
				if (((KeyboardShortcut)(ref value)).IsDown())
				{
					Dump();
				}
			}
		}

		private static void Dump()
		{
			//IL_008c: Unknown result type (might be due to invalid IL or missing references)
			LocalUser firstLocalUser = LocalUserManager.GetFirstLocalUser();
			Inventory inventory = (Object.op_Implicit((Object)(object)((firstLocalUser != null) ? firstLocalUser.cachedMaster : null)) ? firstLocalUser.cachedMaster.inventory : null);
			RecipePlanner planner = RecipeBook.Planner;
			InventorySnapshot inventorySnapshot = InventorySnapshot.FromInventory(inventory);
			Log.LogInfo((object)$"Recipe dump: {CraftableCatalog.GetAllRecipes().Length} recipes, inventory: {inventorySnapshot}");
			foreach (CraftPlan item in planner.Plan(inventorySnapshot, Settings.MaxChainSteps.Value, 20000))
			{
				Log.LogInfo((object)string.Format("  {0} in {1}: {2}", PickupCatalog.GetPickupDef(item.Result)?.internalName, item.Steps.Count, string.Join(" ; ", item.Steps.ConvertAll((CraftStep s) => string.Join("+", Array.ConvertAll(s.Ingredients, (PickupIndex i) => PickupCatalog.GetPickupDef(i)?.internalName)) + "->" + PickupCatalog.GetPickupDef(s.Result)?.internalName))));
			}
		}
	}
	internal sealed class RecipePlanner
	{
		private sealed class Node
		{
			public InventorySnapshot State;

			public List<CraftStep> Path;
		}

		private readonly RecipeEntry[] recipes;

		private readonly HashSet<PickupIndex> intermediates = new HashSet<PickupIndex>();

		public bool HitBudget { get; private set; }

		public RecipePlanner(RecipeEntry[] recipes)
		{
			//IL_004b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0050: Unknown result type (might be due to invalid IL or missing references)
			//IL_0058: Unknown result type (might be due to invalid IL or missing references)
			this.recipes = recipes;
			for (int i = 0; i < recipes.Length; i++)
			{
				IngredientSlotEntry[] possibleIngredients = recipes[i].possibleIngredients;
				foreach (IngredientSlotEntry val in possibleIngredients)
				{
					if (val.pickups != null)
					{
						PickupIndex[] pickups = val.pickups;
						foreach (PickupIndex item in pickups)
						{
							intermediates.Add(item);
						}
					}
				}
			}
		}

		public List<CraftPlan> Plan(InventorySnapshot start, int maxSteps, int stateBudget)
		{
			//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_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_00e5: Unknown result type (might be due to invalid IL or missing references)
			HitBudget = false;
			Dictionary<PickupIndex, CraftPlan> dictionary = new Dictionary<PickupIndex, CraftPlan>();
			HashSet<string> hashSet = new HashSet<string> { start.Key() };
			List<Node> list = new List<Node>
			{
				new Node
				{
					State = start,
					Path = new List<CraftStep>()
				}
			};
			int num = 0;
			for (int i = 1; i <= maxSteps; i++)
			{
				if (list.Count <= 0)
				{
					break;
				}
				List<Node> list2 = new List<Node>();
				foreach (Node item in list)
				{
					foreach (CraftStep item2 in EnumerateCrafts(item.State))
					{
						List<CraftStep> list3 = new List<CraftStep>(item.Path) { item2 };
						if (!dictionary.ContainsKey(item2.Result))
						{
							dictionary[item2.Result] = new CraftPlan
							{
								Result = item2.Result,
								Steps = list3
							};
						}
						if (i == maxSteps || !intermediates.Contains(item2.Result))
						{
							continue;
						}
						InventorySnapshot inventorySnapshot = item.State.Apply(item2);
						if (hashSet.Add(inventorySnapshot.Key()))
						{
							if (++num > stateBudget)
							{
								HitBudget = true;
								return Sorted(dictionary);
							}
							list2.Add(new Node
							{
								State = inventorySnapshot,
								Path = list3
							});
						}
					}
				}
				list = list2;
			}
			return Sorted(dictionary);
		}

		private static List<CraftPlan> Sorted(Dictionary<PickupIndex, CraftPlan> best)
		{
			return (from p in best.Values
				orderby p.Steps.Count, PickupRarity.Rank(p.Result) descending, Language.GetString(PickupCatalog.GetPickupDef(p.Result)?.nameToken ?? "")
				select p).ToList();
		}

		internal IEnumerable<CraftStep> EnumerateCrafts(InventorySnapshot state)
		{
			RecipeEntry[] array = recipes;
			foreach (RecipeEntry recipe in array)
			{
				HashSet<string> emitted = new HashSet<string>();
				PickupIndex[] chosen = (PickupIndex[])(object)new PickupIndex[recipe.possibleIngredients.Length];
				foreach (PickupIndex[] item2 in Fill(recipe, state, chosen, 0))
				{
					string item = string.Join(",", from p in item2
						select p.value into v
						orderby v
						select v);
					if (emitted.Add(item))
					{
						yield return new CraftStep
						{
							Recipe = recipe,
							Ingredients = (PickupIndex[])item2.Clone()
						};
					}
				}
			}
		}

		private static IEnumerable<PickupIndex[]> Fill(RecipeEntry recipe, InventorySnapshot state, PickupIndex[] chosen, int slot)
		{
			if (slot == chosen.Length)
			{
				yield return chosen;
				yield break;
			}
			PickupIndex[] pickups = recipe.possibleIngredients[slot].pickups;
			if (pickups == null)
			{
				yield break;
			}
			PickupIndex[] array = pickups;
			foreach (PickupIndex val in array)
			{
				int num = 0;
				for (int j = 0; j < slot; j++)
				{
					if (chosen[j] == val)
					{
						num++;
					}
				}
				if (state.Count(val) <= num)
				{
					continue;
				}
				chosen[slot] = val;
				foreach (PickupIndex[] item in Fill(recipe, state, chosen, slot + 1))
				{
					yield return item;
				}
			}
		}
	}
	internal sealed class RecipeSidebar : MonoBehaviour
	{
		private const string Header = "You can craft";

		private const string ContinuedHeader = "You can craft (continued)";

		private const string NothingHeader = "Nothing to craft";

		private const int SettleFrames = 3;

		private CraftingPanel panel;

		private Inventory inventory;

		private SidebarColumn left;

		private SidebarColumn right;

		private bool rendered;

		private bool lastTruncated;

		private bool settled;

		private int stillFrames;

		private Rect lastWindow;

		private int lastSlots;

		private InventorySnapshot snapshot;

		internal List<CraftPlan> Plans { get; private set; } = new List<CraftPlan>();

		public void Init(HUD owner)
		{
			panel = ((Component)this).GetComponent<CraftingPanel>();
			left = new SidebarColumn(((Component)this).transform, "RecipeHelperSidebarLeft");
			right = new SidebarColumn(((Component)this).transform, "RecipeHelperSidebarRight");
			right.Hide();
			if (RecipeHelperPlugin.Settings.DebugLogging.Value)
			{
				RecipeHelperPlugin.Log.LogInfo((object)("Sidebar: built on '" + ((Object)this).name + "'"));
			}
		}

		private void Update()
		{
			CraftingController craftingController = panel.craftingController;
			object obj;
			if (craftingController == null)
			{
				obj = null;
			}
			else
			{
				NetworkUIPromptController networkUIPromptController = ((PickupPickerController)craftingController).networkUIPromptController;
				obj = ((networkUIPromptController != null) ? networkUIPromptController.currentParticipantMaster : null);
			}
			CharacterMaster val = (CharacterMaster)obj;
			Inventory val2 = (Object.op_Implicit((Object)(object)val) ? val.inventory : null);
			WatchWindow();
			WatchSlots();
			if (!rendered || !((Object)(object)val2 == (Object)(object)inventory))
			{
				if (Object.op_Implicit((Object)(object)inventory))
				{
					inventory.onInventoryChanged -= Refresh;
				}
				inventory = val2;
				if (Object.op_Implicit((Object)(object)inventory))
				{
					inventory.onInventoryChanged += Refresh;
				}
				rendered = true;
				Refresh();
			}
		}

		private void WatchWindow()
		{
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Expected O, but got Unknown
			//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_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: 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)
			Rect val = SidebarLayout.Anchor(panel, (RectTransform)((Component)this).transform);
			if (val != lastWindow)
			{
				lastWindow = val;
				stillFrames = 0;
				if (settled)
				{
					settled = false;
					left.Hide();
					right.Hide();
				}
			}
			else if (!settled && ++stillFrames >= 3)
			{
				settled = true;
				if (rendered)
				{
					Render(lastTruncated);
				}
			}
		}

		private void WatchSlots()
		{
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			CraftingController craftingController = panel.craftingController;
			PickupIndex[] array = ((craftingController != null) ? craftingController.ingredients : null);
			int num = 17;
			if (array != null)
			{
				PickupIndex[] array2 = array;
				foreach (PickupIndex val in array2)
				{
					num = num * 31 + val.value;
				}
			}
			if (num != lastSlots)
			{
				lastSlots = num;
				if (rendered && settled)
				{
					Render(lastTruncated);
				}
			}
		}

		private void FillSlots(CraftStep step)
		{
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			if (!SlotFiller.Fill(panel.craftingController, ((Component)this).GetComponent<PickupPickerPanel>(), step) && RecipeHelperPlugin.Settings.DebugLogging.Value)
			{
				RecipeHelperPlugin.Log.LogInfo((object)("Sidebar: the dialog doesn't offer every ingredient of " + Ui.Name(step.Result) + "; slots left as they were."));
			}
		}

		private void OnDestroy()
		{
			if (Object.op_Implicit((Object)(object)inventory))
			{
				inventory.onInventoryChanged -= Refresh;
			}
		}

		private void Refresh()
		{
			PluginConfig settings = RecipeHelperPlugin.Settings;
			RecipePlanner planner = RecipeBook.Planner;
			snapshot = (settings.DebugAlwaysShow.Value ? EverythingSnapshot() : InventorySnapshot.FromInventory(inventory));
			int maxSteps = (settings.DebugAlwaysShow.Value ? 1 : settings.MaxChainSteps.Value);
			Plans = planner.Plan(snapshot, maxSteps, 20000);
			if (planner.HitBudget && settings.DebugLogging.Value)
			{
				RecipeHelperPlugin.Log.LogInfo((object)"Recipe search stopped at the state budget; longer chains may be missing.");
			}
			Render(planner.HitBudget);
		}

		private static InventorySnapshot EverythingSnapshot()
		{
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			Dictionary<PickupIndex, int> dictionary = new Dictionary<PickupIndex, int>();
			foreach (PickupDef allPickup in PickupCatalog.allPickups)
			{
				dictionary[allPickup.pickupIndex] = 2;
			}
			return new InventorySnapshot(dictionary);
		}

		private void Render(bool truncatedSearch)
		{
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: Expected O, but got Unknown
			lastTruncated = truncatedSearch;
			if (!settled)
			{
				return;
			}
			SidebarLayout sidebarLayout = SidebarLayout.Measure((RectTransform)((Component)this).transform, panel);
			if (RecipeHelperPlugin.Settings.DebugLogging.Value)
			{
				RecipeHelperPlugin.Log.LogInfo((object)string.Format("Sidebar: {0} results, inventory={1}; {2}; screen {3}x{4}", Plans.Count, Object.op_Implicit((Object)(object)inventory) ? "yes" : "none", sidebarLayout, Screen.width, Screen.height));
			}
			left.Place(sidebarLayout.LeftX, sidebarLayout.CenterY, sidebarLayout.LeftWidth);
			right.Place(sidebarLayout.RightX, sidebarLayout.CenterY, sidebarLayout.RightWidth);
			if (Plans.Count == 0)
			{
				left.Show("Nothing to craft");
				right.Hide();
				return;
			}
			List<SidebarBlock> blocks = ListView.Blocks(Plans, snapshot, (CraftStep step) => SlotFiller.Holds(panel.craftingController, step), FillSlots);
			Flow(blocks, (!(sidebarLayout.RightWidth > 0f)) ? new SidebarColumn[1] { left } : new SidebarColumn[2] { left, right }, sidebarLayout.Height);
			if (sidebarLayout.RightWidth <= 0f)
			{
				right.Hide();
			}
		}

		private void Flow(List<SidebarBlock> blocks, SidebarColumn[] columns, float maxHeight)
		{
			int num = 0;
			columns[0].Show("You can craft");
			for (int i = 1; i < columns.Length; i++)
			{
				columns[i].Hide();
			}
			string text = null;
			int num2 = 0;
			int num3 = 0;
			foreach (SidebarBlock block in blocks)
			{
				num3 += block.Results;
			}
			for (int j = 0; j < blocks.Count; j++)
			{
				SidebarBlock sidebarBlock = blocks[j];
				SidebarColumn sidebarColumn = columns[num];
				GameObject item = ((sidebarBlock.Group != null && sidebarBlock.Group != text) ? sidebarColumn.AddLabel(sidebarBlock.Group) : null);
				GameObject item2 = sidebarColumn.Add(sidebarBlock);
				if (sidebarColumn.Height() <= maxHeight || sidebarColumn.Count <= 2)
				{
					text = sidebarBlock.Group;
					num2 += sidebarBlock.Results;
					continue;
				}
				sidebarColumn.Remove(item2);
				sidebarColumn.Remove(item);
				if (num + 1 >= columns.Length)
				{
					break;
				}
				num++;
				columns[num].Show("You can craft (continued)");
				text = null;
				j--;
			}
			if (num2 < num3)
			{
				columns[num].AddText("and " + (num3 - num2) + " more");
			}
			if (lastTruncated)
			{
				columns[num].AddText("Longer chains not searched.");
			}
		}
	}
	internal static class RecipePlannerLimits
	{
		public const int StateBudget = 20000;
	}
	internal static class RiskOfOptionsCompat
	{
		public const string GUID = "com.rune580.riskofoptions";

		private const string IconResource = "RecipeHelper.icon.png";

		public static bool Enabled => Chainloader.PluginInfos.ContainsKey("com.rune580.riskofoptions");

		[MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.NoOptimization)]
		public static void Register(PluginConfig settings)
		{
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Expected O, but got Unknown
			//IL_0034: 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_0040: Unknown result type (might be due to invalid IL or missing references)
			//IL_004c: Expected O, but got Unknown
			//IL_0047: Unknown result type (might be due to invalid IL or missing references)
			//IL_0051: Expected O, but got Unknown
			//IL_0057: Unknown result type (might be due to invalid IL or missing references)
			//IL_0061: Expected O, but got Unknown
			//IL_0067: Unknown result type (might be due to invalid IL or missing references)
			//IL_0071: Expected O, but got Unknown
			//IL_0077: Unknown result type (might be due to invalid IL or missing references)
			//IL_0081: Expected O, but got Unknown
			ModSettingsManager.SetModDescription("Shows what you can craft at the Wandering CHEF.");
			Sprite val = LoadIcon();
			if (Object.op_Implicit((Object)(object)val))
			{
				ModSettingsManager.SetModIcon(val);
			}
			ModSettingsManager.AddOption((BaseOption)new CheckBoxOption(settings.Enabled));
			ModSettingsManager.AddOption((BaseOption)new IntSliderOption(settings.MaxChainSteps, new IntSliderConfig
			{
				min = 1,
				max = 5
			}));
			ModSettingsManager.AddOption((BaseOption)new CheckBoxOption(settings.DebugLogging));
			ModSettingsManager.AddOption((BaseOption)new CheckBoxOption(settings.DebugAlwaysShow));
			ModSettingsManager.AddOption((BaseOption)new KeyBindOption(settings.DumpKey));
		}

		private static Sprite LoadIcon()
		{
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: Expected O, but got Unknown
			//IL_0063: Unknown result type (might be due to invalid IL or missing references)
			//IL_0072: Unknown result type (might be due to invalid IL or missing references)
			using Stream stream = typeof(RiskOfOptionsCompat).Assembly.GetManifestResourceStream("RecipeHelper.icon.png");
			if (stream == null)
			{
				return null;
			}
			using MemoryStream memoryStream = new MemoryStream();
			stream.CopyTo(memoryStream);
			Texture2D val = new Texture2D(2, 2, (TextureFormat)4, false);
			if (!ImageConversion.LoadImage(val, memoryStream.ToArray()))
			{
				return null;
			}
			return Sprite.Create(val, new Rect(0f, 0f, (float)((Texture)val).width, (float)((Texture)val).height), new Vector2(0.5f, 0.5f));
		}
	}
	internal sealed class SidebarBlock
	{
		public string Group;

		public int Results;

		public Action<RectTransform, float> Build;
	}
	internal sealed class SidebarColumn
	{
		private const int Padding = 12;

		private const float Spacing = 10f;

		private const float HeaderFontSize = 24f;

		private const float LabelFontSize = 13f;

		private static readonly Color BackgroundColor = new Color(0f, 0f, 0f, 0.62f);

		public readonly GameObject Root;

		public readonly RectTransform Rect;

		private readonly TextMeshProUGUI header;

		private readonly List<GameObject> content = new List<GameObject>();

		public float InnerWidth => Rect.sizeDelta.x - 24f;

		public int Count => content.Count;

		public SidebarColumn(Transform parent, string name)
		{
			//IL_0053: 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)
			Rect = Ui.Stack(parent, name, 10f, (TextAnchor)0);
			Root = ((Component)Rect).gameObject;
			((Transform)Rect).SetAsLastSibling();
			Ui.Pad(Rect, 12);
			Ui.Background(Rect, BackgroundColor);
			Root.AddComponent<ContentSizeFitter>().verticalFit = (FitMode)2;
			header = Ui.Text((Transform)(object)Rect, "", 24f, Color.white);
		}

		public void Place(float x, float y, float width)
		{
			//IL_0017: 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_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0050: Unknown result type (might be due to invalid IL or missing references)
			//IL_0067: Unknown result type (might be due to invalid IL or missing references)
			//IL_0071: Unknown result type (might be due to invalid IL or missing references)
			RectTransform rect = Rect;
			Vector2 anchorMin = (Rect.anchorMax = ((RectTransform)((Transform)Rect).parent).pivot);
			rect.anchorMin = anchorMin;
			Rect.pivot = new Vector2(0f, 0.5f);
			Rect.anchoredPosition = new Vector2(x, y);
			Rect.sizeDelta = new Vector2(width, Rect.sizeDelta.y);
		}

		public void Show(string title)
		{
			Clear();
			Root.SetActive(true);
			((TMP_Text)header).text = title;
		}

		public void Hide()
		{
			Clear();
			Root.SetActive(false);
		}

		public GameObject AddLabel(string text)
		{
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			GameObject gameObject = ((Component)Ui.Text((Transform)(object)Rect, text, 13f, Ui.Muted)).gameObject;
			content.Add(gameObject);
			return gameObject;
		}

		public GameObject AddText(string text)
		{
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			GameObject gameObject = ((Component)Ui.Text((Transform)(object)Rect, text, 13f, Ui.Body)).gameObject;
			content.Add(gameObject);
			return gameObject;
		}

		public GameObject Add(SidebarBlock block)
		{
			block.Build(Rect, InnerWidth);
			GameObject gameObject = ((Component)((Transform)Rect).GetChild(((Transform)Rect).childCount - 1)).gameObject;
			content.Add(gameObject);
			return gameObject;
		}

		public void Remove(GameObject item)
		{
			if (Object.op_Implicit((Object)(object)item))
			{
				content.Remove(item);
				item.SetActive(false);
				Object.Destroy((Object)(object)item);
			}
		}

		public float Height()
		{
			LayoutRebuilder.ForceRebuildLayoutImmediate(Rect);
			return LayoutUtility.GetPreferredHeight(Rect);
		}

		private void Clear()
		{
			GameObject[] array = content.ToArray();
			foreach (GameObject item in array)
			{
				Remove(item);
			}
		}
	}
	internal struct SidebarLayout
	{
		private const float Margin = 12f;

		private const float MinWidth = 160f;

		private const float FallbackWidth = 360f;

		public float LeftX;

		public float LeftWidth;

		public float RightX;

		public float RightWidth;

		public float CenterY;

		public float Height;

		public string WindowName;

		public string Candidates;

		public static SidebarLayout Measure(RectTransform panelRect, CraftingPanel panel)
		{
			//IL_0015: 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_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_0037: Unknown result type (might be due to invalid IL or missing references)
			//IL_0046: Unknown result type (might be due to invalid IL or missing references)
			//IL_004b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0050: Unknown result type (might be due to invalid IL or missing references)
			//IL_005b: 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_0075: Unknown result type (might be due to invalid IL or missing references)
			//IL_007b: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fa: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ff: 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_010c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0111: Unknown result type (might be due to invalid IL or missing references)
			//IL_0116: 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_013b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0157: Unknown result type (might be due to invalid IL or missing references)
			//IL_016b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0194: Unknown result type (might be due to invalid IL or missing references)
			Canvas componentInParent = ((Component)panelRect).GetComponentInParent<Canvas>();
			Camera val = ((Object.op_Implicit((Object)(object)componentInParent) && (int)componentInParent.rootCanvas.renderMode != 0) ? componentInParent.rootCanvas.worldCamera : null);
			Vector2 val2 = ToLocal(panelRect, val, Vector2.zero);
			Vector2 val3 = ToLocal(panelRect, val, new Vector2((float)Screen.width, (float)Screen.height));
			SidebarLayout result = new SidebarLayout
			{
				CenterY = (val2.y + val3.y) / 2f,
				Height = val3.y - val2.y - 24f
			};
			StringBuilder stringBuilder = (RecipeHelperPlugin.Settings.DebugLogging.Value ? new StringBuilder() : null);
			RectTransform val4 = FindWindow(panelRect, panel, val, stringBuilder);
			result.Candidates = stringBuilder?.ToString();
			if (Object.op_Implicit((Object)(object)val4))
			{
				Vector3[] array = (Vector3[])(object)new Vector3[4];
				val4.GetWorldCorners(array);
				Vector2 val5 = ToLocal(panelRect, val, RectTransformUtility.WorldToScreenPoint(val, array[0]));
				Vector2 val6 = ToLocal(panelRect, val, RectTransformUtility.WorldToScreenPoint(val, array[2]));
				result.WindowName = ((Object)val4).name;
				result.LeftX = val2.x + 12f;
				result.LeftWidth = val5.x - 12f - result.LeftX;
				result.RightX = val6.x + 12f;
				result.RightWidth = val3.x - 12f - result.RightX;
			}
			if (result.LeftWidth < 160f)
			{
				result.LeftX = val2.x + 12f;
				result.LeftWidth = 360f;
				result.RightWidth = 0f;
			}
			if (result.RightWidth < 160f)
			{
				result.RightWidth = 0f;
			}
			return result;
		}

		public static Rect Anchor(CraftingPanel panel, RectTransform panelRect)
		{
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_0042: Unknown result type (might be due to invalid IL or missing references)
			Canvas componentInParent = ((Component)panelRect).GetComponentInParent<Canvas>();
			Camera camera = ((Object.op_Implicit((Object)(object)componentInParent) && (int)componentInParent.rootCanvas.renderMode != 0) ? componentInParent.rootCanvas.worldCamera : null);
			return ScreenRect(Object.op_Implicit((Object)(object)panel.ingredientContainer) ? panel.ingredientContainer : panelRect, camera);
		}

		private static RectTransform FindWindow(RectTransform panelRect, CraftingPanel panel, Camera camera, StringBuilder trace)
		{
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_0063: 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_0088: 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_009b: Unknown result type (might be due to invalid IL or missing references)
			if (!Object.op_Implicit((Object)(object)panel.ingredientContainer) || !Object.op_Implicit((Object)(object)panel.inventoryContainer))
			{
				return null;
			}
			Rect inner = ScreenRect(panel.ingredientContainer, camera);
			Rect val = ScreenRect(panel.inventoryContainer, camera);
			RectTransform result = null;
			float num = 0f;
			Image[] componentsInChildren = ((Component)panelRect).GetComponentsInChildren<Image>();
			foreach (Image val2 in componentsInChildren)
			{
				if (!((Behaviour)val2).enabled || ((Graphic)val2).color.a <= 0f)
				{
					continue;
				}
				RectTransform rectTransform = ((Graphic)val2).rectTransform;
				Rect outer = ScreenRect(rectTransform, camera);
				if (!(((Rect)(ref outer)).width >= (float)Screen.width) && Encloses(outer, inner) && !(((Rect)(ref outer)).xMin > ((Rect)(ref val)).xMin + 1f) && !(((Rect)(ref outer)).xMax < ((Rect)(ref val)).xMax - 1f))
				{
					trace?.Append($" {((Object)rectTransform).name}={((Rect)(ref outer)).width:0}px");
					float num2 = ((Rect)(ref outer)).width * ((Rect)(ref outer)).height;
					if (num2 > num)
					{
						result = rectTransform;
						num = num2;
					}
				}
			}
			return result;
		}

		private static bool Encloses(Rect outer, Rect inner)
		{
			if (((Rect)(ref outer)).xMin <= ((Rect)(ref inner)).xMin + 1f && ((Rect)(ref outer)).xMax >= ((Rect)(ref inner)).xMax - 1f && ((Rect)(ref outer)).yMin <= ((Rect)(ref inner)).yMin + 1f)
			{
				return ((Rect)(ref outer)).yMax >= ((Rect)(ref inner)).yMax - 1f;
			}
			return false;
		}

		private static Rect ScreenRect(RectTransform rect, Camera camera)
		{
			//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_001b: 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_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			//IL_003c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0042: Unknown result type (might be due to invalid IL or missing references)
			Vector3[] array = (Vector3[])(object)new Vector3[4];
			rect.GetWorldCorners(array);
			Vector2 val = RectTransformUtility.WorldToScreenPoint(camera, array[0]);
			Vector2 val2 = RectTransformUtility.WorldToScreenPoint(camera, array[2]);
			return Rect.MinMaxRect(val.x, val.y, val2.x, val2.y);
		}

		private static Vector2 ToLocal(RectTransform rect, Camera camera, Vector2 screenPoint)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			Vector2 result = default(Vector2);
			RectTransformUtility.ScreenPointToLocalPointInRectangle(rect, screenPoint, camera, ref result);
			return result;
		}

		public override string ToString()
		{
			return string.Format("window='{0}' left x={1:0} w={2:0}, right x={3:0} w={4:0}, height={5:0}; candidates:{6}", WindowName ?? "not found", LeftX, LeftWidth, RightX, RightWidth, Height, Candidates);
		}
	}
	internal static class SlotFiller
	{
		public static bool Holds(CraftingController controller, CraftStep step)
		{
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			PickupIndex[] array = (Object.op_Implicit((Object)(object)controller) ? controller.ingredients : null);
			if (array == null || array.Length != step.Ingredients.Length)
			{
				return false;
			}
			bool[] array2 = new bool[array.Length];
			PickupIndex[] ingredients = step.Ingredients;
			foreach (PickupIndex ingredient in ingredients)
			{
				int num = Array.FindIndex(array, (PickupIndex p) => p == ingredient);
				while (num >= 0 && array2[num])
				{
					num = Array.FindIndex(array, num + 1, (PickupIndex p) => p == ingredient);
				}
				if (num < 0)
				{
					return false;
				}
				array2[num] = true;
			}
			return true;
		}

		public static bool Fill(CraftingController controller, PickupPickerPanel picker, CraftStep step)
		{
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_0049: Unknown result type (might be due to invalid IL or missing references)
			//IL_004b: 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_00a2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00aa: Unknown result type (might be due to invalid IL or missing references)
			if (!Object.op_Implicit((Object)(object)controller) || !Object.op_Implicit((Object)(object)picker) || controller.ingredients == null || controller.ingredients.Length != step.Ingredients.Length)
			{
				return false;
			}
			if (Holds(controller, step))
			{
				return true;
			}
			PickupIndex[] ingredients = step.Ingredients;
			foreach (PickupIndex pickup in ingredients)
			{
				if (ButtonIndex(picker, pickup) < 0)
				{
					return false;
				}
			}
			PickupIndex[] ingredients2 = controller.ingredients;
			for (int j = 0; j < ingredients2.Length; j++)
			{
				if (ingredients2[j] != PickupIndex.none)
				{
					controller.ClearSlot(j);
				}
			}
			ingredients = step.Ingredients;
			foreach (PickupIndex pickup2 in ingredients)
			{
				int num = ButtonIndex(picker, pickup2);
				if (num >= 0)
				{
					((PickupPickerController)controller).SubmitChoice(num);
				}
			}
			return true;
		}

		private static int ButtonIndex(PickupPickerPanel picker, PickupIndex pickup)
		{
			//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)
			Option[] pickupOptions = picker.pickupOptions;
			if (pickupOptions == null)
			{
				return -1;
			}
			for (int i = 0; i < pickupOptions.Length; i++)
			{
				if (pickupOptions[i].pickup.pickupIndex == pickup)
				{
					return i;
				}
			}
			return -1;
		}
	}
	internal sealed class SlotDetail
	{
		public PickupIndex Chosen;

		public List<PickupIndex> Alternates = new List<PickupIndex>();

		public bool MadeByEarlierStep;
	}
	internal sealed class StepDetail
	{
		public CraftStep Step;

		public SlotDetail[] Slots;

		public static List<StepDetail> Build(InventorySnapshot start, CraftPlan plan)
		{
			//IL_005c: 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_0069: 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_0072: 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_00a7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ac: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ae: 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_00ba: 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_00d5: Unknown result type (might be due to invalid IL or missing references)
			List<StepDetail> list = new List<StepDetail>();
			HashSet<PickupIndex> hashSet = new HashSet<PickupIndex>();
			InventorySnapshot inventorySnapshot = start;
			foreach (CraftStep step in plan.Steps)
			{
				StepDetail stepDetail = new StepDetail
				{
					Step = step,
					Slots = new SlotDetail[step.Ingredients.Length]
				};
				for (int i = 0; i < step.Ingredients.Length; i++)
				{
					PickupIndex val = step.Ingredients[i];
					SlotDetail slotDetail = new SlotDetail
					{
						Chosen = val,
						MadeByEarlierStep = hashSet.Contains(val)
					};
					PickupIndex[] pickups = step.Recipe.possibleIngredients[i].pickups;
					if (pickups != null)
					{
						PickupIndex[] array = pickups;
						foreach (PickupIndex val2 in array)
						{
							if (val2 != val && inventorySnapshot.Count(val2) > UsedByOtherSlots(step, i, val2))
							{
								slotDetail.Alternates.Add(val2);
							}
						}
					}
					stepDetail.Slots[i] = slotDetail;
				}
				list.Add(stepDetail);
				hashSet.Add(step.Result);
				inventorySnapshot = inventorySnapshot.Apply(step);
			}
			return list;
		}

		private static int UsedByOtherSlots(CraftStep step, int slot, PickupIndex pickup)
		{
			//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)
			int num = 0;
			for (int i = 0; i < step.Ingredients.Length; i++)
			{
				if (i != slot && step.Ingredients[i] == pickup)
				{
					num++;
				}
			}
			return num;
		}
	}
	internal static class Ui
	{
		public static readonly Color Muted = Color32.op_Implicit(new Color32((byte)143, (byte)163, (byte)199, byte.MaxValue));

		public static readonly Color Body = Color32.op_Implicit(new Color32((byte)195, (byte)199, (byte)211, byte.MaxValue));

		public static readonly Color CardBackground = new Color(1f, 1f, 1f, 0.05f);

		private static readonly Color TileBackground = Color32.op_Implicit(new Color32((byte)23, (byte)27, (byte)36, byte.MaxValue));

		private const float FrameWidth = 2f;

		private const float IconInset = 3f;

		private const float MadeFrameAlpha = 0.4f;

		public static RectTransform Rect(Transform parent, string name)
		{
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: Expected O, but got Unknown
			RectTransform val = (RectTransform)new GameObject(name, new Type[1] { typeof(RectTransform) })
			{
				layer = ((Component)parent).gameObject.layer
			}.transform;
			((Transform)val).SetParent(parent, false);
			return val;
		}

		public static RectTransform Row(Transform parent, string name, float spacing)
		{
			RectTransform obj = Rect(parent, name);
			HorizontalLayoutGroup obj2 = ((Component)obj).gameObject.AddComponent<HorizontalLayoutGroup>();
			((HorizontalOrVerticalLayoutGroup)obj2).spacing = spacing;
			((LayoutGroup)obj2).childAlignment = (TextAnchor)0;
			((HorizontalOrVerticalLayoutGroup)obj2).childControlWidth = true;
			((HorizontalOrVerticalLayoutGroup)obj2).childControlHeight = true;
			((HorizontalOrVerticalLayoutGroup)obj2).childForceExpandWidth = false;
			((HorizontalOrVerticalLayoutGroup)obj2).childForceExpandHeight = false;
			return obj;
		}

		public static RectTransform Stack(Transform parent, string name, float spacing, TextAnchor alignment = (TextAnchor)0)
		{
			//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_0031: Invalid comparison between Unknown and I4
			RectTransform obj = Rect(parent, name);
			VerticalLayoutGroup obj2 = ((Component)obj).gameObject.AddComponent<VerticalLayoutGroup>();
			((HorizontalOrVerticalLayoutGroup)obj2).spacing = spacing;
			((LayoutGroup)obj2).childAlignment = alignment;
			((HorizontalOrVerticalLayoutGroup)obj2).childControlWidth = true;
			((HorizontalOrVerticalLayoutGroup)obj2).childControlHeight = true;
			((HorizontalOrVerticalLayoutGroup)obj2).childForceExpandWidth = (int)alignment == 0;
			((HorizontalOrVerticalLayoutGroup)obj2).childForceExpandHeight = false;
			return obj;
		}

		public static void Pad(RectTransform rect, int padding)
		{
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0014: Expected O, but got Unknown
			((LayoutGroup)((Component)rect).GetComponent<HorizontalOrVerticalLayoutGroup>()).padding = new RectOffset(padding, padding, padding, padding);
		}

		public static void Background(RectTransform rect, Color color)
		{
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			Image obj = ((Component)rect).gameObject.AddComponent<Image>();
			((Graphic)obj).color = color;
			((Graphic)obj).raycastTarget = false;
		}

		public static void Size(RectTransform rect, float width, float height)
		{
			LayoutElement obj = Element(rect);
			float minWidth = (obj.preferredWidth = width);
			obj.minWidth = minWidth;
			minWidth = (obj.preferredHeight = height);
			obj.minHeight = minWidth;
			minWidth = (obj.flexibleHeight = 0f);
			obj.flexibleWidth = minWidth;
		}

		public static void Flexible(RectTransform rect)
		{
			Element(rect).flexibleWidth = 1f;
		}

		private static LayoutElement Element(RectTransform rect)
		{
			LayoutElement component = ((Component)rect).GetComponent<LayoutElement>();
			if (!Object.op_Implicit((Object)(object)component))
			{
				return ((Component)rect).gameObject.AddComponent<LayoutElement>();
			}
			return component;
		}

		public static TextMeshProUGUI Text(Transform parent, string text, float fontSize, Color color)
		{
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			HGTextMeshProUGUI obj = ((Component)Rect(parent, "Text")).gameObject.AddComponent<HGTextMeshProUGUI>();
			((TMP_Text)obj).richText = true;
			((TMP_Text)obj).enableWordWrapping = true;
			((TMP_Text)obj).alignment = (TextAlignmentOptions)257;
			((TMP_Text)obj).fontSize = fontSize;
			((Graphic)obj).color = color;
			((Graphic)obj).raycastTarget = false;
			((TMP_Text)obj).text = text;
			return (TextMeshProUGUI)(object)obj;
		}

		public static void Glyph(Transform parent, string glyph, float tileSize)
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			TextMeshProUGUI obj = Text(parent, glyph, 16f, Muted);
			((TMP_Text)obj).alignment = (TextAlignmentOptions)514;
			((TMP_Text)obj).enableWordWrapping = false;
			Size(((TMP_Text)obj).rectTransform, 14f, tileSize);
		}

		public static RectTransform Tile(Transform parent, PickupIndex pickup, float size, bool madeByEarlierStep = false)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: 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_0036: Unknown result type (might be due to invalid IL or missing references)
			//IL_004e: Unknown result type (might be due to invalid IL or missing references)
			//IL_007b: Unknown result type (might be due to invalid IL or missing references)
			PickupDef pickupDef = PickupCatalog.GetPickupDef(pickup);
			RectTransform val = Rect(parent, "Tile");
			Size(val, size, size);
			Image obj = ((Component)val).gameObject.AddComponent<Image>();
			Color color = pickupDef?.baseColor ?? Muted;
			color.a = (madeByEarlierStep ? 0.4f : 1f);
			((Graphic)obj).color = color;
			((Graphic)obj).raycastTarget = false;
			RectTransform obj2 = Rect((Transform)(object)val, "Background");
			Fill(obj2, 2f);
			Image obj3 = ((Component)obj2).gameObject.AddComponent<Image>();
			((Graphic)obj3).color = TileBackground;
			((Graphic)obj3).raycastTarget = false;
			if (pickupDef != null)
			{
				RectTransform obj4 = Rect((Transform)(object)val, "Icon");
				Fill(obj4, 3f);
				Image val2 = ((Component)obj4).gameObject.AddComponent<Image>();
				val2.preserveAspect = true;
				((Graphic)val2).raycastTarget = false;
				((Behaviour)val2).enabled = false;
				AsyncImage obj5 = ((Component)obj4).gameObject.AddComponent<AsyncImage>();
				((AsyncViewable<Sprite, Image>)(object)obj5).renderer = val2;
				obj5.SetAssetOrDirectReference((AsyncIconProvider)(object)pickupDef);
				((Behaviour)val2).enabled = true;
			}
			return val;
		}

		public static string Name(PickupIndex pickup)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			PickupDef pickupDef = PickupCatalog.GetPickupDef(pickup);
			if (pickupDef == null)
			{
				return "?";
			}
			return Language.GetString(pickupDef.nameToken);
		}

		public static Color TierColor(PickupIndex pickup)
		{
			//IL_0000: 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_000a: Unknown result type (might be due to invalid IL or missing references)
			return PickupCatalog.GetPickupDef(pickup)?.baseColor ?? Muted;
		}

		public static void Fill(RectTransform rect, float inset)
		{
			//IL_0001: 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_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			rect.anchorMin = Vector2.zero;
			rect.anchorMax = Vector2.one;
			rect.offsetMin = new Vector2(inset, inset);
			rect.offsetMax = new Vector2(0f - inset, 0f - inset);
		}
	}
	internal static class PluginVersionInfo
	{
		public const string Version = "1.0.0";
	}
}
namespace System.Runtime.CompilerServices
{
	[AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)]
	internal sealed class IgnoresAccessChecksToAttribute : Attribute
	{
		public IgnoresAccessChecksToAttribute(string assemblyName)
		{
		}
	}
}