Decompiled source of CraftIndex v0.3.1

CraftIndex.dll

Decompiled 6 hours ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Text;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using InventoryUX.Core;
using InventoryUX.Runtime;
using Microsoft.CodeAnalysis;
using TMPro;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[assembly: AssemblyCompany("CraftIndex")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("0.3.1.0")]
[assembly: AssemblyInformationalVersion("0.3.1+3a9829310d8cc8c9761d7177112baaee7c67cc84")]
[assembly: AssemblyProduct("CraftIndex")]
[assembly: AssemblyTitle("CraftIndex")]
[assembly: AssemblyVersion("0.3.1.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableAttribute : Attribute
	{
		public readonly byte[] NullableFlags;

		public NullableAttribute(byte P_0)
		{
			NullableFlags = new byte[1] { P_0 };
		}

		public NullableAttribute(byte[] P_0)
		{
			NullableFlags = P_0;
		}
	}
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableContextAttribute : Attribute
	{
		public readonly byte Flag;

		public NullableContextAttribute(byte P_0)
		{
			Flag = P_0;
		}
	}
	[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 InventoryUX
{
	[BepInPlugin("com.inventoryux.valheim", "CraftIndex", "0.3.1")]
	public sealed class Plugin : BaseUnityPlugin
	{
		internal const string PluginGuid = "com.inventoryux.valheim";

		internal const string PluginName = "CraftIndex";

		internal const string PluginVersion = "0.3.1";

		private Harmony? _harmony;

		internal static ManualLogSource LogInstance { get; private set; }

		internal static Plugin Instance { get; private set; }

		private void Awake()
		{
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: Expected O, but got Unknown
			Instance = this;
			LogInstance = ((BaseUnityPlugin)this).Logger;
			ModConfig.Bind(((BaseUnityPlugin)this).Config);
			_harmony = new Harmony("com.inventoryux.valheim");
			_harmony.PatchAll(typeof(Plugin).Assembly);
			((BaseUnityPlugin)this).Logger.LogInfo((object)"CraftIndex 0.3.1 loaded. Undiscovered content is never rendered.");
		}

		private void OnDestroy()
		{
			Cleanup("Hammer UI", HammerGroupDecorations.Shutdown);
			Cleanup("Hammer sizing", HammerGridSizer.Restore);
			Cleanup("Hammer caches", HammerOrganizer.Reset);
			Cleanup("recipe UI", RecipeOrganizer.Shutdown);
			Cleanup("food cache", FoodStatsResolver.Reset);
			Harmony? harmony = _harmony;
			if (harmony != null)
			{
				harmony.UnpatchSelf();
			}
		}

		private static void Cleanup(string name, Action action)
		{
			try
			{
				action();
			}
			catch (Exception arg)
			{
				LogInstance.LogWarning((object)$"CraftIndex could not fully release {name} during shutdown: {arg}");
			}
		}
	}
}
namespace InventoryUX.Runtime
{
	internal enum CraftingSection
	{
		Workbench,
		Forge,
		Cooking,
		Advanced,
		Processing,
		Utility
	}
	internal readonly struct CraftingPieceLayout
	{
		internal CraftingSection Section { get; }

		internal int SortOrder { get; }

		internal int Subgroup { get; }

		internal bool IsPrimaryStation { get; }

		internal CraftingPieceLayout(CraftingSection section, int sortOrder, int subgroup, bool isPrimaryStation = false)
		{
			Section = section;
			SortOrder = sortOrder;
			Subgroup = subgroup;
			IsPrimaryStation = isPrimaryStation;
		}
	}
	internal static class CraftingLayoutMetadata
	{
		private readonly struct PieceRule
		{
			internal CraftingPieceLayout Layout { get; }

			private string[] Markers { get; }

			internal PieceRule(CraftingPieceLayout layout, string[] markers)
			{
				Layout = layout;
				Markers = markers;
			}

			internal bool Matches(string id)
			{
				for (int i = 0; i < Markers.Length; i++)
				{
					if (id.Contains(Markers[i]))
					{
						return true;
					}
				}
				return false;
			}
		}

		private static readonly PieceRule[] Rules = new PieceRule[46]
		{
			Rule(CraftingSection.Workbench, 110, 0, "choppingblock"),
			Rule(CraftingSection.Workbench, 120, 0, "tanningrack"),
			Rule(CraftingSection.Workbench, 130, 0, "adze"),
			Rule(CraftingSection.Workbench, 140, 0, "toolshelf"),
			Rule(CraftingSection.Workbench, 100, 0, true, "workbench"),
			Rule(CraftingSection.Forge, 210, 0, "forgebellows", "bellows"),
			Rule(CraftingSection.Forge, 220, 0, "anvils"),
			Rule(CraftingSection.Forge, 230, 0, "grindingwheel"),
			Rule(CraftingSection.Forge, 240, 0, "smithsanvil"),
			Rule(CraftingSection.Forge, 250, 0, "forgecooler"),
			Rule(CraftingSection.Forge, 260, 0, "forgetoolrack", "toolrack"),
			Rule(CraftingSection.Forge, 100, 0, true, "forge"),
			Rule(CraftingSection.Cooking, 110, 0, "spicerack"),
			Rule(CraftingSection.Cooking, 120, 0, "butcherstable", "butchertable"),
			Rule(CraftingSection.Cooking, 130, 0, "potsandpans"),
			Rule(CraftingSection.Cooking, 140, 0, "mortarandpestle", "mortar"),
			Rule(CraftingSection.Cooking, 150, 0, "rollingpin", "cuttingboard"),
			Rule(CraftingSection.Cooking, 400, 3, true, "meadketill", "meadkettle", "ketill", "kettle"),
			Rule(CraftingSection.Cooking, 410, 3, "fermenter", "fermentationbarrel"),
			Rule(CraftingSection.Cooking, 100, 0, true, "cauldron"),
			Rule(CraftingSection.Cooking, 210, 1, "ironcookingstation", "cookingstationiron"),
			Rule(CraftingSection.Cooking, 200, 1, true, "cookingstation"),
			Rule(CraftingSection.Cooking, 300, 2, true, "foodpreparation", "foodprep", "preptable"),
			Rule(CraftingSection.Cooking, 310, 2, "stoneoven", "oven"),
			Rule(CraftingSection.Advanced, 110, 0, "artisanpress"),
			Rule(CraftingSection.Advanced, 100, 0, true, "artisantable", "artisan"),
			Rule(CraftingSection.Advanced, 210, 1, "blackforgecooler"),
			Rule(CraftingSection.Advanced, 200, 1, true, "blackforge"),
			Rule(CraftingSection.Advanced, 300, 2, "gemcutter"),
			Rule(CraftingSection.Advanced, 310, 2, "metalcutter"),
			Rule(CraftingSection.Advanced, 320, 2, "vice", "vise"),
			Rule(CraftingSection.Advanced, 410, 3, "unfadingcandles"),
			Rule(CraftingSection.Advanced, 420, 3, "featherywreath", "wreath"),
			Rule(CraftingSection.Advanced, 430, 3, "runetable"),
			Rule(CraftingSection.Advanced, 400, 3, true, "galdrtable", "galdr"),
			Rule(CraftingSection.Processing, 100, 0, "charcoalkiln", "kiln"),
			Rule(CraftingSection.Processing, 110, 0, "smelter"),
			Rule(CraftingSection.Processing, 120, 0, "blastfurnace"),
			Rule(CraftingSection.Processing, 130, 0, "windmill"),
			Rule(CraftingSection.Processing, 140, 0, "spinningwheel"),
			Rule(CraftingSection.Processing, 150, 0, "sapextractor", "sapcollector"),
			Rule(CraftingSection.Processing, 160, 0, "obliterator", "incinerator"),
			Rule(CraftingSection.Processing, 170, 0, "eitrrefinery", "refineryeitr"),
			Rule(CraftingSection.Utility, 100, 0, "stonecutter"),
			Rule(CraftingSection.Utility, 110, 0, "beehive"),
			Rule(CraftingSection.Utility, 120, 0, "wispfountain")
		};

		internal static CraftingPieceLayout Resolve(Piece piece)
		{
			string text = Normalize(HammerOrganizer.GetLabel(piece, (PieceCategory)1));
			string text2 = ((Localization.instance != null) ? Localization.instance.Localize(piece.m_name) : piece.m_name);
			string text3 = Normalize(text + " " + ((Object)((Component)piece).gameObject).name + " " + piece.m_name + " " + text2);
			if (ContainsAny(text3, "eitrrefinery", "refineryeitr"))
			{
				return ResolveWithin(text3, CraftingSection.Processing, 170, 0);
			}
			if (text.Contains("workbench"))
			{
				return ResolveWithin(text3, CraftingSection.Workbench, 900, 1);
			}
			if (text.Contains("artisan"))
			{
				return ResolveWithin(text3, CraftingSection.Advanced, 900, 0);
			}
			if (text.Contains("blackforge"))
			{
				return ResolveWithin(text3, CraftingSection.Advanced, 900, 1);
			}
			if (text.Contains("galdr"))
			{
				return ResolveWithin(text3, CraftingSection.Advanced, 900, 3);
			}
			if (text.Contains("forge"))
			{
				return ResolveWithin(text3, CraftingSection.Forge, 900, 1);
			}
			if (ContainsAny(text, "cauldron", "foodpreparation", "foodprep", "preptable", "cooking"))
			{
				return ResolveWithin(text3, CraftingSection.Cooking, 900, 3);
			}
			if (ContainsAny(text, "mead", "ketill", "kettle", "brewing"))
			{
				return ResolveWithin(text3, CraftingSection.Cooking, 900, 3);
			}
			for (int i = 0; i < Rules.Length; i++)
			{
				if (Rules[i].Matches(text3))
				{
					return Rules[i].Layout;
				}
			}
			return new CraftingPieceLayout(CraftingSection.Utility, 900, 9);
		}

		internal static string Label(CraftingSection section)
		{
			return section switch
			{
				CraftingSection.Workbench => "WORKBENCH", 
				CraftingSection.Forge => "FORGE", 
				CraftingSection.Cooking => "COOKING", 
				CraftingSection.Advanced => "ADVANCED", 
				CraftingSection.Processing => "PROCESSING", 
				_ => "UTILITY", 
			};
		}

		internal static bool IsRepair(Piece piece)
		{
			if (piece.m_repairPiece)
			{
				return true;
			}
			string text = Normalize(((Object)((Component)piece).gameObject).name);
			string text2 = Normalize(piece.m_name);
			switch (text)
			{
			default:
				if (!(text2 == "repair"))
				{
					return text2 == "piecerepair";
				}
				break;
			case "repair":
			case "piecerepair":
			case "hammerrepair":
			case "repairpiece":
				break;
			}
			return true;
		}

		private static CraftingPieceLayout ResolveWithin(string id, CraftingSection section, int fallbackOrder, int fallbackSubgroup)
		{
			for (int i = 0; i < Rules.Length; i++)
			{
				PieceRule pieceRule = Rules[i];
				if (pieceRule.Layout.Section == section && pieceRule.Matches(id))
				{
					return pieceRule.Layout;
				}
			}
			return new CraftingPieceLayout(section, fallbackOrder, fallbackSubgroup);
		}

		private static PieceRule Rule(CraftingSection section, int order, int subgroup, params string[] markers)
		{
			return new PieceRule(new CraftingPieceLayout(section, order, subgroup), markers);
		}

		private static PieceRule Rule(CraftingSection section, int order, int subgroup, bool primary, params string[] markers)
		{
			return new PieceRule(new CraftingPieceLayout(section, order, subgroup, primary), markers);
		}

		private static bool ContainsAny(string value, params string[] markers)
		{
			for (int i = 0; i < markers.Length; i++)
			{
				if (value.Contains(markers[i]))
				{
					return true;
				}
			}
			return false;
		}

		private static string Normalize(string? value)
		{
			if (string.IsNullOrEmpty(value))
			{
				return string.Empty;
			}
			char[] array = new char[value.Length];
			int length = 0;
			foreach (char c in value)
			{
				if (char.IsLetterOrDigit(c))
				{
					array[length++] = char.ToLower(c, CultureInfo.InvariantCulture);
				}
			}
			return new string(array, 0, length);
		}
	}
	internal static class DataInventoryWriter
	{
		private static bool _written;

		internal static void TryWriteOnce()
		{
			if (_written || (Object)(object)ObjectDB.instance == (Object)null || (Object)(object)ZNetScene.instance == (Object)null)
			{
				return;
			}
			try
			{
				string text = Path.Combine(Paths.ConfigPath, "CraftIndex");
				Directory.CreateDirectory(text);
				string text2 = Path.Combine(text, "loaded-data-inventory.csv");
				File.WriteAllText(text2, BuildCsv(), new UTF8Encoding(encoderShouldEmitUTF8Identifier: true));
				_written = true;
				Plugin.LogInstance.LogInfo((object)("Wrote the loaded piece/recipe inventory to " + text2));
			}
			catch (Exception arg)
			{
				_written = true;
				Plugin.LogInstance.LogError((object)$"Could not write the data inventory: {arg}");
			}
		}

		private static string BuildCsv()
		{
			StringBuilder stringBuilder = new StringBuilder();
			WriteRow(stringBuilder, "ContentType", "PrefabID", "DisplayName", "KnownUnlockMechanism", "HammerCategory", "PieceType", "CraftingStation", "StationExtensionParent", "StationLevelContribution", "ItemType", "WeaponFamily", "ArmorType", "Recipe", "Ingredients", "RequiredStation", "RequiredStationLevel", "FoodHP", "FoodStamina", "FoodEitr", "FoodDuration", "FoodRegen", "ProposedGroup", "ProposedBiome", "ProposedSortOrder");
			WritePieces(stringBuilder);
			WriteRecipes(stringBuilder);
			return stringBuilder.ToString();
		}

		private static void WritePieces(StringBuilder output)
		{
			//IL_006b: Unknown result type (might be due to invalid IL or missing references)
			HashSet<string> hashSet = new HashSet<string>(StringComparer.Ordinal);
			List<GameObject> prefabs = ZNetScene.instance.m_prefabs;
			for (int i = 0; i < prefabs.Count; i++)
			{
				GameObject val = prefabs[i];
				if (!((Object)(object)val == (Object)null))
				{
					Piece component = val.GetComponent<Piece>();
					if (!((Object)(object)component == (Object)null) && hashSet.Add(((Object)val).name))
					{
						CraftingStation component2 = val.GetComponent<CraftingStation>();
						StationExtension component3 = val.GetComponent<StationExtension>();
						PieceGroup pieceGroup = HammerOrganizer.Classify(component, component.m_category);
						string text = (((Object)(object)component2 != (Object)null) ? "Crafting station" : (((Object)(object)component3 != (Object)null) ? "Station extension" : "Build piece"));
						WriteRow(output, "Piece", ((Object)val).name, Localize(component.m_name), "Piece.m_name in Player.m_knownRecipes", ((object)Unsafe.As<PieceCategory, PieceCategory>(ref component.m_category)/*cast due to .constrained prefix*/).ToString(), text, ((Object)(object)component.m_craftingStation != (Object)null) ? Localize(component.m_craftingStation.m_name) : (((Object)(object)component2 != (Object)null) ? Localize(component2.m_name) : string.Empty), ((Object)(object)component3 != (Object)null && (Object)(object)component3.m_craftingStation != (Object)null) ? Localize(component3.m_craftingStation.m_name) : string.Empty, ((Object)(object)component3 != (Object)null) ? "Native unique attached extension (+1)" : string.Empty, string.Empty, string.Empty, string.Empty, string.Empty, FormatPieceIngredients(component), string.Empty, string.Empty, string.Empty, string.Empty, string.Empty, string.Empty, string.Empty, pieceGroup.Label, string.Empty, $"{pieceGroup.Order}:{pieceGroup.Suborder}");
					}
				}
			}
		}

		private static void WriteRecipes(StringBuilder output)
		{
			//IL_0131: Unknown result type (might be due to invalid IL or missing references)
			List<Recipe> recipes = ObjectDB.instance.m_recipes;
			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))
				{
					SharedData shared = val.m_item.m_itemData.m_shared;
					RecipeFacts recipeFacts = ToFacts(val, i);
					RecipeGroup recipeGroup = (recipeFacts.IsFeast ? new RecipeGroup("Feasts", 4) : (recipeFacts.IsFood ? FoodClassifier.ToGroup(FoodClassifier.Classify(recipeFacts.Health, recipeFacts.Stamina, recipeFacts.Eitr)) : RecipeClassifier.GetTypeGroup(recipeFacts)));
					ProgressionBiome biome = BiomeClassifier.Classify(recipeFacts.Id, recipeFacts.IngredientIds);
					WriteRow(output, "Recipe", recipeFacts.Id, recipeFacts.DisplayName, "Player.GetAvailableRecipes / Player.IsRecipeKnown", string.Empty, string.Empty, string.Empty, string.Empty, string.Empty, ((object)Unsafe.As<ItemType, ItemType>(ref shared.m_itemType)/*cast due to .constrained prefix*/).ToString(), ((object)Unsafe.As<SkillType, SkillType>(ref shared.m_skillType)/*cast due to .constrained prefix*/).ToString(), ArmorType(shared.m_itemType), ((Object)val).name, FormatRecipeIngredients(val), ((Object)(object)val.m_craftingStation != (Object)null) ? Localize(val.m_craftingStation.m_name) : string.Empty, val.m_minStationLevel.ToString(CultureInfo.InvariantCulture), shared.m_food.ToString(CultureInfo.InvariantCulture), shared.m_foodStamina.ToString(CultureInfo.InvariantCulture), shared.m_foodEitr.ToString(CultureInfo.InvariantCulture), shared.m_foodBurnTime.ToString(CultureInfo.InvariantCulture), shared.m_foodRegen.ToString(CultureInfo.InvariantCulture), recipeGroup.Label, biome.ToString(), $"{BiomeClassifier.ToGroup(biome).Order}:{recipeGroup.Order}");
				}
			}
		}

		private static RecipeFacts ToFacts(Recipe recipe, int originalIndex)
		{
			SharedData shared = recipe.m_item.m_itemData.m_shared;
			List<string> list = new List<string>();
			if (recipe.m_resources != null)
			{
				for (int i = 0; i < recipe.m_resources.Length; i++)
				{
					ItemDrop val = recipe.m_resources[i]?.m_resItem;
					if (!((Object)(object)val == (Object)null))
					{
						list.Add(((Object)((Component)val).gameObject).name);
						list.Add(val.m_itemData.m_shared.m_name);
					}
				}
			}
			ResolvedFoodStats resolvedFoodStats = FoodStatsResolver.Resolve(recipe.m_item);
			float health = (resolvedFoodStats.Resolved ? resolvedFoodStats.Health : shared.m_food);
			float stamina = (resolvedFoodStats.Resolved ? resolvedFoodStats.Stamina : shared.m_foodStamina);
			float eitr = (resolvedFoodStats.Resolved ? resolvedFoodStats.Eitr : shared.m_foodEitr);
			return new RecipeFacts(((Object)((Component)recipe.m_item).gameObject).name, Localize(shared.m_name), ((object)Unsafe.As<ItemType, ItemType>(ref shared.m_itemType)/*cast due to .constrained prefix*/).ToString(), ((object)Unsafe.As<SkillType, SkillType>(ref shared.m_skillType)/*cast due to .constrained prefix*/).ToString(), list, health, stamina, eitr, originalIndex, resolvedFoodStats.IsFeast);
		}

		private static string FormatPieceIngredients(Piece piece)
		{
			if (piece.m_resources == null)
			{
				return string.Empty;
			}
			List<string> list = new List<string>();
			for (int i = 0; i < piece.m_resources.Length; i++)
			{
				Requirement val = piece.m_resources[i];
				if ((Object)(object)val?.m_resItem != (Object)null)
				{
					list.Add($"{Localize(val.m_resItem.m_itemData.m_shared.m_name)} x{val.m_amount}");
				}
			}
			return string.Join("; ", list);
		}

		private static string FormatRecipeIngredients(Recipe recipe)
		{
			if (recipe.m_resources == null)
			{
				return string.Empty;
			}
			List<string> list = new List<string>();
			for (int i = 0; i < recipe.m_resources.Length; i++)
			{
				Requirement val = recipe.m_resources[i];
				if ((Object)(object)val?.m_resItem != (Object)null)
				{
					list.Add($"{Localize(val.m_resItem.m_itemData.m_shared.m_name)} x{val.m_amount}");
				}
			}
			return string.Join("; ", list);
		}

		private static string ArmorType(ItemType itemType)
		{
			//IL_0000: 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_0024: Expected I4, but got Unknown
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: Invalid comparison between Unknown and I4
			switch (itemType - 6)
			{
			default:
				if ((int)itemType != 17)
				{
					break;
				}
				return "Shoulder";
			case 0:
				return "Helmet";
			case 1:
				return "Chest";
			case 5:
				return "Legs";
			case 6:
				return "Hands";
			case 2:
			case 3:
			case 4:
				break;
			}
			return string.Empty;
		}

		private static string Localize(string value)
		{
			if (Localization.instance == null)
			{
				return value;
			}
			return Localization.instance.Localize(value);
		}

		private static void WriteRow(StringBuilder output, params string[] values)
		{
			for (int i = 0; i < values.Length; i++)
			{
				if (i > 0)
				{
					output.Append(',');
				}
				output.Append(Escape(values[i]));
			}
			output.AppendLine();
		}

		private static string Escape(string? value)
		{
			value = value ?? string.Empty;
			if (value.IndexOfAny(new char[4] { ',', '"', '\r', '\n' }) < 0)
			{
				return value;
			}
			return "\"" + value.Replace("\"", "\"\"") + "\"";
		}
	}
	internal sealed class FailureCircuitBreaker
	{
		private readonly string _operation;

		private readonly float _retryDelaySeconds;

		private readonly float _logIntervalSeconds;

		private float _retryAfter;

		private float _nextLogAt;

		private int _suppressedFailures;

		internal bool IsOpen => Time.realtimeSinceStartup < _retryAfter;

		internal FailureCircuitBreaker(string operation, float retryDelaySeconds = 10f, float logIntervalSeconds = 60f)
		{
			_operation = operation;
			_retryDelaySeconds = retryDelaySeconds;
			_logIntervalSeconds = logIntervalSeconds;
		}

		internal void Reset()
		{
			_retryAfter = 0f;
		}

		internal void Trip(Exception exception)
		{
			float realtimeSinceStartup = Time.realtimeSinceStartup;
			_retryAfter = realtimeSinceStartup + _retryDelaySeconds;
			if (realtimeSinceStartup < _nextLogAt)
			{
				_suppressedFailures++;
				return;
			}
			string text = ((_suppressedFailures > 0) ? $" ({_suppressedFailures} repeated failures suppressed)" : string.Empty);
			_suppressedFailures = 0;
			_nextLogAt = realtimeSinceStartup + _logIntervalSeconds;
			Plugin.LogInstance.LogWarning((object)$"{_operation} paused for {_retryDelaySeconds:0} seconds after an error{text}: {exception}");
		}
	}
	internal static class FoodStatsResolver
	{
		private readonly struct FoodResolutionCacheEntry
		{
			internal ItemDrop Output { get; }

			internal ResolvedFoodStats Stats { get; }

			internal FoodResolutionCacheEntry(ItemDrop output, ResolvedFoodStats stats)
			{
				Output = output;
				Stats = stats;
			}
		}

		private static readonly Dictionary<string, ItemDrop> CookedByInput = new Dictionary<string, ItemDrop>(StringComparer.Ordinal);

		private static readonly Dictionary<string, ItemDrop> FeastFoodByInput = new Dictionary<string, ItemDrop>(StringComparer.Ordinal);

		private static readonly Dictionary<int, FoodResolutionCacheEntry> ResolutionByOutput = new Dictionary<int, FoodResolutionCacheEntry>();

		private static int _sceneInstanceId = int.MinValue;

		private static int _scenePrefabCount = -1;

		internal static void Reset()
		{
			CookedByInput.Clear();
			FeastFoodByInput.Clear();
			ResolutionByOutput.Clear();
			_sceneInstanceId = int.MinValue;
			_scenePrefabCount = -1;
		}

		internal static ResolvedFoodStats Resolve(ItemDrop output)
		{
			if (output == null || (Object)(object)output == (Object)null)
			{
				return default(ResolvedFoodStats);
			}
			bool flag = EnsureIndex();
			int instanceID = ((Object)output).GetInstanceID();
			if (ResolutionByOutput.TryGetValue(instanceID, out var value) && value.Output == output)
			{
				return value.Stats;
			}
			Feast val = ((Component)output).GetComponent<Feast>() ?? ((Component)output).GetComponentInChildren<Feast>(true);
			ItemDrop val2 = (((Object)(object)val != (Object)null) ? GetFeastFood(val) : null);
			if ((Object)(object)val2 != (Object)null)
			{
				ResolvedFoodStats resolvedFoodStats = FromItem(val2, resolved: true, isFeast: true);
				if (flag)
				{
					ResolutionByOutput[instanceID] = new FoodResolutionCacheEntry(output, resolvedFoodStats);
				}
				return resolvedFoodStats;
			}
			string name = ((Object)((Component)output).gameObject).name;
			if (FeastFoodByInput.TryGetValue(name, out ItemDrop value2) && (Object)(object)value2 != (Object)null)
			{
				ResolvedFoodStats resolvedFoodStats2 = FromItem(value2, resolved: true, isFeast: true);
				if (flag)
				{
					ResolutionByOutput[instanceID] = new FoodResolutionCacheEntry(output, resolvedFoodStats2);
				}
				return resolvedFoodStats2;
			}
			ItemDrop val3 = output;
			bool resolved = false;
			string b = null;
			string b2 = null;
			string b3 = null;
			string b4 = null;
			for (int i = 0; i < 4; i++)
			{
				string name2 = ((Object)((Component)val3).gameObject).name;
				if (string.Equals(name2, b, StringComparison.Ordinal) || string.Equals(name2, b2, StringComparison.Ordinal) || string.Equals(name2, b3, StringComparison.Ordinal) || string.Equals(name2, b4, StringComparison.Ordinal) || !CookedByInput.TryGetValue(name2, out ItemDrop value3) || (Object)(object)value3 == (Object)null)
				{
					break;
				}
				switch (i)
				{
				case 0:
					b = name2;
					break;
				case 1:
					b2 = name2;
					break;
				case 2:
					b3 = name2;
					break;
				default:
					b4 = name2;
					break;
				}
				val3 = value3;
				resolved = true;
			}
			ResolvedFoodStats resolvedFoodStats3 = FromItem(val3, resolved, isFeast: false);
			if (flag)
			{
				ResolutionByOutput[instanceID] = new FoodResolutionCacheEntry(output, resolvedFoodStats3);
			}
			return resolvedFoodStats3;
		}

		private static bool EnsureIndex()
		{
			//IL_01c4: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ca: Invalid comparison between Unknown and I4
			ZNetScene instance = ZNetScene.instance;
			if ((Object)(object)instance == (Object)null || instance.m_prefabs == null)
			{
				return false;
			}
			int instanceID = ((Object)instance).GetInstanceID();
			int count = instance.m_prefabs.Count;
			if (_sceneInstanceId == instanceID && _scenePrefabCount == count)
			{
				return true;
			}
			Reset();
			_sceneInstanceId = instanceID;
			_scenePrefabCount = count;
			for (int i = 0; i < instance.m_prefabs.Count; i++)
			{
				GameObject val = instance.m_prefabs[i];
				if ((Object)(object)val == (Object)null)
				{
					continue;
				}
				CookingStation[] componentsInChildren = val.GetComponentsInChildren<CookingStation>(true);
				for (int j = 0; j < componentsInChildren.Length; j++)
				{
					List<ItemConversion> conversion = componentsInChildren[j].m_conversion;
					if (conversion == null)
					{
						continue;
					}
					for (int k = 0; k < conversion.Count; k++)
					{
						ItemConversion val2 = conversion[k];
						if (!((Object)(object)val2?.m_from == (Object)null) && !((Object)(object)val2.m_to == (Object)null))
						{
							string name = ((Object)((Component)val2.m_from).gameObject).name;
							if (!CookedByInput.ContainsKey(name))
							{
								CookedByInput.Add(name, val2.m_to);
							}
						}
					}
				}
				Feast[] componentsInChildren2 = val.GetComponentsInChildren<Feast>(true);
				foreach (Feast val3 in componentsInChildren2)
				{
					Piece val4 = ((Component)val3).GetComponent<Piece>() ?? ((Component)val3).GetComponentInParent<Piece>();
					ItemDrop feastFood = GetFeastFood(val3);
					if ((Object)(object)feastFood == (Object)null)
					{
						continue;
					}
					ItemDrop val5 = ((Component)val3).GetComponent<ItemDrop>() ?? ((Component)val3).GetComponentInParent<ItemDrop>();
					if ((Object)(object)val5 != (Object)null)
					{
						AddFeastMapping(((Object)((Component)val5).gameObject).name, feastFood);
					}
					ItemDrop component = val.GetComponent<ItemDrop>();
					if ((Object)(object)component != (Object)null)
					{
						AddFeastMapping(((Object)((Component)component).gameObject).name, feastFood);
					}
					if ((Object)(object)val4 == (Object)null || (int)val4.m_category != 5 || val4.m_resources == null)
					{
						continue;
					}
					for (int m = 0; m < val4.m_resources.Length; m++)
					{
						ItemDrop val6 = val4.m_resources[m]?.m_resItem;
						if (!((Object)(object)val6 == (Object)null))
						{
							AddFeastMapping(((Object)((Component)val6).gameObject).name, feastFood);
						}
					}
				}
			}
			return true;
		}

		private static ItemDrop? GetFeastFood(Feast feast)
		{
			if ((Object)(object)feast.m_foodItem != (Object)null)
			{
				return feast.m_foodItem;
			}
			return ((Component)feast).GetComponent<ItemDrop>() ?? ((Component)feast).GetComponentInParent<ItemDrop>();
		}

		private static void AddFeastMapping(string inputId, ItemDrop feastFood)
		{
			if (!string.IsNullOrEmpty(inputId) && !FeastFoodByInput.ContainsKey(inputId))
			{
				FeastFoodByInput.Add(inputId, feastFood);
			}
		}

		private static ResolvedFoodStats FromItem(ItemDrop item, bool resolved, bool isFeast)
		{
			SharedData shared = item.m_itemData.m_shared;
			return new ResolvedFoodStats(shared.m_food, shared.m_foodStamina, shared.m_foodEitr, resolved, isFeast);
		}
	}
	internal readonly struct ResolvedFoodStats
	{
		internal float Health { get; }

		internal float Stamina { get; }

		internal float Eitr { get; }

		internal bool Resolved { get; }

		internal bool IsFeast { get; }

		internal ResolvedFoodStats(float health, float stamina, float eitr, bool resolved, bool isFeast)
		{
			Health = health;
			Stamina = stamina;
			Eitr = eitr;
			Resolved = resolved;
			IsFeast = isFeast;
		}
	}
	internal static class HammerGridDimensions
	{
		internal const int NativeWidth = 15;

		internal const int NativeHeight = 6;

		internal const int ExpandedWidth = 15;

		internal const int ExpandedHeight = 6;

		internal const float ReferenceCraftingRowScale = 1.1666666f;

		internal static int Width
		{
			get
			{
				if (!ModConfig.Enabled.Value)
				{
					return 15;
				}
				return 15;
			}
		}

		internal static int Height
		{
			get
			{
				if (!ModConfig.Enabled.Value)
				{
					return 6;
				}
				return 6;
			}
		}

		internal static int MaxX => Width - 1;

		internal static int MaxY => Height - 1;

		internal static float CraftingRowPitch(Hud hud)
		{
			return hud.m_pieceIconSpacing * 1.1666666f;
		}
	}
	internal static class HammerGridSizer
	{
		private sealed class RectState
		{
			private readonly RectTransform _rect;

			private readonly Vector2 _sizeDelta;

			private readonly Vector2 _anchoredPosition;

			internal RectState(RectTransform rect)
			{
				//IL_000f: Unknown result type (might be due to invalid IL or missing references)
				//IL_0014: Unknown result type (might be due to invalid IL or missing references)
				//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)
				_rect = rect;
				_sizeDelta = rect.sizeDelta;
				_anchoredPosition = rect.anchoredPosition;
			}

			internal void Restore()
			{
				//IL_0016: 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)
				if (!((Object)(object)_rect == (Object)null))
				{
					_rect.sizeDelta = _sizeDelta;
					_rect.anchoredPosition = _anchoredPosition;
				}
			}
		}

		private sealed class ReparentedRectState
		{
			private readonly RectTransform _rect;

			private readonly Transform _parent;

			private readonly int _siblingIndex;

			private readonly Vector2 _anchorMin;

			private readonly Vector2 _anchorMax;

			private readonly Vector2 _pivot;

			private readonly Vector2 _sizeDelta;

			private readonly Vector2 _anchoredPosition;

			internal ReparentedRectState(RectTransform rect)
			{
				//IL_0027: Unknown result type (might be due to invalid IL or missing references)
				//IL_002c: Unknown result type (might be due to invalid IL or missing references)
				//IL_0033: 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_003f: 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_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_0057: Unknown result type (might be due to invalid IL or missing references)
				//IL_005c: Unknown result type (might be due to invalid IL or missing references)
				_rect = rect;
				_parent = ((Transform)rect).parent;
				_siblingIndex = ((Transform)rect).GetSiblingIndex();
				_anchorMin = rect.anchorMin;
				_anchorMax = rect.anchorMax;
				_pivot = rect.pivot;
				_sizeDelta = rect.sizeDelta;
				_anchoredPosition = rect.anchoredPosition;
			}

			internal void Restore()
			{
				//IL_0059: 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_007b: 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_009d: Unknown result type (might be due to invalid IL or missing references)
				if (!((Object)(object)_rect == (Object)null) && !((Object)(object)_parent == (Object)null))
				{
					((Transform)_rect).SetParent(_parent, false);
					((Transform)_rect).SetSiblingIndex(Mathf.Min(_siblingIndex, _parent.childCount - 1));
					_rect.anchorMin = _anchorMin;
					_rect.anchorMax = _anchorMax;
					_rect.pivot = _pivot;
					_rect.sizeDelta = _sizeDelta;
					_rect.anchoredPosition = _anchoredPosition;
				}
			}
		}

		private static int _hudInstanceId = int.MinValue;

		private static RectState? _windowState;

		private static RectState? _maskState;

		private static RectState? _categoryState;

		private static ReparentedRectState? _previousCategoryControlState;

		internal static float RepairRailWidth { get; private set; }

		internal static void Apply(Hud hud)
		{
			//IL_00a8: 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_00d1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00dd: Unknown result type (might be due to invalid IL or missing references)
			//IL_015b: Unknown result type (might be due to invalid IL or missing references)
			//IL_016a: Unknown result type (might be due to invalid IL or missing references)
			//IL_016f: 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_018d: Unknown result type (might be due to invalid IL or missing references)
			//IL_019e: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_0106: Unknown result type (might be due to invalid IL or missing references)
			//IL_0115: Unknown result type (might be due to invalid IL or missing references)
			//IL_011a: Unknown result type (might be due to invalid IL or missing references)
			int instanceID = ((Object)hud).GetInstanceID();
			if (_hudInstanceId != instanceID)
			{
				Restore();
				float pieceIconSpacing = hud.m_pieceIconSpacing;
				float num = 0f * pieceIconSpacing;
				float num2 = Mathf.Max(0f, 1f * pieceIconSpacing);
				RepairRailWidth = pieceIconSpacing + 28f;
				RectTransform val = (((Object)(object)hud.m_pieceSelectionWindow != (Object)null) ? hud.m_pieceSelectionWindow.GetComponent<RectTransform>() : null);
				if ((Object)(object)val != (Object)null)
				{
					_windowState = new RectState(val);
					ExpandCentered(val, num + RepairRailWidth, num2);
				}
				RectTransform pieceListMask = hud.m_pieceListMask;
				if ((Object)(object)pieceListMask != (Object)null)
				{
					_maskState = new RectState(pieceListMask);
					float widthDelta = (Mathf.Approximately(pieceListMask.anchorMin.x, pieceListMask.anchorMax.x) ? num : 0f);
					float heightDelta = (Mathf.Approximately(pieceListMask.anchorMin.y, pieceListMask.anchorMax.y) ? num2 : 0f);
					ExpandKeepingTopLeft(pieceListMask, widthDelta, heightDelta);
					pieceListMask.anchoredPosition += new Vector2(RepairRailWidth, 0f);
				}
				RectTransform val2 = (((Object)(object)hud.m_pieceCategoryRoot != (Object)null) ? hud.m_pieceCategoryRoot.GetComponent<RectTransform>() : null);
				if ((Object)(object)val2 != (Object)null)
				{
					_categoryState = new RectState(val2);
					val2.sizeDelta -= new Vector2(RepairRailWidth, 0f);
					val2.anchoredPosition += new Vector2(RepairRailWidth * (1f - val2.pivot.x), 0f);
					MovePreviousCategoryControl(val2, val, RepairRailWidth);
				}
				_hudInstanceId = instanceID;
			}
		}

		internal static void Restore()
		{
			_windowState?.Restore();
			_maskState?.Restore();
			_categoryState?.Restore();
			_previousCategoryControlState?.Restore();
			_windowState = null;
			_maskState = null;
			_categoryState = null;
			_previousCategoryControlState = null;
			_hudInstanceId = int.MinValue;
			RepairRailWidth = 0f;
		}

		private static void MovePreviousCategoryControl(RectTransform categoryRoot, RectTransform? window, float repairRailWidth)
		{
			//IL_0053: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: Unknown result type (might be due to invalid IL or missing references)
			//IL_007d: 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)
			if (!((Object)(object)window == (Object)null))
			{
				RectTransform val = FindInteractiveControl(categoryRoot, "Q") ?? FindInteractiveControl(window, "Q");
				if (!((Object)(object)val == (Object)null))
				{
					_previousCategoryControlState = new ReparentedRectState(val);
					((Transform)val).SetParent((Transform)(object)window, false);
					((Transform)val).SetAsLastSibling();
					val.anchorMin = new Vector2(0f, 1f);
					val.anchorMax = new Vector2(0f, 1f);
					val.pivot = new Vector2(0f, 1f);
					val.anchoredPosition = new Vector2(repairRailWidth + 42f, -18f);
				}
			}
		}

		private static RectTransform? FindInteractiveControl(RectTransform root, string displayedText)
		{
			TextMeshProUGUI[] componentsInChildren = ((Component)root).GetComponentsInChildren<TextMeshProUGUI>(true);
			for (int i = 0; i < componentsInChildren.Length; i++)
			{
				if (string.Equals(((TMP_Text)componentsInChildren[i]).text?.Trim(), displayedText, StringComparison.OrdinalIgnoreCase))
				{
					return InteractiveAncestor(root, ((TMP_Text)componentsInChildren[i]).transform);
				}
			}
			Text[] componentsInChildren2 = ((Component)root).GetComponentsInChildren<Text>(true);
			for (int j = 0; j < componentsInChildren2.Length; j++)
			{
				if (string.Equals(componentsInChildren2[j].text?.Trim(), displayedText, StringComparison.OrdinalIgnoreCase))
				{
					return InteractiveAncestor(root, ((Component)componentsInChildren2[j]).transform);
				}
			}
			return null;
		}

		private static RectTransform? InteractiveAncestor(RectTransform root, Transform child)
		{
			Transform val = child;
			while ((Object)(object)val != (Object)(object)root && (Object)(object)val.parent != (Object)null)
			{
				if ((Object)(object)((Component)val).GetComponent<UIInputHandler>() != (Object)null || (Object)(object)((Component)val).GetComponent<Button>() != (Object)null)
				{
					return (RectTransform?)(object)((val is RectTransform) ? val : null);
				}
				val = val.parent;
			}
			return TopLevelChild(root, child);
		}

		private static RectTransform? TopLevelChild(RectTransform root, Transform child)
		{
			Transform val = child;
			while ((Object)(object)val.parent != (Object)null && (Object)(object)val.parent != (Object)(object)root)
			{
				val = val.parent;
			}
			if (!((Object)(object)val.parent == (Object)(object)root))
			{
				return null;
			}
			return (RectTransform?)(object)((val is RectTransform) ? val : null);
		}

		private static void ExpandCentered(RectTransform rect, float widthDelta, float heightDelta)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			rect.sizeDelta += new Vector2(widthDelta, heightDelta);
		}

		private static void ExpandKeepingTopLeft(RectTransform rect, float widthDelta, float heightDelta)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			//IL_000e: 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_0021: 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_0040: Unknown result type (might be due to invalid IL or missing references)
			//IL_0045: Unknown result type (might be due to invalid IL or missing references)
			rect.sizeDelta += new Vector2(widthDelta, heightDelta);
			rect.anchoredPosition += new Vector2(widthDelta * rect.pivot.x, (0f - heightDelta) * (1f - rect.pivot.y));
		}
	}
	internal static class HammerGroupDecorations
	{
		private readonly struct CraftingEntry
		{
			internal int PieceIndex { get; }

			internal CraftingPieceLayout Metadata { get; }

			internal string Name { get; }

			internal CraftingEntry(int pieceIndex, CraftingPieceLayout metadata, string name)
			{
				PieceIndex = pieceIndex;
				Metadata = metadata;
				Name = name;
			}
		}

		private sealed class CraftingLayoutResult
		{
			internal int[] Slots { get; }

			internal float[] XOffsets { get; }

			internal int RepairIndex { get; }

			internal string[] RowLabels { get; }

			internal int[] Representatives { get; }

			internal List<SubgroupDivider> SubgroupBreaks { get; }

			internal int VisibleRows { get; }

			internal CraftingLayoutResult(int[] slots, float[] xOffsets, int repairIndex, string[] rowLabels, int[] representatives, List<SubgroupDivider> subgroupBreaks, int visibleRows)
			{
				Slots = slots;
				XOffsets = xOffsets;
				RepairIndex = repairIndex;
				RowLabels = rowLabels;
				Representatives = representatives;
				SubgroupBreaks = subgroupBreaks;
				VisibleRows = visibleRows;
			}
		}

		private readonly struct SubgroupDivider
		{
			internal int Row { get; }

			internal int Column { get; }

			internal int GapCount { get; }

			internal SubgroupDivider(int row, int column, int gapCount)
			{
				Row = row;
				Column = column;
				GapCount = gapCount;
			}
		}

		private sealed class ShelfLayoutResult
		{
			internal int[] Slots { get; }

			internal float[] XPositions { get; }

			internal List<ShelfCard> Cards { get; }

			internal List<ShelfDivider> Dividers { get; }

			internal int VisibleRows { get; }

			internal float RowPitch { get; }

			internal int RepairIndex { get; }

			internal ShelfLayoutResult(int[] slots, float[] xPositions, List<ShelfCard> cards, List<ShelfDivider> dividers, int visibleRows, float rowPitch, int repairIndex)
			{
				Slots = slots;
				XPositions = xPositions;
				Cards = cards;
				Dividers = dividers;
				VisibleRows = visibleRows;
				RowPitch = rowPitch;
				RepairIndex = repairIndex;
			}
		}

		private readonly struct ShelfCard
		{
			internal int StartRow { get; }

			internal int RowSpan { get; }

			internal string Label { get; }

			internal int Representative { get; }

			internal ShelfCard(int startRow, int rowSpan, string label, int representative)
			{
				StartRow = startRow;
				RowSpan = rowSpan;
				Label = label;
				Representative = representative;
			}
		}

		private readonly struct ShelfDivider
		{
			internal int Row { get; }

			internal float X { get; }

			internal ShelfDivider(int row, float x)
			{
				Row = row;
				X = x;
			}
		}

		private readonly struct NativeBackgroundState
		{
			private GameObject Root { get; }

			private bool Active { get; }

			private Image Image { get; }

			private Color Color { get; }

			private bool RaycastTarget { get; }

			private RectTransform Rect { get; }

			private Vector2 SizeDelta { get; }

			private UIInputHandler? Input { get; }

			private bool InputEnabled { get; }

			internal NativeBackgroundState(GameObject root, bool active, Image image, Color color, bool raycastTarget, RectTransform rect, Vector2 sizeDelta, UIInputHandler? input, bool inputEnabled)
			{
				//IL_0016: 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_002e: 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)
				Root = root;
				Active = active;
				Image = image;
				Color = color;
				RaycastTarget = raycastTarget;
				Rect = rect;
				SizeDelta = sizeDelta;
				Input = input;
				InputEnabled = inputEnabled;
			}

			internal void SetHovered(bool hovered)
			{
				//IL_0010: Unknown result type (might be due to invalid IL or missing references)
				//IL_0015: Unknown result type (might be due to invalid IL or missing references)
				//IL_0023: 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)
				if (!((Object)(object)Image == (Object)null))
				{
					Color color = Color;
					color.a = (hovered ? Mathf.Max(Color.a, 0.62f) : 0f);
					((Graphic)Image).color = color;
				}
			}

			internal void Restore()
			{
				//IL_0034: Unknown result type (might be due to invalid IL or missing references)
				//IL_0064: Unknown result type (might be due to invalid IL or missing references)
				if ((Object)(object)Root != (Object)null)
				{
					Root.SetActive(Active);
				}
				if ((Object)(object)Image != (Object)null)
				{
					((Graphic)Image).color = Color;
					((Graphic)Image).raycastTarget = RaycastTarget;
				}
				if ((Object)(object)Rect != (Object)null)
				{
					Rect.sizeDelta = SizeDelta;
				}
				if ((Object)(object)Input != (Object)null)
				{
					((Behaviour)Input).enabled = InputEnabled;
				}
			}
		}

		private readonly struct GroupPalette
		{
			internal Color Text { get; }

			internal Color Background { get; }

			internal GroupPalette(Color text, Color background)
			{
				//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_0008: Unknown result type (might be due to invalid IL or missing references)
				//IL_0009: Unknown result type (might be due to invalid IL or missing references)
				Text = text;
				Background = background;
			}
		}

		private sealed class CategoryCardView
		{
			internal GameObject Root { get; }

			internal RectTransform Rect { get; }

			internal Image Background { get; }

			internal RectTransform IconRect { get; }

			internal Image Icon { get; }

			internal RectTransform LabelRect { get; }

			internal TextMeshProUGUI Label { get; }

			internal CategoryCardView(GameObject root, RectTransform rect, Image background, RectTransform iconRect, Image icon, RectTransform labelRect, TextMeshProUGUI label)
			{
				Root = root;
				Rect = rect;
				Background = background;
				IconRect = iconRect;
				Icon = icon;
				LabelRect = labelRect;
				Label = label;
			}
		}

		private const string Prefix = "InventoryUX_";

		private const int GridWidth = 15;

		private const int GridHeight = 6;

		private const int CategoryColumns = 3;

		private const int ShelfColumns = 15;

		private const int ShelfRows = 7;

		private const float CraftingColumnPitchScale = 0.95f;

		private const float ShelfColumnPitchScale = 0.93f;

		private const float CategoryRailScale = 0.9f;

		private const float CategoryToItemsGap = 14f;

		private const float SubgroupSpacing = 26.4f;

		private const float SubgroupLineInset = 19.8f;

		private const float TileInset = 3f;

		private const float LabelHeight = 14f;

		private const float ViewControlsHeight = 76f;

		private const float ViewButtonGap = 6f;

		private const float HammerSearchHeight = 30f;

		private static readonly FieldInfo PieceIconsField = AccessTools.Field(typeof(Hud), "m_pieceIcons");

		private static readonly FieldInfo PlayerBuildPiecesField = AccessTools.Field(typeof(Player), "m_buildPieces");

		private static readonly MethodInfo UpdateAvailablePiecesMethod = AccessTools.Method(typeof(Player), "UpdateAvailablePiecesList", (Type[])null, (Type[])null);

		private static readonly MethodInfo HudUpdatePieceListMethod = AccessTools.Method(typeof(Hud), "UpdatePieceList", new Type[4]
		{
			typeof(Player),
			typeof(Vector2Int),
			typeof(PieceCategory),
			typeof(bool)
		}, (Type[])null);

		private static readonly Dictionary<int, NativeBackgroundState> NativeBackgrounds = new Dictionary<int, NativeBackgroundState>();

		private static readonly Dictionary<int, UIInputHandler> HoverInputs = new Dictionary<int, UIInputHandler>();

		private static readonly Dictionary<int, Piece> FavoritePiecesByInput = new Dictionary<int, Piece>();

		private static readonly List<CategoryCardView> CategoryCardPool = new List<CategoryCardView>();

		private static readonly List<Image> DecorationLinePool = new List<Image>();

		private static readonly List<GameObject> IconDecorationPool = new List<GameObject>();

		private static readonly HashSet<int> IconDecorationIds = new HashSet<int>();

		private static int _decorationPoolHudId = int.MinValue;

		private static int _usedCategoryCards;

		private static int _usedDecorationLines;

		private static Image? _categoryHeaderBackgroundForPass;

		private static Type? _iconType;

		private static FieldInfo? _iconGoField;

		private static int[] _visualSlots = Array.Empty<int>();

		private static int _visualWidth = 15;

		private static int _visualHeight = 6;

		private static bool _stateValid;

		private static int _appliedHudId = int.MinValue;

		private static readonly int[] PieceGenerations = new int[9];

		private static int _appliedPiecesGeneration = -1;

		private static int _appliedPieceCount = -1;

		private static bool _appliedShowSeparators;

		private static bool _appliedShowPieceNames;

		private static PieceCategory _appliedCategory = (PieceCategory)8;

		private static int _repairLogicalIndex = -1;

		private static Piece? _repairPiece;

		private static GameObject? _persistentRepair;

		private static GameObject? _hiddenRepairRoot;

		private static int _repairHudId = int.MinValue;

		private static GameObject? _persistentViewControls;

		private static Image? _defaultViewBackground;

		private static Image? _modViewBackground;

		private static int _viewControlsHudId = int.MinValue;

		private static int _cleanedGeneratedBackgroundHudId = int.MinValue;

		private static GameObject? _persistentHammerSearch;

		private static TMP_InputField? _hammerSearchInput;

		private static Image? _hammerSearchBackground;

		private static int _hammerSearchHudId = int.MinValue;

		private static string _hammerSearchText = string.Empty;

		private static string _hammerSearchQuery = string.Empty;

		private static bool _hammerSearchHasFocus;

		private static PieceCategory _hammerSearchCategory = (PieceCategory)8;

		private static GameObject? _hammerNoResults;

		private static bool _refreshingHammerList;

		private static readonly GroupPalette[] FallbackPalettes = new GroupPalette[8]
		{
			Palette(0.88f, 0.69f, 0.39f, 0.5f, 0.34f, 0.14f),
			Palette(0.84f, 0.52f, 0.4f, 0.46f, 0.25f, 0.2f),
			Palette(0.62f, 0.76f, 0.53f, 0.28f, 0.42f, 0.24f),
			Palette(0.59f, 0.72f, 0.82f, 0.25f, 0.37f, 0.48f),
			Palette(0.71f, 0.63f, 0.81f, 0.35f, 0.29f, 0.44f),
			Palette(0.49f, 0.76f, 0.73f, 0.2f, 0.4f, 0.38f),
			Palette(0.82f, 0.68f, 0.48f, 0.45f, 0.34f, 0.21f),
			Palette(0.77f, 0.6f, 0.68f, 0.42f, 0.27f, 0.35f)
		};

		internal static bool UseModView { get; private set; } = true;

		internal static bool IsSearchFocused => _hammerSearchHasFocus;

		internal static bool ShouldUseModView(PieceTable table)
		{
			if ((Object)(object)table != (Object)null && (Object)(object)((Component)table).gameObject != (Object)null)
			{
				return ModConfig.GetToolModView(((Object)((Component)table).gameObject).name);
			}
			return false;
		}

		internal static void NotifyPiecesChanged(PieceCategory category)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0002: Expected I4, but got Unknown
			int num = (int)category;
			if (num >= 0 && num < PieceGenerations.Length)
			{
				PieceGenerations[num]++;
			}
		}

		private static int GetPiecesGeneration(PieceCategory category)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0002: Expected I4, but got Unknown
			int num = (int)category;
			if (num < 0 || num >= PieceGenerations.Length)
			{
				return 0;
			}
			return PieceGenerations[num];
		}

		internal static void Apply(Hud hud, IReadOnlyList<Piece> pieces, PieceCategory category)
		{
			//IL_004b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0058: Unknown result type (might be due to invalid IL or missing references)
			//IL_0072: 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_007d: Invalid comparison between Unknown and I4
			//IL_0121: 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_00b0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b4: Invalid comparison between Unknown and I4
			//IL_00b8: 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_0253: Invalid comparison between Unknown and I4
			//IL_025b: Unknown result type (might be due to invalid IL or missing references)
			//IL_023d: Unknown result type (might be due to invalid IL or missing references)
			//IL_026a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0310: Unknown result type (might be due to invalid IL or missing references)
			//IL_03a4: Unknown result type (might be due to invalid IL or missing references)
			//IL_02e9: Unknown result type (might be due to invalid IL or missing references)
			//IL_019e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0321: Unknown result type (might be due to invalid IL or missing references)
			//IL_0375: Unknown result type (might be due to invalid IL or missing references)
			int instanceID = ((Object)hud).GetInstanceID();
			RemoveStaleRepairForDifferentHud(instanceID);
			Player localPlayer = Player.m_localPlayer;
			PieceTable val = (PieceTable)(((Object)(object)localPlayer == (Object)null) ? null : /*isinst with value type is only supported in some contexts*/);
			if ((Object)(object)val != (Object)null)
			{
				UseModView = ShouldUseModView(val);
			}
			EnsurePersistentViewControls(hud, instanceID);
			PrepareHammerSearchCategory(category);
			EnsurePersistentHammerSearch(hud, instanceID);
			UpdateHammerSearchVisibility(category);
			if (_cleanedGeneratedBackgroundHudId != instanceID)
			{
				RemoveGeneratedWarmBackgrounds(hud);
				_cleanedGeneratedBackgroundHudId = instanceID;
			}
			if (!IsEnabled(category))
			{
				Clear(hud, (int)category == 1);
				return;
			}
			bool value = ModConfig.ShowSeparators.Value;
			bool value2 = ModConfig.ShowHammerPieceNames.Value;
			if (_stateValid && _appliedHudId == instanceID && _appliedCategory == category && _appliedPiecesGeneration == GetPiecesGeneration(category) && _appliedPieceCount == pieces.Count && _appliedShowSeparators == value && _appliedShowPieceNames == value2)
			{
				return;
			}
			IList list = (IList)PieceIconsField.GetValue(hud);
			int num = Math.Min(pieces.Count, list.Count);
			Clear(hud);
			SetHammerNoResultsVisible(hud, visible: false);
			_categoryHeaderBackgroundForPass = FindVanillaCategoryHeaderBackground(hud);
			try
			{
				if (CountVisiblePieces(pieces, num, category) == 0 && !string.IsNullOrWhiteSpace(_hammerSearchText))
				{
					int[] array = new int[num];
					for (int i = 0; i < array.Length; i++)
					{
						array[i] = -1;
					}
					int num2 = FindRepairIndex(pieces, num);
					if (num2 >= 0)
					{
						EnsurePersistentRepair(hud, pieces, list, num2);
					}
					ConfigureNativePieceCells(list, pieces, num, array, num2);
					_visualSlots = array;
					_visualWidth = 15;
					_visualHeight = 6;
					SetHammerNoResultsVisible(hud, visible: true);
					RememberState(instanceID, category, pieces.Count, value, value2);
					return;
				}
				if ((int)category == 1 && CanUseReferenceCraftingLayout(pieces, num))
				{
					CraftingLayoutResult craftingLayoutResult = BuildCraftingLayout(pieces, num);
					_visualSlots = craftingLayoutResult.Slots;
					_repairLogicalIndex = craftingLayoutResult.RepairIndex;
					EnsurePersistentRepair(hud, pieces, list, craftingLayoutResult.RepairIndex);
					ApplyGridPermutation(hud, list, craftingLayoutResult, num);
					ConfigureNativePieceCells(list, pieces, num, craftingLayoutResult.Slots, craftingLayoutResult.RepairIndex);
					AddReferenceCraftingRows(hud, pieces, list, num, craftingLayoutResult);
					_visualWidth = 15;
					_visualHeight = craftingLayoutResult.VisibleRows;
					RememberState(instanceID, category, pieces.Count, value, value2);
					return;
				}
				if ((int)category != 1 && CanUseShelfLayout(pieces, num, category))
				{
					ShelfLayoutResult shelfLayoutResult = BuildShelfLayout(hud, pieces, num, category);
					_visualSlots = shelfLayoutResult.Slots;
					_visualWidth = 15;
					_visualHeight = shelfLayoutResult.VisibleRows;
					_repairLogicalIndex = shelfLayoutResult.RepairIndex;
					if (shelfLayoutResult.RepairIndex >= 0)
					{
						EnsurePersistentRepair(hud, pieces, list, shelfLayoutResult.RepairIndex);
					}
					ConfigureNativePieceCells(list, pieces, num, shelfLayoutResult.Slots, shelfLayoutResult.RepairIndex);
					ApplyShelfPositions(hud, list, shelfLayoutResult, num);
					AddShelfRows(hud, pieces, list, num, shelfLayoutResult);
					RememberState(instanceID, category, pieces.Count, value, value2);
					return;
				}
				string a = null;
				for (int j = 0; j < num; j++)
				{
					string text = HammerOrganizer.GetLabel(pieces[j], category) ?? "Other";
					GroupPalette palette = GetPalette(category, text);
					bool flag = !string.Equals(a, text, StringComparison.Ordinal);
					GameObject iconGameObject = GetIconGameObject(list[j]);
					AddTileTint(iconGameObject, palette, flag);
					if (ModConfig.IsFavorite(HammerOrganizer.GetPieceKey(pieces[j])))
					{
						AddFavoriteMarker(hud, iconGameObject);
					}
					if (flag && !IsStandaloneAction(category, text))
					{
						AddLabel(hud, iconGameObject, CompactLabel(text), palette);
					}
					a = text;
				}
				RememberState(instanceID, category, pieces.Count, value, value2);
			}
			catch
			{
				RemoveDecorations(hud, list);
				ResetState();
				throw;
			}
		}

		private static void RememberState(int hudInstanceId, PieceCategory category, int pieceCount, bool showSeparators, bool showPieceNames)
		{
			//IL_0006: 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_000c: Unknown result type (might be due to invalid IL or missing references)
			_appliedHudId = hudInstanceId;
			_appliedCategory = category;
			_appliedPiecesGeneration = GetPiecesGeneration(category);
			_appliedPieceCount = pieceCount;
			_appliedShowSeparators = showSeparators;
			_appliedShowPieceNames = showPieceNames;
			_stateValid = true;
		}

		private static void ResetState()
		{
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			_stateValid = false;
			_appliedHudId = int.MinValue;
			_appliedPiecesGeneration = -1;
			_appliedPieceCount = -1;
			_appliedCategory = (PieceCategory)8;
			_visualSlots = Array.Empty<int>();
			_visualWidth = 15;
			_visualHeight = 6;
			_repairLogicalIndex = -1;
			_categoryHeaderBackgroundForPass = null;
		}

		internal static bool TryNavigate(PieceTable table, int horizontal, int vertical)
		{
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: 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_001f: Unknown result type (might be due to invalid IL or missing references)
			if (_visualSlots.Length < 2 || table.GetSelectedCategory() != _appliedCategory)
			{
				return false;
			}
			Vector2Int selectedIndex = table.GetSelectedIndex();
			int num = ((Vector2Int)(ref selectedIndex)).y * 15 + ((Vector2Int)(ref selectedIndex)).x;
			if (num < 0 || num >= _visualSlots.Length)
			{
				return false;
			}
			int num2 = _visualSlots[num];
			if (num2 < 0)
			{
				int num3 = ((horizontal < 0 || vertical < 0) ? FindLastVisualPiece() : FindFirstVisualPiece());
				if (num3 >= 0)
				{
					SelectLogicalIndex(table, num3);
				}
				return true;
			}
			int num4 = num2 % _visualWidth;
			int num5 = num2 / _visualWidth;
			int num6 = -1;
			if (horizontal != 0)
			{
				int num7 = int.MaxValue;
				for (int i = 0; i < _visualSlots.Length; i++)
				{
					int num8 = _visualSlots[i];
					if (num8 < 0 || num8 / _visualWidth != num5)
					{
						continue;
					}
					int num9 = num8 % _visualWidth - num4;
					if ((horizontal >= 0 || num9 < 0) && (horizontal <= 0 || num9 > 0))
					{
						int num10 = Math.Abs(num9);
						if (num10 < num7)
						{
							num7 = num10;
							num6 = i;
						}
					}
				}
				if (num6 < 0 && horizontal < 0 && _repairLogicalIndex >= 0)
				{
					num6 = _repairLogicalIndex;
				}
				else if (num6 < 0)
				{
					int num11 = ((horizontal < 0) ? int.MinValue : int.MaxValue);
					for (int j = 0; j < _visualSlots.Length; j++)
					{
						int num12 = _visualSlots[j];
						if (num12 >= 0 && num12 / _visualWidth == num5)
						{
							int num13 = num12 % _visualWidth;
							if ((horizontal < 0 && num13 > num11) || (horizontal > 0 && num13 < num11))
							{
								num11 = num13;
								num6 = j;
							}
						}
					}
				}
			}
			else if (vertical != 0)
			{
				for (int k = 1; k < _visualHeight; k++)
				{
					if (num6 >= 0)
					{
						break;
					}
					int num14 = (num5 + vertical * k + _visualHeight * 2) % _visualHeight;
					int num15 = int.MaxValue;
					for (int l = 0; l < _visualSlots.Length; l++)
					{
						int num16 = _visualSlots[l];
						if (num16 >= 0 && num16 / _visualWidth == num14)
						{
							int num17 = Math.Abs(num16 % _visualWidth - num4);
							if (num17 < num15)
							{
								num15 = num17;
								num6 = l;
							}
						}
					}
				}
			}
			if (num6 >= 0 && num6 != num)
			{
				SelectLogicalIndex(table, num6);
			}
			return true;
		}

		private static void SelectLogicalIndex(PieceTable table, int logicalIndex)
		{
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			table.SetSelected(new Vector2Int(logicalIndex % 15, logicalIndex / 15));
		}

		private static int FindFirstVisualPiece()
		{
			int result = -1;
			int num = int.MaxValue;
			for (int i = 0; i < _visualSlots.Length; i++)
			{
				int num2 = _visualSlots[i];
				if (num2 >= 0 && num2 < num)
				{
					num = num2;
					result = i;
				}
			}
			return result;
		}

		private static int FindLastVisualPiece()
		{
			int result = -1;
			int num = int.MinValue;
			for (int i = 0; i < _visualSlots.Length; i++)
			{
				int num2 = _visualSlots[i];
				if (num2 > num)
				{
					num = num2;
					result = i;
				}
			}
			return result;
		}

		private static CraftingLayoutResult BuildCraftingLayout(IReadOnlyList<Piece> pieces, int count)
		{
			List<CraftingEntry>[] array = new List<CraftingEntry>[6];
			for (int i = 0; i < array.Length; i++)
			{
				array[i] = new List<CraftingEntry>();
			}
			List<CraftingEntry> list = new List<CraftingEntry>();
			int repairIndex = -1;
			for (int j = 0; j < count; j++)
			{
				Piece val = pieces[j];
				if (CraftingLayoutMetadata.IsRepair(val))
				{
					repairIndex = j;
				}
				else if (HammerOrganizer.MatchesPreparedSearch(val, (PieceCategory)1, _hammerSearchQuery))
				{
					CraftingPieceLayout metadata = CraftingLayoutMetadata.Resolve(val);
					CraftingEntry item = new CraftingEntry(j, metadata, Localize(val.m_name));
					if (ModConfig.IsFavorite(HammerOrganizer.GetPieceKey(val)))
					{
						list.Add(item);
					}
					else
					{
						array[(int)metadata.Section].Add(item);
					}
				}
			}
			list.Sort(CompareCraftingEntries);
			for (int k = 0; k < array.Length; k++)
			{
				array[k].Sort(CompareCraftingEntries);
			}
			int num = 6 + ((list.Count > 0) ? 1 : 0);
			int[] array2 = new int[count];
			for (int l = 0; l < array2.Length; l++)
			{
				array2[l] = -1;
			}
			float[] array3 = new float[count];
			bool[] array4 = new bool[15 * num];
			string[] array5 = new string[num];
			int[] array6 = new int[num];
			for (int m = 0; m < array6.Length; m++)
			{
				array6[m] = -1;
			}
			List<SubgroupDivider> list2 = new List<SubgroupDivider>();
			List<int> list3 = new List<int>();
			int num2 = 0;
			if (list.Count > 0)
			{
				array5[num2] = "FAVORITES";
				array6[num2] = list[0].PieceIndex;
				int num3 = 3;
				for (int n = 0; n < list.Count; n++)
				{
					CraftingEntry craftingEntry = list[n];
					if (num3 >= 15)
					{
						list3.Add(craftingEntry.PieceIndex);
						continue;
					}
					int num4 = num2 * 15 + num3++;
					array2[craftingEntry.PieceIndex] = num4;
					array4[num4] = true;
				}
				num2++;
			}
			for (int num5 = 0; num5 < array.Length; num5++)
			{
				if (num2 >= num)
				{
					break;
				}
				List<CraftingEntry> list4 = array[num5];
				if (list4.Count == 0)
				{
					continue;
				}
				array5[num2] = CraftingLayoutMetadata.Label((CraftingSection)num5);
				array6[num2] = FindCategoryRepresentative(list4, (CraftingSection)num5);
				int num6 = 3;
				int subgroup = list4[0].Metadata.Subgroup;
				int num7 = 0;
				for (int num8 = 0; num8 < list4.Count; num8++)
				{
					CraftingEntry craftingEntry2 = list4[num8];
					if (num8 > 0 && craftingEntry2.Metadata.Subgroup != subgroup)
					{
						num7++;
						list2.Add(new SubgroupDivider(num2, num6, num7));
					}
					if (num6 >= 15)
					{
						list3.Add(craftingEntry2.PieceIndex);
					}
					else
					{
						int num9 = num2 * 15 + num6;
						array2[craftingEntry2.PieceIndex] = num9;
						array3[craftingEntry2.PieceIndex] = (float)num7 * 26.4f;
						array4[num9] = true;
						num6++;
					}
					subgroup = craftingEntry2.Metadata.Subgroup;
				}
				num2++;
			}
			for (int num10 = 0; num10 < list3.Count; num10++)
			{
				int num11 = FirstFreePieceSlot(array4, num);
				if (num11 < 0)
				{
					break;
				}
				array2[list3[num10]] = num11;
				array4[num11] = true;
			}
			return new CraftingLayoutResult(array2, array3, repairIndex, array5, array6, list2, num2);
		}

		private static int CompareCraftingEntries(CraftingEntry left, CraftingEntry right)
		{
			int num = left.Metadata.SortOrder.CompareTo(right.Metadata.SortOrder);
			if (num != 0)
			{
				return num;
			}
			num = string.Compare(left.Name, right.Name, StringComparison.CurrentCultureIgnoreCase);
			if (num == 0)
			{
				return left.PieceIndex.CompareTo(right.PieceIndex);
			}
			return num;
		}

		private static bool CanUseShelfLayout(IReadOnlyList<Piece> pieces, int count, PieceCategory category)
		{
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			int num = 0;
			for (int i = 0; i < count; i++)
			{
				if (!CraftingLayoutMetadata.IsRepair(pieces[i]) && HammerOrganizer.MatchesPreparedSearch(pieces[i], category, _hammerSearchQuery))
				{
					num++;
				}
			}
			if (num > 0)
			{
				return num <= 105;
			}
			return false;
		}

		private static ShelfLayoutResult BuildShelfLayout(Hud hud, IReadOnlyList<Piece> pieces, int count, PieceCategory category)
		{
			//IL_00c7: 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_00df: Unknown result type (might be due to invalid IL or missing references)
			//IL_0189: Unknown result type (might be due to invalid IL or missing references)
			//IL_018b: Invalid comparison between Unknown and I4
			//IL_018d: Unknown result type (might be due to invalid IL or missing references)
			//IL_036d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0276: Unknown result type (might be due to invalid IL or missing references)
			//IL_02e3: Unknown result type (might be due to invalid IL or missing references)
			//IL_030f: Unknown result type (might be due to invalid IL or missing references)
			List<int> list = new List<int>(count);
			int repairIndex = -1;
			for (int i = 0; i < count; i++)
			{
				if (CraftingLayoutMetadata.IsRepair(pieces[i]))
				{
					repairIndex = i;
				}
			}
			for (int j = 0; j < 2; j++)
			{
				bool flag = j == 0;
				for (int k = 0; k < count; k++)
				{
					Piece piece = pieces[k];
					if (!CraftingLayoutMetadata.IsRepair(piece) && HammerOrganizer.MatchesPreparedSearch(piece, category, _hammerSearchQuery) && ModConfig.IsFavorite(HammerOrganizer.GetPieceKey(piece)) == flag)
					{
						list.Add(k);
					}
				}
			}
			string[] array = new string[list.Count];
			int[] array2 = new int[list.Count];
			int num = 0;
			int num2 = 0;
			string a = null;
			for (int l = 0; l < list.Count; l++)
			{
				Piece piece2 = pieces[list[l]];
				PieceGroup pieceGroup = HammerOrganizer.Classify(piece2, category);
				string text = (array[l] = (ModConfig.IsFavorite(HammerOrganizer.GetPieceKey(piece2)) ? "Favorites" : (HammerOrganizer.GetLabel(piece2, category) ?? pieceGroup.Label)));
				array2[l] = pieceGroup.Suborder;
				if (l == 0 || string.Equals(a, text, StringComparison.Ordinal))
				{
					num2++;
				}
				else
				{
					num += Mathf.CeilToInt((float)num2 / 15f);
					num2 = 1;
				}
				a = text;
			}
			if (num2 > 0)
			{
				num += Mathf.CeilToInt((float)num2 / 15f);
			}
			int num3 = Mathf.Clamp(Mathf.Max(Mathf.CeilToInt((float)list.Count / 15f), num), 1, 7);
			List<int> list2 = (((int)category == 2) ? BuildMaterialRowSizes(array) : (((int)category == 0 && HasCultivatorGroups(array)) ? BuildCultivatorRowSizes(array, array2) : null));
			if (list2 != null)
			{
				num3 = list2.Count;
			}
			float pieceIconSpacing = hud.m_pieceIconSpacing;
			float rowPitch = ShelfRowPitch(hud, num3);
			float num4 = CategoryRailWidth(pieceIconSpacing) + 14f;
			float num5 = 14f * pieceIconSpacing;
			int[] array3 = new int[count];
			for (int m = 0; m < array3.Length; m++)
			{
				array3[m] = -1;
			}
			float[] array4 = new float[count];
			string[] array5 = new string[num3];
			int[] array6 = new int[num3];
			List<ShelfDivider> list3 = new List<ShelfDivider>();
			int num6 = 0;
			for (int n = 0; n < num3; n++)
			{
				int num7 = list2?[n] ?? ShelfRowPlanner.ChooseGroupRowSize(array, num6, 15, num3 - n);
				array5[n] = array[num6];
				array6[n] = list[num6];
				int num8 = 0;
				for (int num9 = 1; num9 < num7; num9++)
				{
					if (IsShelfBreak(array, array2, num6 + num9, category))
					{
						num8++;
					}
				}
				float num10 = pieceIconSpacing * 0.93f;
				if (num7 > 1)
				{
					float num11 = (num5 - num4 - (float)num8 * 26.4f) / (float)(num7 - 1);
					num10 = Mathf.Min(num10, num11);
				}
				int num12 = 0;
				for (int num13 = 0; num13 < num7; num13++)
				{
					int index = num6 + num13;
					int num14 = list[index];
					if (num13 > 0 && IsShelfBreak(array, array2, index, category))
					{
						num12++;
					}
					float num15 = num4 + (float)num13 * num10 + (float)num12 * 26.4f;
					if (num13 > 0 && IsShelfBreak(array, array2, index, category))
					{
						list3.Add(new ShelfDivider(n, num15 - 19.8f));
					}
					array3[num14] = n * 15 + num13;
					array4[num14] = num15;
				}
				num6 += num7;
			}
			List<ShelfCard> cards = BuildShelfCards(pieces, list, array, array5, array6, category);
			return new ShelfLayoutResult(array3, array4, cards, list3, num3, rowPitch, repairIndex);
		}

		private static bool IsShelfBreak(string[] labels, int[] subgroups, int index, PieceCategory category)
		{
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Invalid comparison between Unknown and I4
			//IL_0039: 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_0076: Invalid comparison between Unknown and I4
			if (index <= 0 || index >= labels.Length)
			{
				return false;
			}
			if (!string.Equals(labels[index - 1], labels[index], StringComparison.Ordinal))
			{
				return true;
			}
			if ((int)category == 2 && string.Equals(Normalize(labels[index]), "corewood", StringComparison.Ordinal))
			{
				return false;
			}
			if ((int)category == 0 && (string.Equals(Normalize(labels[index]), "vanilla", StringComparison.Ordinal) || string.Equals(Normalize(labels[index]), "planteverything", StringComparison.Ordinal)))
			{
				return subgroups[index - 1] != subgroups[index];
			}
			if ((int)category == 2)
			{
				return subgroups[index - 1] != subgroups[index];
			}
			return false;
		}

		private static List<int> BuildMaterialRowSizes(string[] labels)
		{
			List<int> list = new List<int>();
			int num = 0;
			while (num < labels.Length)
			{
				int i;
				for (i = num + 1; i < labels.Length && string.Equals(labels[num], labels[i], StringComparison.Ordinal); i++)
				{
				}
				int num2 = i - num;
				int num3 = Mathf.CeilToInt((float)num2 / 15f);
				for (int j = 0; j < num3; j++)
				{
					int num4 = Mathf.CeilToInt((float)num2 / (float)(num3 - j));
					list.Add(num4);
					num2 -= num4;
				}
				num = i;
			}
			return list;
		}

		private static bool HasCultivatorGroups(string[] labels)
		{
			for (int i = 0; i < labels.Length; i++)
			{
				string text = Normalize(labels[i]);
				if (text == "vanilla" || text == "planteverything")
				{
					return true;
				}
			}
			return false;
		}

		private static List<int> BuildCultivatorRowSizes(string[] labels, int[] subgroups)
		{
			List<int> list = new List<int>();
			int num = 0;
			while (num < labels.Length)
			{
				string text = labels[num];
				int i;
				for (i = num + 1; i < labels.Length && string.Equals(text, labels[i], StringComparison.Ordinal); i++)
				{
				}
				string text2 = Normalize(text);
				if (text2 != "vanilla" && text2 != "planteverything")
				{
					AddBalancedRowSizes(list, i - num);
					num = i;
					continue;
				}
				while (num < i)
				{
					int num2 = subgroups[num];
					int j;
					for (j = num + 1; j < i && subgroups[j] == num2; j++)
					{
					}
					AddBalancedRowSizes(list, j - num);
					num = j;
				}
			}
			return list;
		}

		private static void AddBalancedRowSizes(List<int> sizes, int count)
		{
			int num = Mathf.CeilToInt((float)count / 15f);
			int num2 = count;
			for (int i = 0; i < num; i++)
			{
				int num3 = Mathf.CeilToInt((float)num2 / (float)(num - i));
				sizes.Add(num3);
				num2 -= num3;
			}
		}

		private static List<ShelfCard> BuildShelfCards(IReadOnlyList<Piece> pieces, List<int> sourceIndices, string[] labels, string[] rowLabels, int[] representatives, PieceCategory category)
		{
			//IL_0082: Unknown result type (might be due to invalid IL or missing references)
			//IL_0085: Invalid comparison between Unknown and I4
			//IL_0094: Unknown result type (might be due to invalid IL or missing references)
			List<ShelfCard> list = new List<ShelfCard>();
			for (int i = 0; i < rowLabels.Length; i++)
			{
				string text = rowLabels[i];
				if (list.Count > 0 && string.Equals(list[list.Count - 1].Label, text, StringComparison.Ordinal))
				{
					ShelfCard shelfCard = list[list.Count - 1];
					list[list.Count - 1] = new ShelfCard(shelfCard.StartRow, shelfCard.RowSpan + 1, shelfCard.Label, shelfCard.Representative);
					continue;
				}
				int num = representatives[i];
				if ((int)category == 2)
				{
					num = FindBuildingBeamRepresentative(pieces, sourceIndices, labels, text, num);
				}
				else if ((int)category == 0 && string.Equals(Normalize(text), "utility", StringComparison.Ordinal))
				{
					num = FindCartographyRepresentative(pieces, sourceIndices, labels, text, num);
				}
				list.Add(new ShelfCard(i, 1, text, num));
			}
			return list;
		}

		private static int FindBuildingBeamRepresentative(IReadOnlyList<Piece> pieces, List<int> sourceIndices, string[] labels, string label, int fallback)
		{
			string text = Normalize(label);
			for (int i = 0; i < sourceIndices.Count; i++)
			{
				if (string.Equals(labels[i], label, StringComparison.Ordinal))
				{
					Piece val = pieces[sourceIndices[i]];
					string text2 = Normalize(((Object)((Component)val).gameObject).name + " " + val.m_name);
					if (text2.Contains("beam") && (!(text == "darkwood") || text2.Contains("darkwood")) && (!(text == "ashwood") || text2.Contains("grausten") || text2.Contains("ashwood") || text2.Contains("blackwood")) && (!(text == "corewood") || text2.Contains("corewood") || text2.Contains("log")) && (!(text == "wood") || (!text2.Contains("darkwood") && !text2.Contains("grausten") && !text2.Contains("ashwood") && !text2.Contains("corewood") && !text2.Contains("log"))))
					{
						return sourceIndices[i];
					}
				}
			}
			return fallback;
		}

		private static int FindCartographyRepresentative(IReadOnlyList<Piece> pieces, List<int> sourceIndices, string[] labels, string label, int fallback)
		{
			for (int i = 0; i < sourceIndices.Count; i++)
			{
				if (string.Equals(labels[i], label, StringComparison.Ordinal))
				{
					Piece val = pieces[sourceIndices[i]];
					string text = Normalize(((Object)((Component)val).gameObject).name + " " + val.m_name);
					if (text.Contains("cartography") || text.Contains("maptable"))
					{
						return sourceIndices[i];
					}
				}
			}
			return fallback;
		}

		private static float CategoryRailWidth(float spacing)
		{
			return (3f * spacing - 28f) * 0.9f;
		}

		private static float CraftingContentShift(float spacing)
		{
			return CategoryRailWidth(spacing) + 14f - 3f * spacing * 0.95f;
		}

		private static float ShelfRowPitch(Hud hud, int visibleRows)
		{
			if (visibleRows <= 6)
			{
				return hud.m_pieceIconSpacing * 1.1666666f;
			}
			return hud.m_pieceIconSpacing * 7f / (float)visibleRows;
		}

		private static int FindCategoryRepresentative(List<CraftingEntry> entries, CraftingSection section)
		{
			int num = 100;
			for (int i = 0; i < entries.Count; i++)
			{
				if (entries[i].Metadata.SortOrder == num)
				{
					return entries[i].PieceIndex;
				}
			}
			return entries[0].PieceIndex;
		}

		private static int CountVisiblePieces(IReadOnlyList<Piece> pieces, int count, PieceCategory category)
		{
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			int num = 0;
			for (int i = 0; i < count; i++)
			{
				if (!CraftingLayoutMetadata.IsRepair(pieces[i]) && HammerOrganizer.MatchesPreparedSearch(pieces[i], category, _hammerSearchQuery))
				{
					num++;
				}
			}
			return num;
		}

		private static int FindRepairIndex(IReadOnlyList<Piece> pieces, int count)
		{
			for (int i = 0; i < count; i++)
			{
				if (CraftingLayoutMetadata.IsRepair(pieces[i]))
				{
					return i;
				}
			}
			return -1;
		}

		private static bool CanUseReferenceCraftingLayout(IReadOnlyList<Piece> pieces, int count)
		{
			int num = 0;
			bool flag = false;
			for (int i = 0; i < count; i++)
			{
				Piece piece = pieces[i];
				if (!CraftingLayoutMetadata.IsRepair(piece) && HammerOrganizer.MatchesPreparedSearch(piece, (PieceCategory)1, _hammerSearchQuery))
				{
					num++;
					if (ModConfig.IsFavorite(HammerOrganizer.GetPieceKey(piece)))
					{
						flag = true;
					}
				}
			}
			int num2 = 6 + (flag ? 1 : 0);
			if (num > 0)
			{
				return num <= 12 * num2;
			}
			return false;
		}

		private static int FirstFreePieceSlot(bool[] used, int rows)
		{
			for (int i = 0; i < rows; i++)
			{
				for (int j = 3; j < 15; j++)
				{
					int num = i * 15 + j;
					if (!used[num])
					{
						return num;
					}
				}
			}
			return -1;
		}

		private static void AddReferenceCraftingRows(Hud hud, IReadOnlyList<Piece> pieces, IList icons, int count, CraftingLayoutResult layout)
		{
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Expected O, but got Unknown
			RectTransform templateRect = (RectTransform)GetIconGameObject(icons[0]).transform;
			for (int i = 0; i < count; i++)
			{
				if (i != layout.RepairIndex && layout.Slots[i] >= 0)
				{
					GameObject iconGameObject = GetIconGameObject(icons[i]);
					if (ModConfig.IsFavorite(HammerOrganizer.GetPieceKey(pieces[i])))
					{
						AddFavoriteMarker(hud, iconGameObject);
					}
					if (ModConfig.ShowHammerPieceNames.Value)
					{
						AddReferenceTile(hud, iconGameObject, pieces[i]);
					}
				}
			}
			for (int j = 0; j < layout.VisibleRows; j++)
			{
				if (j < layout.VisibleRows - 1 && ModConfig.ShowSeparators.Value)
				{
					AddRowSeparator(hud, templateRect, j, CraftingRowPitch(hud, layout.VisibleRows));
				}
				int num = layout.Representatives[j];
				if (!string.IsNullOrEmpty(layout.RowLabels[j]) && num >= 0)
				{
					AddCategoryCard(hud, templateRect, j, CraftingRowPitch(hud, layout.VisibleRows), layout.RowLabels[j], pieces[num]);
				}
			}
			if (ModConfig.ShowSeparators.Value)
			{
				for (int k = 0; k < layout.SubgroupBreaks.Count; k++)
				{
					AddSubgroupSeparator(hud, templateRect, layout.SubgroupBreaks[k], CraftingRowPitch(hud, layout.VisibleRows));
				}
			}
		}

		private static void AddShelfRows(Hud hud, IReadOnlyList<Piece> pieces, IList icons, int count, ShelfLayoutResult layout)
		{
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Expected O, but got Unknown
			RectTransform templateRect = (RectTransform)GetIconGameObject(icons[0]).transform;
			for (int i = 0; i < count; i++)
			{
				if (layout.Slots[i] >= 0)
				{
					GameObject iconGameObject = GetIconGameObject(icons[i]);
					if (ModConfig.IsFavorite(HammerOrganizer.GetPieceKey(pieces[i])))
					{
						AddFavoriteMarker(hud, iconGameObject);
					}
					if (ModConfig.ShowHammerPieceNames.Value)
					{
						AddReferenceTile(hud, iconGameObject, pieces[i]);
					}
				}
			}
			for (int j = 0; j < layout.VisibleRows; j++)
			{
				if (j >= layout.VisibleRows - 1 || !ModConfig.ShowSeparators.Value)
				{
					continue;
				}
				bool flag = false;
				for (int k = 0; k < layout.Cards.Count; k++)
				{
					if (layout.Cards[k].StartRow == j + 1)
					{
						flag = true;
						break;
					}
				}
				if (flag)
				{
					AddRowSeparator(hud, templateRect, j, layout.RowPitch, 0f);
				}
			}
			for (int l = 0; l < layout.Cards.Count; l++)
			{
				ShelfCard shelfCard = layout.Cards[l];
				AddCategoryCard(hud, templateRect, shelfCard.StartRow, layout.RowPitch, shelfCard.Label, pieces[shelfCard.Representative], shelfCard.RowSpan);
			}
			if (ModConfig.ShowSeparators.Value)
			{
				for (int m = 0; m < layout.Dividers.Count; m++)
				{
					AddShelfDivider(hud, templateRect, layout.Dividers[m], layout.RowPitch);
				}
			}
		}

		private static void AddReferenceTile(Hud hud, GameObject iconRoot, Piece piece)
		{
			//IL_004f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0055: Expected O, but got Unknown
			//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_008e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0098: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ad: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b8: 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_00cd: 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_0168: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a6: Unknown result type (might be due to invalid IL or missing references)
			Transform val = iconRoot.transform.Find("InventoryUX_CraftingPieceName");
			GameObject val2;
			if ((Object)(object)val != (Object)null)
			{
				val2 = ((Component)val).gameObject;
				val2.SetActive(true);
			}
			else
			{
				val2 = new GameObject("InventoryUX_CraftingPieceName", new Type[2]
				{
					typeof(RectTransform),
					typeof(TextMeshProUGUI)
				});
				val2.transform.SetParent(iconRoot.transform, false);
			}
			TrackIconDecoration(val2);
			val2.transform.SetAsLastSibling();
			RectTransform val3 = (RectTransform)val2.transform;
			val3.anchorMin = new Vector2(0f, 0f);
			val3.anchorMax = new Vector2(1f, 0f);
			val3.pivot = new Vector2(0.5f, 0f);
			val3.anchoredPosition = new Vector2(0f, 3f);
			val3.sizeDelta = new Vector2(-8f, 27f);
			TextMeshProUGUI component = val2.GetComponent<TextMeshProUGUI>();
			((TMP_Text)component).text = Localize(piece.m_name);
			((TMP_Text)component).font = (((Object)(object)hud.m_pieceDescription != (Object)null) ? hud.m_pieceDescription.font : null);
			((TMP_Text)component).fontSize = 10.6f;
			((TMP_Text)component).fontSizeMin = 8.6f;
			((TMP_Text)component).fontSizeMax = 10.6f;
			((TMP_Text)component).enableAutoSizing = true;
			((TMP_Text)component).fontStyle = (FontStyles)1;
			((Graphic)component).color = new Color(0.96f, 0.88f, 0.72f, 1f);
			((TMP_Text)component).alignment = (TextAlignmentOptions)1026;
			((TMP_Text)component).textWrappingMode = (TextWrappingModes)1;
			((TMP_Text)component).overflowMode = (TextOverflowModes)1;
			((TMP_Text)component).maxVisibleLines = 2;
			((TMP_Text)component).outlineWidth = 0.22f;
			((TMP_Text)component).outlineColor = new Color32((byte)0, (byte)0, (byte)0, byte.MaxValue);
			((Graphic)component).raycastTarget = false;
		}

		private static void AddFavoriteMarker(Hud hud, GameObject iconRoot)
		{
			//IL_004f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0055: Expected O, but got Unknown
			//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_008e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0098: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ad: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b8: 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_00cd: 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_0145: Unknown result type (might be due to invalid IL or missing references)
			//IL_0166: 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)
			Transform val = iconRoot.transform.Find("InventoryUX_FavoriteMarker");
			GameObject val2;
			if ((Object)(object)val != (Object)null)
			{
				val2 = ((Component)val).gameObject;
				val2.SetActive(true);
			}
			else
			{
				val2 = new GameObject("InventoryUX_FavoriteMarker", new Type[2]
				{
					typeof(RectTransform),
					typeof(TextMeshProUGUI)
				});
				val2.transform.SetParent(iconRoot.transform, false);
			}
			TrackIconDecoration(val2);
			val2.transform.SetAsLastSibling();
			RectTransform val3 = (RectTransform)val2.transform;
			val3.anchorMin = new Vector2(1f, 1f);
			val3.anchorMax = new Vector2(1f, 1f);
			val3.pivot = new Vector2(1f, 1f);
			val3.anchoredPosition = new Vector2(-2f, -1f);
			val3.sizeDelta = new Vector2(22f, 22f);
			TextMeshProUGUI component = val2.GetComponent<TextMeshProUGUI>();
			((TMP_Text)component).text = "★";
			((TMP_Text)component).font = (((Object)(object)hud.m_pieceDescription != (Object)null) ? hud.m_pieceDescription.font : null);
			((TMP_Text)component).fontSize = 17f;
			((TMP_Text)component).fontStyle = (FontStyles)1;
			((Graphic)component).color = new Color(0.93f, 0.63f, 0.25f, 1f);
			((TMP_Text)component).alignment = (TextAlignmentOptions)260;
			((TMP_Text)component).outlineWidth = 0.22f;
			((TMP_Text)component).outlineColor = Color32.op_Implicit(Color.black);
			((Graphic)component).raycastTarget = false;
		}

		private static void AddCategoryCard(Hud hud, RectTransform templateRect, int row, CraftingSection section, Piece representative)
		{
			AddCategoryCard(hud, templateRect, row, HammerGridDimensions.CraftingRowPitch(hud), CraftingLayoutMetadata.Label(section), representative);
		}

		private static void AddCategoryCard(Hud hud, RectTransform templateRect, int row, float rowPitch, string text, Piece representative, int rowSpan = 1)
		{
			//IL_003c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			//IL_0054: 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_0084: Unknown result type (might be due to invalid IL or missing references)
			//IL_013c: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ca: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ff: Unknown result type (might be due to invalid IL or missing references)
			//IL_015e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0173: 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_019d: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b1: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d6: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ed: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f8: Unknown result type (might be due to invalid IL or missing references)
			//IL_020d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0221: Unknown result type (might be due to invalid IL or missing references)
			//IL_02a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_02dc: Unknown result type (might be due to invalid IL or missing references)
			float pieceIconSpacing = hud.m_pieceIconSpacing;
			CategoryCardView categoryCardView = AcquireCategoryCard(hud);
			GameObject root = categoryCardView.Root;
			((Object)root).name = "InventoryUX_CraftingCategory_" + row;
			root.transform.SetAsLastSibling();
			RectTransform rect = categoryCardView.Rect;
			rect.anchorMin = templateRect.anchorMin;
			rect.anchorMax = templateRect.anchorMax;
			rect.pivot = templateRect.pivot;
			rect.anchoredPosition = new Vector2(0f, (float)(-row) * rowPitch);
			rect.sizeDelta = new Vector2(CategoryRailWidth(pieceIconSpacing), rowPitch * (float)rowSpan - 7f);
			Image background = categoryCardView.Background;
			Image categoryHeaderBackgroundForPass = _categoryHeaderBackgroundForPass;
			if ((Object)(object)categoryHeaderBackgroundForPass != (Object)null)
			{
				background.sprite = categoryHeaderBackgroundForPass.sprite;
				background.overrideSprite = categoryHeaderBackgroundForPass.overrideSprite;
				((Graphic)background).material = ((Graphic)categoryHeaderBackgroundForPass).material;
				background.type = categoryHeaderBackgroundForPass.type;
				background.preserveAspect = categoryHeaderBackgroundForPass.preserveAspect;
				background.fillCenter = categoryHeaderBackgroundForPass.fillCenter;
				background.pixelsPerUnitMultiplier = categoryHeaderBackgroundForPass.pixelsPerUnitMultiplier;
				((Graphic)background).color = ((Graphic)categoryHeaderBackgroundForPass).canvasRenderer.GetColor();
			}
			else
			{
				background.sprite = null;
				background.overrideSprite = null;
				((Graphic)background).material = null;
				background.type = (Type)0;
				((Graphic)background).color = new Color(0.2f, 0.2f, 0.2f, 0.7f);
			}
			((Graphic)background).raycastTarget = false;
			RectTransform iconRect = categoryCardView.IconRect;
			iconRect.anchorMin = new Vector2(0f, 0.5f);
			iconRect.anchorMax = new Vector2(0f, 0.5f);
			iconRect.pivot = new Vector2(0f, 0.5f);
			iconRect.anchoredPosition = new Vector2(8f, 0f);
			iconRect.sizeDelta = new Vector2(56f, 56f);
			Image icon = categoryCardView.Icon;
			icon.sprite = representative.m_icon;
			icon.preserveAspect = true;
			((Graphic)icon).color = Color.white;
			((Graphic)icon).raycastTarget = false;
			RectTransform labelRect = categoryCardView.LabelRect;
			labelRect.anchorMin = Vector2.zero;
			labelRect.anchorMax = Vector2.one;
			labelRect.offsetMin = new Vector2(66f, 6f);
			labelRect.offsetMax = new Vector2(-7f, -6f);
			TextMeshProUGUI label = categoryCardView.Label;
			((TMP_Text)label).text = text.ToUpperInvariant();
			((TMP_Text)label).font = (((Object)(object)hud.m_pieceDescription != (Object)null) ? hud.m_pieceDescription.font : null);
			((TMP_Text)label).fontSize = 12.8f;
			((TMP_Text)label).fontSizeMin = 9.5f;
			((TMP_Text)label).fontSizeMax = 12.8f;
			((TMP_Text)label).enableAutoSizing = true;
			((TMP_Text)label).fontStyle = (FontStyles)1;
			((Graphic)label).color = new Color(0.84f, 0.69f, 0.43f, 1f);
			((TMP_Text)label).alignment = (TextAlignmentOptions)4097;
			((TMP_Text)label).textWrappingMode = (TextWrappingModes)0;
			((TMP_Text)label).overflowMode = (TextOverflowModes)1;
			((TMP_Text)label).outlineWidth = 0.12f;
			((TMP_Text)label).outlineColor = new Color32((byte)18, (byte)12, (byte)8, (byte)245);
			((Graphic)label).raycastTarget = false;
		}

		private static CategoryCardView AcquireCategoryCard(Hud hud)
		{
			//IL_0063: Unknown result type (might be due to invalid IL or missing references)
			//IL_0069: Expected O, but got Unknown
			//IL_0081: Unknown result type (might be due to invalid IL or missing references)
			//IL_0087: Expected O, but got Unknown
			//IL_00a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ea: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f1: Expected O, but got Unknown
			//IL_011d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0122: Unknown result type (might be due to invalid IL or missing references)
			//IL_012f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0135: Unknown result type (might be due to invalid IL or missing references)
			//IL_013c: Expected O, but got Unknown
			EnsureDecorationPoolOwner(hud);
			CategoryCardView categoryCardView = ((_usedCategoryCards < CategoryCardPool.Count) ? CategoryCardPool[_usedCategoryCards] : null);
			if (categoryCardView == null || (Object)(object)categoryCardView.Root == (Object)null)
			{
				GameObject val = new GameObject("InventoryUX_CraftingCategoryPool", new Type[2]
				{
					typeof(RectTransform),
					typeof(Image)
				});
				val.transform.SetParent((Transform)(object)hud.m_pieceListRoot, false);
				RectTransform val2 = (RectTransform)val.transform;
				Image component = val.GetComponent<Image>();
				AddRectBorder(val2, new Color(0.68f, 0.5f, 0.25f, 0.68f));
				GameObject val3 = new GameObject("InventoryUX_CraftingCategoryIcon", new Type[2]
				{
					typeof(RectTransform),
					typeof(Image)
				});
				val3.transform.SetParent((Transform)(object)val2, false);
				RectTransform iconRect = (RectTransform)val3.transform;
				Image component2 = val3.GetComponent<Image>();
				GameObject val4 = new GameObject("InventoryUX_CraftingCategoryLabel", new Type[2]
				{
					typeof(RectTransform),
					typeof(TextMeshProUGUI)
				});
				val4.transform.SetParent((Transform)(object)val2, false);
				RectTransform labelRect = (RectTransform)val4.transform;
				TextMeshProUGUI component3 = val4.GetComponent<TextMeshProUGUI>();
				categoryCardView = new CategoryCardView(val, val2, component, iconRect, component2, labelRect, component3);
				if (_usedCategoryCards < CategoryCardPool.Count)
				{
					CategoryCardPool[_usedCategoryCards] = categoryCardView;
				}
				else
				{
					CategoryCardPool.Add(categoryCardView);
				}
			}
			categoryCardView.Root.SetActive(true);
			_usedCategoryCards++;
			return categoryCardView;
		}

		private static Image? FindVanillaCategoryHeaderBackground(Hud hud)
		{
			//IL_0054: 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_005b: 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_0076: Unknown result type (might be due to invalid IL or missing references)
			//IL_0084: Unknown result type (might be due to invalid IL or missing references)
			Image result = null;
			float num = float.MaxValue;
			GameObject[] pieceCategoryTabs = hud.m_pieceCategoryTabs;
			foreach (GameObject val in pieceCategoryTabs)
			{
				if ((Object)(object)val == (Object)null || !val.activeInHierarchy)
				{
					continue;
				}
				Image val2 = val.GetComponent<Image>() ?? val.GetComponentInChildren<Image>(true);
				if ((Object)(object)val2 == (Object)null)
				{
					continue;
				}
				Color color = ((Graphic)val2).canvasRenderer.GetColor();
				if (!(color.a <= 0.05f))
				{
					float num2 = color.r * 0.2126f + color.g * 0.7152f + color.b * 0.0722f;
					if (num2 < num)
					{
						result = val2;
						num = num2;
					}
				}
			}
			return result;
		}

		private static void AddRowSeparator(Hud hud, RectTransform templateRect, int row)
		{
			AddRowSeparator(hud, templateRect, row, HammerGridDimensions.CraftingRowPitch(hud));
		}

		private static void AddRowSeparator(Hud hud, RectTransform templateRect, int row, float rowPitch)
		{
			AddRowSeparator(hud, templateRect, row, rowPitch, 0f);
		}

		private static void AddRowSeparator(Hud hud, RectTransform templateRect, int row, float rowPitch, float startX)
		{
			//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_0036: 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_0042: 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_0057: 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_0094: 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)
			float pieceIconSpacing = hud.m_pieceIconSpacing;
			Image obj = AcquireDecorationLine(hud, "InventoryUX_CraftingRowSeparator_" + row);
			((Component)obj).transform.SetAsLastSibling();
			RectTransform val = (RectTransform)((Component)obj).transform;
			val.anchorMin = templateRect.anchorMin;
			val.anchorMax = templateRect.anchorMax;
			val.pivot = new Vector2(0f, 0.5f);
			val.anchoredPosition = new Vector2(startX, (0f - ((float)row + 1f)) * rowPitch + 3.5f);
			val.sizeDelta = new Vector2(15f * pieceIconSpacing - 9f - startX, 1f);
			((Graphic)obj).color = new Color(0.57f, 0.4f, 0.19f, 0.34f);
			((Graphic)obj).raycastTarget = false;
		}

		private static void AddSubgroupSeparator(Hud hud, RectTransform templateRect, SubgroupDivider divider, float rowPitch)
		{
			//IL_0074: Unknown result type (might be due to invalid IL or missing references)
			//IL_0079: Unknown result type (might be due to invalid IL or missing references)
			//IL_007b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0085: Unknown result type (might be due to