Decompiled source of CraftIndex v0.5.8

CraftIndex.dll

Decompiled 3 weeks ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Reflection.Emit;
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.Patches;
using InventoryUX.Runtime;
using JG224.ModCore.API;
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.5.8.0")]
[assembly: AssemblyInformationalVersion("0.5.8+cb667c9207a6221a43d39bf751af8ab33fc5035e")]
[assembly: AssemblyProduct("CraftIndex")]
[assembly: AssemblyTitle("CraftIndex")]
[assembly: AssemblyVersion("0.5.8.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.5.8")]
	[BepInDependency("com.jg224.modcore", "0.5.0")]
	public sealed class Plugin : BaseUnityPlugin
	{
		internal const string PluginGuid = "com.inventoryux.valheim";

		internal const string PluginName = "CraftIndex";

		internal const string PluginVersion = "0.5.8";

		internal const string ModCoreGuid = "com.jg224.modcore";

		internal const int ProtocolVersion = 1;

		internal static readonly ModuleId ModuleId = new ModuleId("craftindex");

		private readonly List<IDisposable> _registrations = new List<IDisposable>();

		private Harmony? _harmony;

		private bool _shutDown;

		internal static ManualLogSource LogInstance { get; private set; } = null;

		internal static Plugin Instance { get; private set; } = null;

		internal static ICoreServices Core { get; private set; } = null;

		private void Awake()
		{
			//IL_02bc: Unknown result type (might be due to invalid IL or missing references)
			//IL_0056: Unknown result type (might be due to invalid IL or missing references)
			//IL_0065: Unknown result type (might be due to invalid IL or missing references)
			//IL_006d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0077: Expected O, but got Unknown
			//IL_008c: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cf: Expected O, but got Unknown
			//IL_0121: Unknown result type (might be due to invalid IL or missing references)
			//IL_0154: Unknown result type (might be due to invalid IL or missing references)
			//IL_015e: Expected O, but got Unknown
			//IL_0187: Unknown result type (might be due to invalid IL or missing references)
			//IL_0196: Unknown result type (might be due to invalid IL or missing references)
			//IL_019b: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ba: Expected O, but got Unknown
			//IL_01cf: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e9: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f3: Expected O, but got Unknown
			//IL_0208: Unknown result type (might be due to invalid IL or missing references)
			//IL_021d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0227: Expected O, but got Unknown
			//IL_0232: Unknown result type (might be due to invalid IL or missing references)
			//IL_023c: Expected O, but got Unknown
			//IL_026b: Unknown result type (might be due to invalid IL or missing references)
			Instance = this;
			LogInstance = ((BaseUnityPlugin)this).Logger;
			try
			{
				if (!ModCoreApi.IsAvailable)
				{
					throw new InvalidOperationException("ModCore did not initialize before CraftIndex.");
				}
				SemanticVersion val = default(SemanticVersion);
				if (!SemanticVersion.TryParse("0.5.8", ref val))
				{
					throw new InvalidOperationException("CraftIndex has an invalid plugin version.");
				}
				Core = ModCoreApi.Services;
				_registrations.Add(Core.Modules.Register(new ModuleDescriptor(ModuleId, "com.inventoryux.valheim", "CraftIndex", val, 1, (ModuleSide)1, (ModuleRequirement)1, 0uL, 1, 1)));
				_registrations.Add(Core.Namespaces.Register(ModuleId, (NamespaceKind)8, "craftindex.", 1, Array.Empty<string>()));
				_registrations.Add(Core.Ui.Reserve(new UiReservation(ModuleId, (UiSurface)4, "crafting-and-hammer-organization", 20, false)));
				ModConfig.Bind(ConfigFileMigration.Open((BaseUnityPlugin)(object)this, Paths.ConfigPath, ((BaseUnityPlugin)this).Logger));
				foreach (KeyValuePair<ConfigDefinition, ConfigEntryBase> item in ModConfig.File)
				{
					ConfigEntryBase entry = item.Value;
					_registrations.Add(Core.Configuration.Register(new ConfigSettingDescriptor(ModuleId, entry.Definition.Section, entry.Definition.Key, (ConfigScope)1, (Func<string>)(() => Convert.ToString(entry.BoxedValue, CultureInfo.InvariantCulture) ?? string.Empty), 1)));
				}
				_registrations.Add(Core.Input.Register(new InputActionDescriptor(ModuleId, "hammer-favorite", ((object)ModConfig.FavoriteHotkey.Value/*cast due to .constrained prefix*/).ToString(), "build menu", 0)));
				_registrations.Add(Core.Input.Register(new InputActionDescriptor(ModuleId, "hammer-controller-favorite", ModConfig.ControllerFavoriteButton.Value, "build menu", 0)));
				_registrations.Add(Core.Input.Register(new InputActionDescriptor(ModuleId, "hammer-pages", "PageUp / PageDown", "build menu", 0)));
				_harmony = new Harmony("com.inventoryux.valheim");
				SearchInputBlocker.Initialize(_harmony);
				_harmony.PatchAll(typeof(Plugin).Assembly);
				Core.Modules.SetState(ModuleId, (ModuleRuntimeState)2, "Client-local Hammer and crafting UI hooks ready.");
				((BaseUnityPlugin)this).Logger.LogInfo((object)"CraftIndex 0.5.8 loaded. Undiscovered content is never rendered.");
			}
			catch (Exception ex)
			{
				((BaseUnityPlugin)this).Logger.LogError((object)string.Format("{0} failed to initialize safely: {1}", "CraftIndex", ex));
				if (Core != null)
				{
					Core.Modules.SetState(ModuleId, (ModuleRuntimeState)5, ex.Message);
				}
				Shutdown();
				throw;
			}
		}

		private void OnDestroy()
		{
			Shutdown();
		}

		private void Update()
		{
			if (_shutDown)
			{
				return;
			}
			try
			{
				BuildMenuBridge.Tick();
				HammerPaging.Tick();
			}
			catch (Exception exception)
			{
				HammerPatchHealth.Decoration.Trip(exception);
			}
		}

		private void Shutdown()
		{
			//IL_01a6: Unknown result type (might be due to invalid IL or missing references)
			if (!_shutDown)
			{
				_shutDown = true;
				Cleanup("build menu routing", BuildMenuBridge.Shutdown);
				Cleanup("snap-point memory", HammerSnapMemory.Reset);
				Cleanup("Hammer UI", HammerGroupDecorations.Shutdown);
				Cleanup("Hammer sizing", HammerGridSizer.Restore);
				Cleanup("Hammer caches", HammerOrganizer.Reset);
				Cleanup("recipe UI", RecipeOrganizer.Shutdown);
				Cleanup("search input blocker", SearchInputBlocker.Shutdown);
				Cleanup("food cache", FoodStatsResolver.Reset);
				Harmony? harmony = _harmony;
				if (harmony != null)
				{
					harmony.UnpatchSelf();
				}
				_harmony = null;
				for (int num = _registrations.Count - 1; num >= 0; num--)
				{
					Cleanup("ModCore registration", _registrations[num].Dispose);
				}
				_registrations.Clear();
				if (Core != null)
				{
					Core.Metrics.RemoveOwner(ModuleId);
				}
				Core = null;
				Instance = null;
				LogInstance = null;
			}
		}

		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 static class BuildMenuBridge
	{
		private sealed class TableCategories
		{
			internal readonly List<PieceCategory> Values;

			internal readonly List<string> Labels;

			internal TableCategories(PieceTable table)
			{
				Values = new List<PieceCategory>(table.m_categories);
				Labels = new List<string>(table.m_categoryLabels);
			}
		}

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

			public static UnityAction <>9__31_0;

			internal void <EnsureNativeControl>b__31_0()
			{
				Player localPlayer = Player.m_localPlayer;
				PieceTable val = ((localPlayer != null) ? localPlayer.GetBuildTool() : null);
				if (ModConfig.Enabled.Value && (Object)(object)val != (Object)null && ToolViewPreferences.UsesToolPreferences(((Object)((Component)val).gameObject).name))
				{
					SetToolView(organized: true);
				}
				else
				{
					SetEnabled(!ModConfig.Enabled.Value);
				}
			}
		}

		private static readonly MethodInfo UpdateBuild = AccessTools.Method(typeof(Hud), "UpdateBuild", (Type[])null, (Type[])null);

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

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

		private static readonly Dictionary<PieceTable, TableCategories> Categories = new Dictionary<PieceTable, TableCategories>();

		private static GameObject? _nativeControl;

		private static BuildUi? _nativeControlOwner;

		private static TextMeshProUGUI? _nativeLabel;

		private static PieceTable? _activeTool;

		private static string _toolViewSettings = string.Empty;

		private static Hud? _hud;

		private static GameObject[]? _originalTabs;

		private static bool _enabled = true;

		private static int _openedFrame;

		private static ulong _categorySignature;

		private static PieceTable? _categoryTable;

		internal static bool OwnsMenu
		{
			get
			{
				//IL_0049: Unknown result type (might be due to invalid IL or missing references)
				//IL_004e: Unknown result type (might be due to invalid IL or missing references)
				if (ModConfig.Enabled.Value && (Object)(object)Player.m_localPlayer != (Object)null && (Object)(object)Player.m_localPlayer.GetBuildTool() != (Object)null)
				{
					return ModConfig.GetToolModView(((Object)((Component)Player.m_localPlayer.GetBuildTool()).gameObject).name, ((object)Player.m_localPlayer.GetBuildTool().GetSelectedCategory()/*cast due to .constrained prefix*/).ToString());
				}
				return false;
			}
		}

		internal static bool IsOpen
		{
			get
			{
				if ((Object)(object)Hud.instance != (Object)null && (Object)(object)Hud.instance.m_pieceSelectionWindow != (Object)null)
				{
					return Hud.instance.m_pieceSelectionWindow.activeSelf;
				}
				return false;
			}
		}

		internal static bool HasOwnedTabs(Hud hud)
		{
			if ((Object)(object)hud == (Object)(object)_hud && _originalTabs != null)
			{
				return hud.m_pieceCategoryTabs != _originalTabs;
			}
			return false;
		}

		internal static bool BuildVisibility(GameObject nativeMenu)
		{
			if (!OwnsMenu)
			{
				return nativeMenu.activeSelf;
			}
			return IsOpen;
		}

		internal static void Open()
		{
			Hud instance = Hud.instance;
			Player localPlayer = Player.m_localPlayer;
			if (!((Object)(object)instance == (Object)null) && !((Object)(object)localPlayer == (Object)null) && ((Character)localPlayer).InPlaceMode())
			{
				PrepareTool(localPlayer.GetBuildTool());
				instance.m_buildUi.Close();
				UpdateAvailable.Invoke(localPlayer, null);
				EnsureCategories(instance, localPlayer.GetBuildTool());
				instance.m_pieceSelectionWindow.SetActive(true);
				_openedFrame = Time.frameCount;
				UpdateBuild.Invoke(instance, new object[2] { localPlayer, true });
			}
		}

		internal static void Close()
		{
			HammerMenuInput.ConsumeClose(IsOpen, Player.m_localPlayer);
			HammerGroupDecorations.ReleaseSearchFocus();
			if ((Object)(object)Hud.instance != (Object)null && (Object)(object)Hud.instance.m_pieceSelectionWindow != (Object)null)
			{
				Hud.instance.m_pieceSelectionWindow.SetActive(false);
			}
		}

		internal static void SetEnabled(bool enabled)
		{
			ModConfig.Enabled.Value = enabled;
			ModConfig.File.Save();
			ApplyEnabledChange();
		}

		internal static void SetToolView(bool organized)
		{
			//IL_003a: 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)
			Player localPlayer = Player.m_localPlayer;
			PieceTable val = ((localPlayer != null) ? localPlayer.GetBuildTool() : null);
			if (!((Object)(object)val == (Object)null) && ToolViewPreferences.UsesToolPreferences(((Object)((Component)val).gameObject).name))
			{
				ModConfig.SetToolModView(((Object)((Component)val).gameObject).name, ((object)val.GetSelectedCategory()/*cast due to .constrained prefix*/).ToString(), organized);
				ApplyToolViewChange();
			}
		}

		private static void ApplyToolViewChange()
		{
			string value = ModConfig.HammerToolViews.Value;
			if (_toolViewSettings == value)
			{
				return;
			}
			_toolViewSettings = value;
			Hud instance = Hud.instance;
			Player localPlayer = Player.m_localPlayer;
			PieceTable val = ((localPlayer != null) ? localPlayer.GetBuildTool() : null);
			if ((Object)(object)instance == (Object)null || (Object)(object)val == (Object)null || !ToolViewPreferences.UsesToolPreferences(((Object)((Component)val).gameObject).name))
			{
				return;
			}
			bool flag = IsOpen || ((Component)instance.m_buildUi).gameObject.activeSelf;
			Piece selectedPiece = val.GetSelectedPiece();
			Close();
			instance.m_buildUi.Close();
			ReleaseToolLayout();
			UpdateAvailable.Invoke(localPlayer, null);
			if ((Object)(object)selectedPiece != (Object)null)
			{
				localPlayer.SetSelectedPiece(selectedPiece);
			}
			if (flag && ((Character)localPlayer).InPlaceMode())
			{
				if (OwnsMenu)
				{
					Open();
				}
				else
				{
					instance.m_buildUi.OpenBuildMenu();
				}
			}
		}

		internal static void PrepareTool(PieceTable? table)
		{
			if (!((Object)(object)_activeTool == (Object)(object)table))
			{
				Close();
				ReleaseToolLayout();
				_activeTool = table;
			}
		}

		private static void ReleaseToolLayout()
		{
			HammerGroupDecorations.Shutdown();
			HammerRequirementLabels.Restore();
			HammerGridSizer.Restore();
			HammerOrganizer.Reset();
			RestoreCategories();
		}

		private static void ApplyEnabledChange()
		{
			if (_enabled == ModConfig.Enabled.Value)
			{
				return;
			}
			Hud instance = Hud.instance;
			Player localPlayer = Player.m_localPlayer;
			bool num = (Object)(object)instance != (Object)null && (IsOpen || ((Component)instance.m_buildUi).gameObject.activeSelf);
			object obj;
			if (!((Object)(object)localPlayer == (Object)null))
			{
				PieceTable buildTool = localPlayer.GetBuildTool();
				obj = ((buildTool != null) ? buildTool.GetSelectedPiece() : null);
			}
			else
			{
				obj = null;
			}
			Piece val = (Piece)obj;
			_enabled = ModConfig.Enabled.Value;
			Close();
			if ((Object)(object)instance != (Object)null)
			{
				instance.m_buildUi.Close();
			}
			HammerGroupDecorations.Shutdown();
			HammerRequirementLabels.Restore();
			HammerGridSizer.Restore();
			HammerOrganizer.Reset();
			HammerSnapMemory.Reset();
			if ((Object)(object)InventoryGui.instance != (Object)null)
			{
				RecipeOrganizer.Release(InventoryGui.instance);
				if (_enabled && ModConfig.OrganizeRecipes.Value)
				{
					RecipeOrganizer.Organize(InventoryGui.instance);
				}
			}
			RestoreCategories();
			if ((Object)(object)localPlayer != (Object)null && (Object)(object)localPlayer.GetBuildTool() != (Object)null)
			{
				UpdateAvailable.Invoke(localPlayer, null);
				if ((Object)(object)val != (Object)null)
				{
					localPlayer.SetSelectedPiece(val);
				}
			}
			if (num && (Object)(object)localPlayer != (Object)null && ((Character)localPlayer).InPlaceMode() && (Object)(object)instance != (Object)null)
			{
				if (OwnsMenu)
				{
					Open();
				}
				else
				{
					instance.m_buildUi.OpenBuildMenu();
				}
			}
		}

		internal static void Tick()
		{
			ApplyEnabledChange();
			ApplyToolViewChange();
			Hud instance = Hud.instance;
			if ((Object)(object)instance == (Object)null)
			{
				return;
			}
			Player localPlayer = Player.m_localPlayer;
			PrepareTool((localPlayer != null) ? localPlayer.GetBuildTool() : null);
			EnsureNativeControl(instance);
			if (!IsOpen)
			{
				return;
			}
			Player localPlayer2 = Player.m_localPlayer;
			if ((Object)(object)localPlayer2 == (Object)null || !((Character)localPlayer2).InPlaceMode() || ((Character)localPlayer2).IsTeleporting())
			{
				Close();
				return;
			}
			if (!OwnsMenu)
			{
				Close();
				ReleaseToolLayout();
				instance.m_buildUi.OpenBuildMenu();
				return;
			}
			EnsureCategories(instance, localPlayer2.GetBuildTool());
			if (Time.frameCount == _openedFrame || UnifiedPopup.IsVisible() || Console.IsVisible() || Menu.IsVisible() || TextInput.IsVisible() || ((Object)(object)Chat.instance != (Object)null && Chat.instance.HasFocus()) || HammerGroupDecorations.IsSearchFocused)
			{
				return;
			}
			if (ZInput.GetKeyDown((KeyCode)27, true) || ZInput.GetButtonDown("JoyButtonB") || (!ZInput.IsGamepadActive() && ZInput.GetButtonDown("BuildMenu")))
			{
				Close();
				PlayerController.SetTakeInputDelay(0.2f);
				return;
			}
			PieceTable buildTool = localPlayer2.GetBuildTool();
			bool flag = false;
			if (ZInput.GetButtonDown("TabLeft") || ZInput.GetButtonDown("JoyTabLeft"))
			{
				buildTool.PrevCategory();
				flag = true;
			}
			if (ZInput.GetButtonDown("TabRight") || ZInput.GetButtonDown("JoyTabRight"))
			{
				buildTool.NextCategory();
				flag = true;
			}
			if (ZInput.GetButtonDown("JoyDPadLeft"))
			{
				buildTool.LeftPiece();
				flag = true;
			}
			if (ZInput.GetButtonDown("JoyDPadRight"))
			{
				buildTool.RightPiece();
				flag = true;
			}
			if (ZInput.GetButtonDown("JoyDPadUp"))
			{
				buildTool.UpPiece();
				flag = true;
			}
			if (ZInput.GetButtonDown("JoyDPadDown"))
			{
				buildTool.DownPiece();
				flag = true;
			}
			if (flag)
			{
				SetupPlacementGhost.Invoke(localPlayer2, null);
				HammerPaging.RefreshNative(instance, buildTool);
			}
			if (ZInput.GetButtonDown("JoyButtonA"))
			{
				Close();
				PlayerController.SetTakeInputDelay(0.2f);
			}
		}

		private static void EnsureNativeControl(Hud hud)
		{
			//IL_00aa: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b4: Expected O, but got Unknown
			//IL_00de: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e4: Expected O, but got Unknown
			//IL_0120: Unknown result type (might be due to invalid IL or missing references)
			//IL_018b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0190: Unknown result type (might be due to invalid IL or missing references)
			//IL_0191: Unknown result type (might be due to invalid IL or missing references)
			//IL_019b: Unknown result type (might be due to invalid IL or missing references)
			//IL_019c: 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)
			//IL_01a7: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ac: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ad: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_014d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0152: Unknown result type (might be due to invalid IL or missing references)
			//IL_0158: Expected O, but got Unknown
			if ((Object)(object)hud.m_buildUi == (Object)null || !((Component)hud.m_buildUi).gameObject.activeSelf)
			{
				return;
			}
			if ((Object)(object)_nativeControl != (Object)null && (Object)(object)_nativeControlOwner == (Object)(object)hud.m_buildUi)
			{
				UpdateNativeLabel();
				return;
			}
			RectTransform val = NativeBuildMenuControlLayout.Parent(((Component)hud.m_buildUi).transform);
			if ((Object)(object)val == (Object)null)
			{
				return;
			}
			if ((Object)(object)_nativeControl != (Object)null)
			{
				Object.Destroy((Object)(object)_nativeControl);
			}
			_nativeControl = new GameObject("CraftIndex_Enable", new Type[3]
			{
				typeof(RectTransform),
				typeof(Image),
				typeof(Button)
			});
			_nativeControlOwner = hud.m_buildUi;
			_nativeControl.layer = ((Component)val).gameObject.layer;
			RectTransform val2 = (RectTransform)_nativeControl.transform;
			((Transform)val2).SetParent((Transform)(object)val, false);
			NativeBuildMenuControlLayout.Apply(val2);
			_nativeControl.AddComponent<LayoutElement>().ignoreLayout = true;
			((Graphic)_nativeControl.GetComponent<Image>()).color = new Color(0.2f, 0.15f, 0.1f, 0.96f);
			ButtonClickedEvent onClick = _nativeControl.GetComponent<Button>().onClick;
			object obj = <>c.<>9__31_0;
			if (obj == null)
			{
				UnityAction val3 = delegate
				{
					Player localPlayer = Player.m_localPlayer;
					PieceTable val5 = ((localPlayer != null) ? localPlayer.GetBuildTool() : null);
					if (ModConfig.Enabled.Value && (Object)(object)val5 != (Object)null && ToolViewPreferences.UsesToolPreferences(((Object)((Component)val5).gameObject).name))
					{
						SetToolView(organized: true);
					}
					else
					{
						SetEnabled(!ModConfig.Enabled.Value);
					}
				};
				<>c.<>9__31_0 = val3;
				obj = (object)val3;
			}
			((UnityEvent)onClick).AddListener((UnityAction)obj);
			TextMeshProUGUI obj2 = CraftIndexTextFactory.Create("CraftIndex_EnableLabel", (Transform)(object)val2, (Component)(object)hud, hud.m_pieceDescription);
			((Component)obj2).gameObject.layer = ((Component)val).gameObject.layer;
			RectTransform val4 = (RectTransform)((TMP_Text)obj2).transform;
			val4.anchorMin = Vector2.zero;
			val4.anchorMax = Vector2.one;
			Vector2 offsetMin = (val4.offsetMax = Vector2.zero);
			val4.offsetMin = offsetMin;
			_nativeLabel = obj2;
			UpdateNativeLabel();
			((TMP_Text)obj2).fontSize = 15f;
			((TMP_Text)obj2).alignment = (TextAlignmentOptions)514;
			((Graphic)obj2).raycastTarget = false;
		}

		private static void UpdateNativeLabel()
		{
			if (!((Object)(object)_nativeLabel == (Object)null))
			{
				Player localPlayer = Player.m_localPlayer;
				PieceTable val = ((localPlayer != null) ? localPlayer.GetBuildTool() : null);
				string text = ((ModConfig.Enabled.Value && (Object)(object)val != (Object)null && ToolViewPreferences.UsesToolPreferences(((Object)((Component)val).gameObject).name)) ? "MOD VIEW" : (ModConfig.Enabled.Value ? "CRAFTINDEX: ON" : "CRAFTINDEX: OFF"));
				if (((TMP_Text)_nativeLabel).text != text)
				{
					((TMP_Text)_nativeLabel).text = text;
				}
			}
		}

		private static void EnsureCategories(Hud hud, PieceTable table)
		{
			//IL_006c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0071: Unknown result type (might be due to invalid IL or missing references)
			//IL_008b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0091: Invalid comparison between Unknown and I4
			//IL_009b: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e6: Invalid comparison between Unknown and I4
			//IL_00f1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fe: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d6: Unknown result type (might be due to invalid IL or missing references)
			//IL_01dd: Invalid comparison between Unknown and I4
			//IL_024e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0159: Unknown result type (might be due to invalid IL or missing references)
			//IL_0166: Unknown result type (might be due to invalid IL or missing references)
			//IL_0272: Unknown result type (might be due to invalid IL or missing references)
			//IL_0279: Invalid comparison between Unknown and I4
			//IL_02f4: Unknown result type (might be due to invalid IL or missing references)
			//IL_0301: Unknown result type (might be due to invalid IL or missing references)
			//IL_0306: Unknown result type (might be due to invalid IL or missing references)
			//IL_0318: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ab: Unknown result type (might be due to invalid IL or missing references)
			//IL_0323: Unknown result type (might be due to invalid IL or missing references)
			//IL_0326: Unknown result type (might be due to invalid IL or missing references)
			//IL_032d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0337: Unknown result type (might be due to invalid IL or missing references)
			//IL_04cc: Unknown result type (might be due to invalid IL or missing references)
			//IL_04f7: Unknown result type (might be due to invalid IL or missing references)
			//IL_050d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0517: Unknown result type (might be due to invalid IL or missing references)
			//IL_052f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0539: Unknown result type (might be due to invalid IL or missing references)
			//IL_0544: Unknown result type (might be due to invalid IL or missing references)
			//IL_0558: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)table == (Object)null || !HammerCategoryRouting.IsApplied(table))
			{
				RestoreTabs();
				return;
			}
			ulong availableLayoutSignature = HammerOrganizer.GetAvailableLayoutSignature(table);
			if ((Object)(object)_categoryTable == (Object)(object)table && _categorySignature == availableLayoutSignature && (Object)(object)_hud == (Object)(object)hud)
			{
				return;
			}
			_categoryTable = table;
			_categorySignature = availableLayoutSignature;
			if (!Categories.ContainsKey(table))
			{
				Categories.Add(table, new TableCategories(table));
			}
			PieceCategory val = HammerCategoryRouting.SeasonalCategory(table);
			for (int num = table.m_categories.Count - 1; num >= 0; num--)
			{
				if ((int)table.m_categories[num] == 5 || table.m_categories[num] == val)
				{
					table.m_categories.RemoveAt(num);
					if (num < table.m_categoryLabels.Count)
					{
						table.m_categoryLabels.RemoveAt(num);
					}
				}
			}
			for (int i = 0; i < 9; i++)
			{
				PieceCategory val2 = (PieceCategory)i;
				if ((int)val2 == 5 || table.m_categories.Contains(val2))
				{
					continue;
				}
				bool flag = false;
				foreach (Piece layoutPiece in HammerOrganizer.GetLayoutPieces(table, val2))
				{
					if ((Object)(object)layoutPiece != (Object)null && !layoutPiece.m_repairPiece && !layoutPiece.m_removePiece)
					{
						flag = true;
						break;
					}
				}
				if (flag)
				{
					table.m_categories.Add(val2);
					table.m_categoryLabels.Add(CategoryLabel(val2));
				}
			}
			int num2 = table.m_categories.IndexOf((PieceCategory)2);
			if (num2 >= 0 && num2 < table.m_categoryLabels.Count)
			{
				table.m_categoryLabels[num2] = "Wood";
			}
			foreach (Piece layoutPiece2 in HammerOrganizer.GetLayoutPieces(table, (PieceCategory)5))
			{
				if (!((Object)(object)layoutPiece2 == (Object)null) && (int)layoutPiece2.m_category != 100 && !layoutPiece2.m_repairPiece && !layoutPiece2.m_removePiece)
				{
					int index = ((num2 >= 0) ? (num2 + 1) : table.m_categories.Count);
					table.m_categories.Insert(index, (PieceCategory)5);
					table.m_categoryLabels.Insert(index, "Wood(2)");
					break;
				}
			}
			int num3 = table.m_categories.IndexOf((PieceCategory)4);
			foreach (Piece layoutPiece3 in HammerOrganizer.GetLayoutPieces(table, val))
			{
				if (!((Object)(object)layoutPiece3 == (Object)null) && (int)layoutPiece3.m_category != 100 && !layoutPiece3.m_repairPiece && !layoutPiece3.m_removePiece)
				{
					int index2 = ((num3 >= 0) ? (num3 + 1) : table.m_categories.Count);
					table.m_categories.Insert(index2, val);
					table.m_categoryLabels.Insert(index2, "Seasonal");
					break;
				}
			}
			if (table.m_categories.Count > 0 && !table.m_categories.Contains(table.GetSelectedCategory()))
			{
				PieceCategory category = (PieceCategory)((table.GetSelectedCategory() == val && num3 >= 0) ? 4 : ((num2 >= 0) ? 2 : ((int)table.m_categories[0])));
				table.SetCategory(category);
				HammerGroupDecorations.PrepareHammerSearchCategory(category, force: true);
				table.SetSelected(Vector2Int.zero);
				Player localPlayer = Player.m_localPlayer;
				if ((Object)(object)localPlayer != (Object)null && (Object)(object)localPlayer.GetBuildTool() == (Object)(object)table)
				{
					HammerGroupDecorations.TrySelectRepair(localPlayer);
					SetupPlacementGhost.Invoke(localPlayer, null);
				}
			}
			if ((Object)(object)_hud != (Object)(object)hud)
			{
				RestoreTabs();
				_hud = hud;
				_originalTabs = hud.m_pieceCategoryTabs;
			}
			if (_originalTabs.Length == 0)
			{
				return;
			}
			List<GameObject> list = ((hud.m_pieceCategoryTabs != _originalTabs) ? new List<GameObject>(hud.m_pieceCategoryTabs) : new List<GameObject>());
			GameObject[] originalTabs = _originalTabs;
			for (int j = 0; j < originalTabs.Length; j++)
			{
				originalTabs[j].SetActive(false);
			}
			while (list.Count < table.m_categories.Count)
			{
				int index3 = list.Count;
				GameObject val3 = Object.Instantiate<GameObject>(_originalTabs[0], _originalTabs[0].transform.parent);
				((Object)val3).name = "CraftIndex_Category_" + index3;
				val3.GetComponent<UIInputHandler>().m_onLeftDown = delegate
				{
					if ((Object)(object)Player.m_localPlayer != (Object)null)
					{
						Player.m_localPlayer.SetBuildCategory(index3);
					}
				};
				list.Add(val3);
			}
			hud.m_pieceCategoryTabs = list.ToArray();
			for (int num4 = 0; num4 < list.Count; num4++)
			{
				list[num4].SetActive(num4 < table.m_categories.Count);
				if (num4 < table.m_categories.Count)
				{
					RectTransform val4 = (RectTransform)list[num4].transform;
					(list[num4].GetComponent<LayoutElement>() ?? list[num4].AddComponent<LayoutElement>()).ignoreLayout = true;
					val4.anchorMin = new Vector2((float)num4 / (float)table.m_categories.Count, 0f);
					val4.anchorMax = new Vector2((float)(num4 + 1) / (float)table.m_categories.Count, 1f);
					val4.offsetMin = new Vector2(2f, 0f);
					val4.offsetMax = new Vector2(-2f, 0f);
				}
			}
		}

		private unsafe static string CategoryLabel(PieceCategory category)
		{
			//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
			return (category - 2) switch
			{
				0 => "Wood", 
				3 => "Wood(2)", 
				4 => "Feasts", 
				5 => "Food", 
				6 => "Meads", 
				_ => ((object)(*(PieceCategory*)(&category))/*cast due to .constrained prefix*/).ToString(), 
			};
		}

		internal static void RestoreCategories(PieceTable table)
		{
			if (Categories.TryGetValue(table, out TableCategories value))
			{
				table.m_categories.Clear();
				table.m_categories.AddRange(value.Values);
				table.m_categoryLabels.Clear();
				table.m_categoryLabels.AddRange(value.Labels);
				Categories.Remove(table);
				_categoryTable = null;
				_categorySignature = 0uL;
			}
		}

		private static void RestoreCategories()
		{
			foreach (PieceTable item in new List<PieceTable>(Categories.Keys))
			{
				if ((Object)(object)item != (Object)null)
				{
					RestoreCategories(item);
				}
			}
			Categories.Clear();
			RestoreTabs();
			_categoryTable = null;
			_categorySignature = 0uL;
			if ((Object)(object)_nativeControl != (Object)null)
			{
				Object.Destroy((Object)(object)_nativeControl);
			}
			_nativeControl = null;
			_nativeControlOwner = null;
			_nativeLabel = null;
		}

		private static void RestoreTabs()
		{
			HammerCategoryHeader.Restore();
			if ((Object)(object)_hud != (Object)null && _originalTabs != null)
			{
				GameObject[] pieceCategoryTabs;
				if (_hud.m_pieceCategoryTabs != _originalTabs)
				{
					pieceCategoryTabs = _hud.m_pieceCategoryTabs;
					for (int i = 0; i < pieceCategoryTabs.Length; i++)
					{
						Object.Destroy((Object)(object)pieceCategoryTabs[i]);
					}
				}
				_hud.m_pieceCategoryTabs = _originalTabs;
				pieceCategoryTabs = _originalTabs;
				for (int i = 0; i < pieceCategoryTabs.Length; i++)
				{
					pieceCategoryTabs[i].SetActive(true);
				}
			}
			_hud = null;
			_originalTabs = null;
		}

		internal static void Shutdown()
		{
			Close();
			HammerRequirementLabels.Restore();
			RestoreCategories();
			_activeTool = null;
		}
	}
	internal static class ConfigFileMigration
	{
		internal const string CurrentFileName = "jg224.CraftIndex.cfg";

		internal const string LegacyFileName = "com.inventoryux.valheim.cfg";

		internal static ConfigFile Open(BaseUnityPlugin plugin, string configDirectory, ManualLogSource log)
		{
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: Expected O, but got Unknown
			if (MoveLegacy(configDirectory) && log != null)
			{
				log.LogInfo((object)"Renamed legacy config com.inventoryux.valheim.cfg to jg224.CraftIndex.cfg.");
			}
			return PluginConfigFiles.Attach(plugin, new ConfigFile(Path.Combine(configDirectory, "jg224.CraftIndex.cfg"), true, plugin.Info.Metadata));
		}

		internal static bool MoveLegacy(string configDirectory)
		{
			Directory.CreateDirectory(configDirectory);
			if (ExactPath(configDirectory, "jg224.CraftIndex.cfg") != null)
			{
				return false;
			}
			string text = ExactPath(configDirectory, "com.inventoryux.valheim.cfg");
			if (text == null)
			{
				return false;
			}
			string destFileName = Path.Combine(configDirectory, "jg224.CraftIndex.cfg");
			File.Move(text, destFileName);
			return true;
		}

		private static string? ExactPath(string directory, string fileName)
		{
			return Directory.EnumerateFiles(directory, "*.cfg", SearchOption.TopDirectoryOnly).FirstOrDefault((string path) => string.Equals(Path.GetFileName(path), fileName, StringComparison.Ordinal));
		}
	}
	internal static class CraftIndexTextFactory
	{
		internal static TextMeshProUGUI Create(string name, Transform parent, Component fontContext, TMP_Text? preferredFontSource)
		{
			//IL_004c: 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_0058: Unknown result type (might be due to invalid IL or missing references)
			//IL_006d: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)parent == (Object)null)
			{
				throw new ArgumentNullException("parent");
			}
			TMP_Text obj = ResolveFontSource(fontContext, preferredFontSource);
			TMP_FontAsset font = obj.font;
			Material val = obj.fontSharedMaterial;
			if ((Object)(object)val == (Object)null)
			{
				val = ((TMP_Asset)font).material;
			}
			GameObject val2 = new GameObject(name, new Type[1] { typeof(RectTransform) });
			val2.SetActive(false);
			TextMeshProUGUI val3 = val2.AddComponent<TextMeshProUGUI>();
			((TMP_Text)val3).fontSharedMaterial = val;
			((TMP_Text)val3).font = font;
			val2.SetActive(true);
			val2.transform.SetParent(parent, false);
			return val3;
		}

		private static TMP_Text ResolveFontSource(Component fontContext, TMP_Text? preferredFontSource)
		{
			if (HasUsableFont(preferredFontSource))
			{
				return preferredFontSource;
			}
			if ((Object)(object)fontContext != (Object)null)
			{
				TMP_Text[] componentsInChildren = fontContext.GetComponentsInChildren<TMP_Text>(true);
				foreach (TMP_Text val in componentsInChildren)
				{
					if (HasUsableFont(val))
					{
						return val;
					}
				}
			}
			throw new InvalidOperationException("CraftIndex could not find a loaded Valheim font asset for its generated UI.");
		}

		private static bool HasUsableFont(TMP_Text? candidate)
		{
			if ((Object)(object)candidate == (Object)null || (Object)(object)candidate.font == (Object)null)
			{
				return false;
			}
			if (!((Object)(object)candidate.fontSharedMaterial != (Object)null))
			{
				return (Object)(object)((TMP_Asset)candidate.font).material != (Object)null;
			}
			return true;
		}
	}
	internal static class CraftingLayoutMetadata
	{
		internal static CraftingPieceLayout Resolve(Piece piece)
		{
			if (ModConfig.TryGetGroupOverride(HammerOrganizer.GetPieceKey(piece), out var value) && Enum.TryParse<CraftingSection>(value.Label.Replace(" ", string.Empty), ignoreCase: true, out var result) && Enum.IsDefined(typeof(CraftingSection), result))
			{
				return new CraftingPieceLayout(result, value.Order, value.Subgroup);
			}
			CraftingStation component = ((Component)piece).GetComponent<CraftingStation>();
			StationExtension component2 = ((Component)piece).GetComponent<StationExtension>();
			string station = (((Object)(object)component != (Object)null) ? component.m_name : (((Object)(object)component2 != (Object)null && (Object)(object)component2.m_craftingStation != (Object)null) ? component2.m_craftingStation.m_name : string.Empty));
			string localizedName = ((Localization.instance != null) ? Localization.instance.Localize(piece.m_name) : piece.m_name);
			return CraftingLayoutRules.Resolve(((Object)((Component)piece).gameObject).name, piece.m_name, localizedName, station, (Object)(object)component == (Object)null && (Object)(object)component2 != (Object)null);
		}

		internal static string Label(CraftingSection section)
		{
			return CraftingLayoutRules.Label(section);
		}

		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 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 != 6 || 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 HammerCategoryHeader
	{
		private static GameObject[]? _tabs;

		private static TMP_Text[][] _labels = Array.Empty<TMP_Text[]>();

		private static TMP_Text?[] _normal = Array.Empty<TMP_Text>();

		private static TMP_Text?[] _selected = Array.Empty<TMP_Text>();

		private static Transform?[] _selectedRoots = Array.Empty<Transform>();

		private static string[][] _text = Array.Empty<string[]>();

		private static float[] _widths = Array.Empty<float>();

		private static float[] _layoutWidths = Array.Empty<float>();

		private static RectTransform? _parent;

		private static Vector2 _anchorMin;

		private static Vector2 _anchorMax;

		private static Vector2 _size;

		private static Vector2 _position;

		private static float _windowWidth = -1f;

		private static int _visibleCount = -1;

		internal static void Apply(Hud hud)
		{
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0064: Unknown result type (might be due to invalid IL or missing references)
			//IL_006b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0070: Unknown result type (might be due to invalid IL or missing references)
			//IL_0077: Unknown result type (might be due to invalid IL or missing references)
			//IL_007c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0083: Unknown result type (might be due to invalid IL or missing references)
			//IL_0088: Unknown result type (might be due to invalid IL or missing references)
			//IL_0352: Unknown result type (might be due to invalid IL or missing references)
			//IL_0357: Unknown result type (might be due to invalid IL or missing references)
			//IL_03c2: Unknown result type (might be due to invalid IL or missing references)
			//IL_03c7: Unknown result type (might be due to invalid IL or missing references)
			//IL_03fb: Unknown result type (might be due to invalid IL or missing references)
			//IL_0400: Unknown result type (might be due to invalid IL or missing references)
			//IL_041f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0424: Unknown result type (might be due to invalid IL or missing references)
			//IL_0429: Unknown result type (might be due to invalid IL or missing references)
			//IL_042e: Unknown result type (might be due to invalid IL or missing references)
			//IL_043c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0441: Unknown result type (might be due to invalid IL or missing references)
			//IL_045a: Unknown result type (might be due to invalid IL or missing references)
			//IL_045f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0464: Unknown result type (might be due to invalid IL or missing references)
			//IL_0469: Unknown result type (might be due to invalid IL or missing references)
			//IL_0475: Unknown result type (might be due to invalid IL or missing references)
			//IL_047c: Expected O, but got Unknown
			//IL_0490: Unknown result type (might be due to invalid IL or missing references)
			//IL_04ae: Unknown result type (might be due to invalid IL or missing references)
			//IL_04bd: Unknown result type (might be due to invalid IL or missing references)
			//IL_04c4: Unknown result type (might be due to invalid IL or missing references)
			//IL_04d6: Unknown result type (might be due to invalid IL or missing references)
			//IL_04e5: Unknown result type (might be due to invalid IL or missing references)
			//IL_04ee: Unknown result type (might be due to invalid IL or missing references)
			//IL_04f3: Unknown result type (might be due to invalid IL or missing references)
			//IL_0502: Unknown result type (might be due to invalid IL or missing references)
			//IL_050c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0513: Unknown result type (might be due to invalid IL or missing references)
			//IL_0527: Unknown result type (might be due to invalid IL or missing references)
			//IL_0531: Unknown result type (might be due to invalid IL or missing references)
			//IL_0538: Unknown result type (might be due to invalid IL or missing references)
			//IL_057a: Unknown result type (might be due to invalid IL or missing references)
			//IL_057f: Unknown result type (might be due to invalid IL or missing references)
			//IL_058a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0594: Unknown result type (might be due to invalid IL or missing references)
			//IL_059f: Unknown result type (might be due to invalid IL or missing references)
			//IL_05a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_05b7: Unknown result type (might be due to invalid IL or missing references)
			//IL_05e3: Unknown result type (might be due to invalid IL or missing references)
			//IL_0261: Unknown result type (might be due to invalid IL or missing references)
			//IL_0302: Unknown result type (might be due to invalid IL or missing references)
			if (!BuildMenuBridge.IsOpen || !BuildMenuBridge.HasOwnedTabs(hud))
			{
				return;
			}
			RectTransform component = hud.m_pieceSelectionWindow.GetComponent<RectTransform>();
			GameObject[] pieceCategoryTabs = hud.m_pieceCategoryTabs;
			if (_tabs != pieceCategoryTabs)
			{
				Restore();
				if (pieceCategoryTabs.Length == 0)
				{
					return;
				}
				Transform parent = pieceCategoryTabs[0].transform.parent;
				RectTransform val = (RectTransform)(object)((parent is RectTransform) ? parent : null);
				if (val == null)
				{
					return;
				}
				_tabs = pieceCategoryTabs;
				_parent = val;
				_anchorMin = val.anchorMin;
				_anchorMax = val.anchorMax;
				_size = val.sizeDelta;
				_position = val.anchoredPosition;
				_labels = new TMP_Text[pieceCategoryTabs.Length][];
				_normal = (TMP_Text?[])(object)new TMP_Text[pieceCategoryTabs.Length];
				_selected = (TMP_Text?[])(object)new TMP_Text[pieceCategoryTabs.Length];
				_selectedRoots = (Transform?[])(object)new Transform[pieceCategoryTabs.Length];
				_text = new string[pieceCategoryTabs.Length][];
				_widths = new float[pieceCategoryTabs.Length];
				for (int i = 0; i < pieceCategoryTabs.Length; i++)
				{
					_labels[i] = pieceCategoryTabs[i].GetComponentsInChildren<TMP_Text>(true);
					_text[i] = new string[_labels[i].Length];
					Transform val2 = pieceCategoryTabs[i].transform.Find("Selected");
					_selectedRoots[i] = val2;
					TMP_Text[] array = _labels[i];
					foreach (TMP_Text val3 in array)
					{
						if ((Object)(object)val2 != (Object)null && val3.transform.IsChildOf(val2))
						{
							_selected[i] = _selected[i] ?? val3;
						}
						else
						{
							_normal[i] = _normal[i] ?? val3;
						}
					}
				}
			}
			int num = 0;
			bool flag = false;
			for (int k = 0; k < pieceCategoryTabs.Length; k++)
			{
				if (!pieceCategoryTabs[k].activeSelf)
				{
					continue;
				}
				num++;
				TMP_Text val4 = (((Object)(object)_selectedRoots[k] != (Object)null && ((Component)_selectedRoots[k]).gameObject.activeSelf) ? _selected[k] : _normal[k]);
				string text = (((Object)(object)val4 == (Object)null) ? null : val4.text);
				bool flag2 = false;
				for (int l = 0; l < _labels[k].Length; l++)
				{
					TMP_Text val5 = _labels[k][l];
					if (text != null && val5.text != text)
					{
						val5.text = text;
					}
					if (val5.enableAutoSizing || val5.fontSize != 20f || (int)val5.textWrappingMode != 0)
					{
						val5.enableAutoSizing = false;
						val5.fontSize = 20f;
						val5.textWrappingMode = (TextWrappingModes)0;
						flag2 = true;
					}
					if (_text[k][l] != val5.text)
					{
						_text[k][l] = val5.text;
						flag2 = true;
					}
				}
				if (flag2)
				{
					float num2 = 0f;
					TMP_Text[] array = _labels[k];
					foreach (TMP_Text val6 in array)
					{
						num2 = Mathf.Max(num2, val6.GetPreferredValues(val6.text, float.PositiveInfinity, float.PositiveInfinity).x);
					}
					_widths[k] = num2;
					flag = true;
				}
			}
			if (num == 0)
			{
				return;
			}
			Rect rect;
			if (!flag && _visibleCount == num)
			{
				float windowWidth = _windowWidth;
				rect = component.rect;
				if (Mathf.Approximately(windowWidth, ((Rect)(ref rect)).width))
				{
					goto IL_03ef;
				}
			}
			float[] array2 = new float[num];
			int m = 0;
			int num3 = 0;
			for (; m < pieceCategoryTabs.Length; m++)
			{
				if (pieceCategoryTabs[m].activeSelf)
				{
					array2[num3++] = _widths[m];
				}
			}
			float num4 = HammerGridSizer.RepairRailWidth + 160f;
			HammerGridSizer.SetHeaderWidth(hud, HammerTabLayout.RequiredWidth(array2) + num4);
			rect = component.rect;
			_windowWidth = ((Rect)(ref rect)).width;
			_visibleCount = num;
			_layoutWidths = HammerTabLayout.Allocate(array2, _windowWidth - num4);
			goto IL_03ef;
			IL_03ef:
			Transform parent2 = ((Transform)_parent).parent;
			rect = component.rect;
			Vector3 val7 = parent2.InverseTransformPoint(((Transform)component).TransformPoint(new Vector3(((Rect)(ref rect)).xMin + HammerGridSizer.RepairRailWidth + 80f, 0f, 0f)));
			Transform parent3 = ((Transform)_parent).parent;
			rect = component.rect;
			Vector3 val8 = parent3.InverseTransformPoint(((Transform)component).TransformPoint(new Vector3(((Rect)(ref rect)).xMax - 80f, 0f, 0f)));
			RectTransform val9 = (RectTransform)((Transform)_parent).parent;
			_parent.anchorMin = new Vector2(0f, _anchorMin.y);
			_parent.anchorMax = new Vector2(0f, _anchorMax.y);
			_parent.sizeDelta = new Vector2(val8.x - val7.x, _size.y);
			RectTransform? parent4 = _parent;
			float x = val7.x;
			rect = val9.rect;
			parent4.anchoredPosition = new Vector2(x - ((Rect)(ref rect)).xMin + _parent.pivot.x * (val8.x - val7.x), _position.y);
			float num5 = (val8.x - val7.x) / (_windowWidth - HammerGridSizer.RepairRailWidth - 160f);
			float num6 = 0f;
			int n = 0;
			int num7 = 0;
			for (; n < pieceCategoryTabs.Length; n++)
			{
				if (pieceCategoryTabs[n].activeSelf)
				{
					RectTransform val10 = (RectTransform)pieceCategoryTabs[n].transform;
					val10.anchorMin = new Vector2(0f, 0f);
					val10.anchorMax = new Vector2(0f, 1f);
					val10.offsetMin = new Vector2(num6 + 2f, 0f);
					num6 += _layoutWidths[num7++] * num5;
					val10.offsetMax = new Vector2(num6 - 2f, 0f);
				}
			}
		}

		internal static void Restore()
		{
			//IL_0012: 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_0030: 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)
			if ((Object)(object)_parent != (Object)null)
			{
				_parent.anchorMin = _anchorMin;
				_parent.anchorMax = _anchorMax;
				_parent.sizeDelta = _size;
				_parent.anchoredPosition = _position;
			}
			_tabs = null;
			_parent = null;
			_windowWidth = -1f;
			_visibleCount = -1;
			_labels = Array.Empty<TMP_Text[]>();
			_text = Array.Empty<string[]>();
			_normal = Array.Empty<TMP_Text>();
			_selected = Array.Empty<TMP_Text>();
			_selectedRoots = Array.Empty<Transform>();
			_widths = Array.Empty<float>();
			_layoutWidths = Array.Empty<float>();
		}
	}
	internal static class HammerCategoryHints
	{
		private sealed class RectState
		{
			private readonly RectTransform _rect;

			private readonly Vector2 _min;

			private readonly Vector2 _max;

			private readonly Vector2 _pivot;

			private readonly Vector2 _size;

			private readonly Vector2 _position;

			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)
				//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)
				_rect = rect;
				_min = rect.anchorMin;
				_max = rect.anchorMax;
				_pivot = rect.pivot;
				_size = rect.sizeDelta;
				_position = 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)
				//IL_0038: Unknown result type (might be due to invalid IL or missing references)
				//IL_0049: Unknown result type (might be due to invalid IL or missing references)
				//IL_005a: Unknown result type (might be due to invalid IL or missing references)
				if (!((Object)(object)_rect == (Object)null))
				{
					_rect.anchorMin = _min;
					_rect.anchorMax = _max;
					_rect.pivot = _pivot;
					_rect.sizeDelta = _size;
					_rect.anchoredPosition = _position;
				}
			}
		}

		private static RectTransform? _window;

		private static RectState[]? _states;

		internal static void Apply(RectTransform window, float repairRailWidth, float headerCenterY)
		{
			//IL_00c5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00da: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ef: Unknown result type (might be due to invalid IL or missing references)
			//IL_0107: Unknown result type (might be due to invalid IL or missing references)
			//IL_0119: Unknown result type (might be due to invalid IL or missing references)
			//IL_012c: Unknown result type (might be due to invalid IL or missing references)
			//IL_013a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0152: Unknown result type (might be due to invalid IL or missing references)
			//IL_0160: Unknown result type (might be due to invalid IL or missing references)
			//IL_016e: Unknown result type (might be due to invalid IL or missing references)
			//IL_01af: 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_01b2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b9: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ce: Unknown result type (might be due to invalid IL or missing references)
			//IL_01dc: Unknown result type (might be due to invalid IL or missing references)
			if (_window == window)
			{
				return;
			}
			Restore();
			string[] array = new string[7] { "InputHelp", "InputHelp/MK hints", "InputHelp/Gamepad hints", "InputHelp/MK hints/Left", "InputHelp/MK hints/Right", "InputHelp/Gamepad hints/gamepad_hint_L", "InputHelp/Gamepad hints/gamepad_hint_R" };
			RectTransform[] array2 = (RectTransform[])(object)new RectTransform[array.Length];
			for (int i = 0; i < array.Length; i++)
			{
				Transform obj = ((Transform)window).Find(array[i]);
				RectTransform val = (RectTransform)(object)((obj is RectTransform) ? obj : null);
				if ((Object)(object)val == (Object)null)
				{
					return;
				}
				array2[i] = val;
			}
			_states = new RectState[array2.Length];
			for (int j = 0; j < array2.Length; j++)
			{
				_states[j] = new RectState(array2[j]);
			}
			_window = window;
			RectTransform obj2 = array2[0];
			obj2.anchorMin = new Vector2(0f, 1f);
			obj2.anchorMax = new Vector2(1f, 1f);
			obj2.pivot = new Vector2(0.5f, 0.5f);
			obj2.sizeDelta = new Vector2(0f - repairRailWidth - 84f, 40f);
			obj2.anchoredPosition = new Vector2(repairRailWidth * 0.5f, headerCenterY);
			for (int k = 1; k <= 2; k++)
			{
				array2[k].anchorMin = Vector2.zero;
				array2[k].anchorMax = Vector2.one;
				array2[k].pivot = new Vector2(0.5f, 0.5f);
				array2[k].sizeDelta = Vector2.zero;
				array2[k].anchoredPosition = Vector2.zero;
			}
			Vector2 val2 = default(Vector2);
			for (int l = 3; l < array2.Length; l++)
			{
				((Vector2)(ref val2))..ctor((l % 2 == 1) ? 0f : 1f, 0.5f);
				RectTransform obj3 = array2[l];
				Vector2 anchorMin = (array2[l].anchorMax = val2);
				obj3.anchorMin = anchorMin;
				array2[l].pivot = new Vector2(0.5f, 0.5f);
				array2[l].anchoredPosition = Vector2.zero;
			}
		}

		internal static void Restore()
		{
			if (_states != null)
			{
				RectState[] states = _states;
				for (int i = 0; i < states.Length; i++)
				{
					states[i].Restore();
				}
			}
			_states = null;
			_window = null;
		}
	}
	internal static class HammerCategoryRouting
	{
		private sealed class Projection
		{
			internal readonly List<CategoryMerge<Piece>> Merges = new List<CategoryMerge<Piece>>();

			internal readonly List<KeyValuePair<List<Piece>, Piece>> ActionCopies = new List<KeyValuePair<List<Piece>, Piece>>();

			internal readonly CategorySlots<Piece, Vector2Int> Slots;

			internal Projection(PieceTable table, List<List<Piece>> buckets)
			{
				Slots = new CategorySlots<Piece, Vector2Int>(buckets, 10, table.m_selectedPiece, table.m_lastSelectedPiece);
				table.m_selectedPiece = Slots.Selected;
				table.m_lastSelectedPiece = Slots.LastSelected;
			}

			internal void Restore(PieceTable table)
			{
				foreach (KeyValuePair<List<Piece>, Piece> actionCopy in ActionCopies)
				{
					actionCopy.Key.Remove(actionCopy.Value);
				}
				for (int num = Merges.Count - 1; num >= 0; num--)
				{
					Merges[num].Restore();
				}
				Slots.Restore();
				table.m_selectedPiece = Slots.OriginalSelected;
				table.m_lastSelectedPiece = Slots.OriginalLastSelected;
			}
		}

		private static readonly FieldInfo Available = AccessTools.Field(typeof(PieceTable), "m_availablePiecesByCategory");

		private static readonly Dictionary<PieceTable, Projection> Merges = new Dictionary<PieceTable, Projection>();

		internal static bool IsApplied(PieceTable table)
		{
			if ((Object)(object)table != (Object)null)
			{
				return Merges.ContainsKey(table);
			}
			return false;
		}

		internal static PieceCategory SeasonalCategory(PieceTable table)
		{
			return (PieceCategory)Merges[table].Slots.Category;
		}

		internal static PieceCategory SemanticCategory(PieceTable? table, PieceCategory category)
		{
			//IL_0001: 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)
			if (!IsSeasonalCategory(table, category))
			{
				return category;
			}
			return (PieceCategory)4;
		}

		internal static bool IsSeasonalCategory(PieceTable? table, PieceCategory category)
		{
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: Invalid comparison between Unknown and I4
			if ((Object)(object)table != (Object)null && Merges.TryGetValue(table, out Projection value))
			{
				return (int)category == value.Slots.Category;
			}
			return false;
		}

		internal static PieceCategory SelectionCategory(PieceTable table, Piece? piece, PieceCategory previous, bool wasSeasonal)
		{
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Invalid comparison between Unknown and I4
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: Invalid comparison between Unknown and I4
			//IL_003a: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)piece != (Object)null) || piece.m_repairPiece || piece.m_removePiece || (int)piece.m_category < 0 || (int)piece.m_category >= 9)
			{
				if (!wasSeasonal)
				{
					return previous;
				}
				return SeasonalCategory(table);
			}
			return Destination(table, piece);
		}

		internal static int PreviousCategoryIndex(int category, int previousSeasonal, int currentSeasonal)
		{
			if (category != currentSeasonal)
			{
				if (category != previousSeasonal)
				{
					return category;
				}
				return -1;
			}
			return previousSeasonal;
		}

		internal static HammerLayoutTab? LayoutTab(PieceTable? table, PieceCategory category)
		{
			//IL_0001: 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_002e: Expected I4, but got Unknown
			if (IsSeasonalCategory(table, category))
			{
				return HammerLayoutTab.Seasonal;
			}
			return (int)category switch
			{
				0 => HammerLayoutTab.Misc, 
				1 => HammerLayoutTab.Crafting, 
				2 => HammerLayoutTab.Wood, 
				5 => HammerLayoutTab.SpecialtyWood, 
				3 => HammerLayoutTab.HeavyBuild, 
				4 => HammerLayoutTab.Furniture, 
				_ => null, 
			};
		}

		internal static PieceCategory Destination(PieceTable table, Piece piece)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			return Destination(piece, SeasonalCategory(table));
		}

		private static PieceCategory Destination(Piece piece, PieceCategory seasonalCategory)
		{
			//IL_004e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0053: Unknown result type (might be due to invalid IL or missing references)
			//IL_0054: Unknown result type (might be due to invalid IL or missing references)
			//IL_0056: Invalid comparison between Unknown and I4
			//IL_0065: 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)
			if (HammerAuthoredLayout.TryGet(Utils.GetPrefabName(((Component)piece).gameObject), out HammerLayoutCell cell))
			{
				switch (cell.Tab)
				{
				case HammerLayoutTab.Misc:
					return (PieceCategory)0;
				case HammerLayoutTab.Crafting:
					return (PieceCategory)1;
				case HammerLayoutTab.Wood:
					return (PieceCategory)2;
				case HammerLayoutTab.SpecialtyWood:
					return (PieceCategory)5;
				case HammerLayoutTab.HeavyBuild:
					return (PieceCategory)3;
				case HammerLayoutTab.Furniture:
					return (PieceCategory)4;
				case HammerLayoutTab.Seasonal:
					return seasonalCategory;
				}
			}
			PieceCategory val = BaseDestination(piece);
			if ((int)val != 2 || !WoodFamilies.UsesSecondTab(Specialty(piece)))
			{
				return val;
			}
			return (PieceCategory)5;
		}

		internal static string? Specialty(Piece piece)
		{
			return WoodFamilies.Specialty(((Object)((Component)piece).gameObject).name, Resources(piece));
		}

		private static List<string> Resources(Piece piece)
		{
			List<string> list = new List<string>();
			if (piece.m_resources != null)
			{
				Requirement[] resources = piece.m_resources;
				foreach (Requirement val in resources)
				{
					if (val != null && (Object)(object)val.m_resItem != (Object)null)
					{
						list.Add(((Object)((Component)val.m_resItem).gameObject).name);
					}
				}
			}
			return list;
		}

		private static PieceCategory BaseDestination(Piece piece)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Invalid comparison between Unknown and I4
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			if ((int)piece.m_category != 5)
			{
				return piece.m_category;
			}
			if (WoodFamilies.IsDisplayDecor(((Object)((Component)piece).gameObject).name, (Object)(object)((Component)piece).GetComponent<Sign>() != (Object)null))
			{
				return (PieceCategory)4;
			}
			string label = BuildPieceMetadata.Material(((Object)((Component)piece).gameObject).name, Resources(piece)).Label;
			bool station = (Object)(object)((Component)piece).GetComponent<CraftingStation>() != (Object)null || (Object)(object)((Component)piece).GetComponent<StationExtension>() != (Object)null;
			return (PieceCategory)(BuildPieceMetadata.ExistingTab(((object)Unsafe.As<UsageTagFlags, UsageTagFlags>(ref piece.m_usage)/*cast due to .constrained prefix*/).ToString(), label, station) switch
			{
				"Crafting" => 1, 
				"Furniture" => 4, 
				"Building" => 2, 
				"HeavyBuild" => 3, 
				_ => 0, 
			});
		}

		internal static void Apply(PieceTable table, List<List<Piece>> buckets)
		{
			//IL_00b6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c0: Expected I4, but got Unknown
			if (buckets.Count <= 5 || Merges.ContainsKey(table))
			{
				return;
			}
			Projection projection = new Projection(table, buckets);
			List<CategoryMerge<Piece>> merges = projection.Merges;
			try
			{
				int num = Math.Min(9, buckets.Count);
				Piece[][] array = new Piece[num][];
				for (int i = 0; i < num; i++)
				{
					array[i] = buckets[i].ToArray();
				}
				for (int j = 0; j < num; j++)
				{
					int source = j;
					Dictionary<Piece, int> destinations = new Dictionary<Piece, int>();
					Piece[] array2 = array[source];
					foreach (Piece val in array2)
					{
						if (!IsAction(val))
						{
							destinations[val] = (int)Destination(val, (PieceCategory)projection.Slots.Category);
						}
					}
					merges.Add(new CategoryMerge<Piece>(buckets, source, (Piece piece) => destinations[piece], (Piece piece) => (Object)(object)piece == (Object)null || !destinations.TryGetValue(piece, out var value) || value == source, retainExcluded: true));
				}
				CopyActions(buckets[2], buckets[5], projection);
				CopyActions(buckets[4], buckets[projection.Slots.Category], projection);
				Merges.Add(table, projection);
			}
			catch
			{
				projection.Restore(table);
				throw;
			}
		}

		private static bool IsAction(Piece piece)
		{
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Invalid comparison between Unknown and I4
			if (!((Object)(object)piece == (Object)null) && (int)piece.m_category != 100 && !piece.m_repairPiece)
			{
				return piece.m_removePiece;
			}
			return true;
		}

		private static void CopyActions(List<Piece> source, List<Piece> target, Projection projection)
		{
			foreach (Piece item in source)
			{
				if ((Object)(object)item != (Object)null && IsAction(item) && !target.Contains(item))
				{
					target.Add(item);
					projection.ActionCopies.Add(new KeyValuePair<List<Piece>, Piece>(target, item));
				}
			}
		}

		internal static void Restore(PieceTable table)
		{
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_004f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0055: Invalid comparison between Unknown and I4
			//IL_0058: Unknown result type (might be due to invalid IL or missing references)
			//IL_005f: Invalid comparison between Unknown and I4
			//IL_0072: Unknown result type (might be due to invalid IL or missing references)
			//IL_007c: Expected I4, but got Unknown
			//IL_0089: Unknown result type (might be due to invalid IL or missing references)
			//IL_009c: Unknown result type (might be due to invalid IL or missing references)
			if (!Merges.TryGetValue(table, out Projection value))
			{
				return;
			}
			Piece selectedPiece = table.GetSelectedPiece();
			BuildMenuBridge.RestoreCategories(table);
			if (table.GetSelectedCategory() == SeasonalCategory(table))
			{
				table.SetCategory((PieceCategory)4);
			}
			value.Restore(table);
			Merges.Remove(table);
			if ((Object)(object)selectedPiece != (Object)null && (int)selectedPiece.m_category >= 0 && (int)selectedPiece.m_category < 9)
			{
				int num = ((List<List<Piece>>)Available.GetValue(table))[(int)selectedPiece.m_category].IndexOf(selectedPiece);
				if (num >= 0)
				{
					table.SetCategory(selectedPiece.m_category);
					table.SetSelected(new Vector2Int(num % 15, num / 15));
				}
			}
		}

		internal static void Reset()
		{
			foreach (PieceTable item in new List<PieceTable>(Merges.Keys))
			{
				if ((Object)(object)item != (Object)null)
				{
					Restore(item);
				}
			}
			Merges.Clear();
		}
	}
	internal static class HammerGridDimensions
	{
		internal const int NativeWidth = 15;

		internal const int NativeHeight = 6;

		internal const int ExpandedWidth = 15;

		internal const int ExpandedHeight = 15;

		internal const int ItemColumns = 14;

		internal const float ItemScale = 1f;

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

		internal static int Height
		{
			get
			{
				if (!BuildMenuBridge.OwnsMenu)
				{
					return 6;
				}
				return 15;
			}
		}

		internal static int MaxX => Width - 1;

		internal static int MaxY => Height - 1;

		internal static int TableHeight(PieceTable table)
		{
			if (!BuildMenuBridge.OwnsMenu || Player.m_localPlayer.GetBuildTool() != table)
			{
				return 6;
			}
			return 15;
		}

		internal static int TableMaxY(PieceTable table)
		{
			return TableHeight(table) - 1;
		}

		internal static float CraftingRowPitch(Hud hud)
		{
			return HammerPanelLayout.RowPitch(hud.m_pieceIconSpacing);
		}

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

		internal static float ItemStart(float spacing)
		{
			return CategoryRailWidth(spacing) + 14f;
		}

		internal static float ContentWidth(float spacing)
		{
			return Mathf.Max(15f * spacing, ItemStart(spacing) + 14f * HammerPanelLayout.RowPitch(spacing) + 12f);
		}
	}
	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 static int _hudInstanceId = int.MinValue;

		private static RectState? _windowState;

		private static RectState? _maskState;

		private static RectState? _categoryState;

		private static float _contentHeight;

		private static float _headerWidthDelta;

		internal static float RepairRailWidth { get; private set; }

		internal static void Apply(Hud hud)
		{
			//IL_00bc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ed: Unknown result type (might be due to invalid IL or missing references)
			//IL_010a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0116: Unknown result type (might be due to invalid IL or missing references)
			//IL_012b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0138: Unknown result type (might be due to invalid IL or missing references)
			//IL_013d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0181: Unknown result type (might be due to invalid IL or missing references)
			//IL_0190: Unknown result type (might be due to invalid IL or missing references)
			//IL_0195: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c4: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c9: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e6: Unknown result type (might be due to invalid IL or missing references)
			//IL_020c: Unknown result type (might be due to invalid IL or missing references)
			int instanceID = ((Object)hud).GetInstanceID();
			if (_hudInstanceId == instanceID)
			{
				return;
			}
			Restore();
			float pieceIconSpacing = hud.m_pieceIconSpacing;
			float num = HammerGridDimensions.ContentWidth(pieceIconSpacing) - 15f * pieceIconSpacing;
			_contentHeight = HammerPanelLayout.ContentHeight(pieceIconSpacing, 6);
			float num2 = _contentHeight - 6f * pieceIconSpacing;
			RepairRailWidth = pieceIconSpacing + 28f;
			float num3 = num + RepairRailWidth;
			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, num3, num2);
			}
			RectTransform pieceListMask = hud.m_pieceListMask;
			if ((Object)(object)pieceListMask != (Object)null)
			{
				_maskState = new RectState(pieceListMask);
				float widthDelta = num - (pieceListMask.anchorMax.x - pieceListMask.anchorMin.x) * num3;
				float heightDelta = num2 * (1f - (pieceListMask.anchorMax.y - pieceListMask.anchorMin.y));
				ExpandKeepingTopLeft(pieceListMask, widthDelta, heightDelta);
				pieceListMask.anchoredPosition += new Vector2(RepairRailWidth - pieceListMask.anchorMin.x * num3, (1f - pieceListMask.anchorMax.y) * num2);
			}
			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);
				if ((Object)(object)val != (Object)null)
				{
					float repairRailWidth = RepairRailWidth;
					float y = val2.anchoredPosition.y;
					Transform obj = ((Transform)val2).Find("Tabs");
					Transform obj2 = ((obj is RectTransform) ? obj : null);
					HammerCategoryHints.Apply(val, repairRailWidth, y + ((obj2 != null) ? ((RectTransform)obj2).anchoredPosition.y : 0f));
				}
			}
			_hudInstanceId = instanceID;
		}

		internal static void SetSharedLayout(Hud hud, int rows)
		{
			//IL_0072: 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_009b: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ab: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bd: Unknown result type (might be due to invalid IL or missing references)
			Apply(hud);
			float num = HammerPanelLayout.ContentHeight(hud.m_pieceIconSpacing, rows);
			float num2 = num - _contentHeight;
			if (!Mathf.Approximately(num2, 0f))
			{
				RectTransform val = (((Object)(object)hud.m_pieceSelectionWindow != (Object)null) ? hud.m_pieceSelectionWindow.GetComponent<RectTransform>() : null);
				if ((Object)(object)val != (Object)null)
				{
					ExpandCentered(val, 0f, num2);
				}
				RectTransform pieceListMask = hud.m_pieceListMask;
				if ((Object)(object)pieceListMask != (Object)null)
				{
					float heightDelta = num2 * (1f - (pieceListMask.anchorMax.y - pieceListMask.anchorMin.y));
					ExpandKeepingTopLeft(pieceListMask, 0f, heightDelta);
					pieceListMask.anchoredPosition += new Vector2(0f, (1f - pieceListMask.anchorMax.y) * num2);
				}
				_contentHeight = num;
			}
		}

		internal static void SetHeaderWidth(Hud hud, float requiredWidth)
		{
			//IL_0013: 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_0074: Unknown result type (might be due to invalid IL or missing references)
			//IL_0080: Unknown result type (might be due to invalid IL or missing references)
			//IL_009a: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b3: 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)
			Apply(hud);
			RectTransform component = hud.m_pieceSelectionWindow.GetComponent<RectTransform>();
			Rect rect = component.rect;
			float num = ((Rect)(ref rect)).width - _headerWidthDelta;
			float num2 = Mathf.Max(0f, requiredWidth - num);
			float num3 = num2 - _headerWidthDelta;
			if (!Mathf.Approximately(num3, 0f))
			{
				ExpandCentered(component, num3, 0f);
				RectTransform pieceListMask = hud.m_pieceListMask;
				if ((Object)(object)pieceListMask != (Object)null)
				{
					ExpandKeepingTopLeft(pieceListMask, num3 * (1f - (pieceListMask.anchorMax.x - pieceListMask.anchorMin.x)), 0f);
					pieceListMask.anchoredPosition += new Vector2((0f - pieceListMask.anchorMin.x) * num3, 0f);
				}
				_headerWidthDelta = num2;
			}
		}

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

		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 int[] GroupIds { get; }

			internal int RepairIndex { get; }

			internal string[] RowLabels { get; }

			internal int[] Representatives { get; }

			internal int VisibleRows { get; }

			internal CraftingLayoutResult(int[] slots, int[] groupIds, int repairIndex, string[] rowLabels, int[] representatives, int visibleRows)
			{
				Slots = slots;
				GroupIds = groupIds;
				RepairIndex = repairIndex;
				RowLabels = rowLabels;
				Representatives = representatives;
				VisibleRows = visibleRows;
			}
		}

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

			internal int[] GroupIds { get; }

			internal List<ShelfCard> Cards { get; }

			internal int VisibleRows { get; }

			internal float RowPitch { get; }

			internal int ColumnCount { get; }

			internal int RepairIndex { get; }

			internal ShelfLayoutResult(int[] slots, int[] groupIds, List<ShelfCard> cards, int visibleRows, float rowPitch, int columnCount, int repairIndex)
			{
				Slots = slots;
				GroupIds = groupIds;
				Cards = cards;
				VisibleRows = visibleRows;
				RowPitch = rowPitch;
				ColumnCount = columnCount;
				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 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 Vector3 NativeScale { get; }

			private RectTransform? IconRect { get; }

			private Vector2 IconAnchorMin { get; }

			private Vector2 IconAnchorMax { get; }

			private Vector2 IconPivot { get; }

			private Vector2 IconAnchoredPosition { get; }

			private Vector2 IconSizeDelta { get; }

			private Image? IconImage { get; }

			private bool IconPreserveAspect { 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, RectTransform? iconRect, Image? iconImage, 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)
				//IL_0038: Unknown result type (might be due to invalid IL or missing references)
				//IL_003d: Unknown result type (might be due to invalid IL or missing references)
				//IL_005e: Unknown result type (might be due to invalid IL or missing references)
				//IL_0055: Unknown result type (might be due to invalid IL or missing references)
				//IL_0063: Unknown result type (might be due to invalid IL or missing references)
				//IL_007c: Unknown result type (might be due to invalid IL or missing references)
				//IL_0073: Unknown result type (might be due to invalid IL or missing references)
				//IL_0081: Unknown result type (might be due to invalid IL or missing references)
				//IL_009a: Unknown result type (might be due to invalid IL or missing references)
				//IL_0091: Unknown result type (might be due to invalid IL or missing references)
				//IL_009f: Unknown result type (might be due to invalid IL or missing references)
				//IL_00b8: Unknown result type (mig