Decompiled source of Legacy Build Menu v1.0.0

plugins/LegacyBuildMenu/LegacyBuildMenu.dll

Decompiled a week ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using System.Text.RegularExpressions;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using TMPro;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.Events;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: AssemblyTitle("LegacyBuildMenu")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("Azumatt")]
[assembly: AssemblyProduct("LegacyBuildMenu")]
[assembly: AssemblyCopyright("Copyright ©  2026")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("9D000134-08B3-4B35-A9C4-A08D6C3D0226")]
[assembly: AssemblyFileVersion("1.0.0")]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.0.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.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 LegacyBuildMenu
{
	[RequireComponent(typeof(CanvasGroup))]
	public class GripHandle : MonoBehaviour, IPointerEnterHandler, IEventSystemHandler, IPointerExitHandler, IBeginDragHandler, IDragHandler, IEndDragHandler
	{
		public Action<Vector2>? Dragged;

		public Action? Ended;

		private CanvasGroup _cg = null;

		private float _scale = 1f;

		private bool _dragging;

		private bool _hovered;

		private static Sprite? _rounded;

		private void Awake()
		{
			_cg = ((Component)this).GetComponent<CanvasGroup>();
			Canvas componentInParent = ((Component)this).GetComponentInParent<Canvas>();
			if ((Object)(object)componentInParent != (Object)null && componentInParent.scaleFactor > 0f)
			{
				_scale = componentInParent.scaleFactor;
			}
		}

		private void Update()
		{
			float num = ((_dragging || _hovered) ? 1f : 0f);
			_cg.alpha = Mathf.MoveTowards(_cg.alpha, num, Time.unscaledDeltaTime * 8f);
		}

		public void OnPointerEnter(PointerEventData eventData)
		{
			_hovered = true;
		}

		public void OnPointerExit(PointerEventData eventData)
		{
			_hovered = false;
		}

		public void OnBeginDrag(PointerEventData eventData)
		{
			_dragging = true;
		}

		public void OnDrag(PointerEventData eventData)
		{
			//IL_000d: 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)
			Dragged?.Invoke(eventData.delta / _scale);
		}

		public void OnEndDrag(PointerEventData eventData)
		{
			_dragging = false;
			Ended?.Invoke();
		}

		internal static Sprite RoundedRect()
		{
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Expected O, but got Unknown
			//IL_00df: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ee: Unknown result type (might be due to invalid IL or missing references)
			//IL_010e: Unknown result type (might be due to invalid IL or missing references)
			//IL_008d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0076: Unknown result type (might be due to invalid IL or missing references)
			//IL_0092: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)_rounded != (Object)null)
			{
				return _rounded;
			}
			Texture2D val = new Texture2D(64, 64)
			{
				wrapMode = (TextureWrapMode)1,
				filterMode = (FilterMode)1
			};
			Color32[] array = (Color32[])(object)new Color32[4096];
			for (int i = 0; i < 64; i++)
			{
				for (int j = 0; j < 64; j++)
				{
					array[i * 64 + j] = (CornerCut(j, i, 64, 14) ? new Color32(byte.MaxValue, byte.MaxValue, byte.MaxValue, (byte)0) : new Color32(byte.MaxValue, byte.MaxValue, byte.MaxValue, byte.MaxValue));
				}
			}
			val.SetPixels32(array);
			val.Apply();
			_rounded = Sprite.Create(val, new Rect(0f, 0f, 64f, 64f), new Vector2(0.5f, 0.5f), 100f, 0u, (SpriteMeshType)0, new Vector4(14f, 14f, 14f, 14f));
			((Object)_rounded).name = "LegacyBuildMenu_Rounded";
			return _rounded;
		}

		private static bool CornerCut(int x, int y, int size, int r)
		{
			int num = ((x < r) ? r : ((x >= size - r) ? (size - r - 1) : x));
			int num2 = ((y < r) ? r : ((y >= size - r) ? (size - r - 1) : y));
			int num3 = x - num;
			int num4 = y - num2;
			return num3 * num3 + num4 * num4 > r * r;
		}
	}
	[HarmonyPatch]
	public static class LegacyMenu
	{
		private const string PieceManagerHarmonyId = "org.bepinex.helpers.PieceManager";

		private const string JotunnHarmonyId = "com.jotunn.jotunn";

		private static bool? _tabManagerPresent;

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

		private static bool Enabled => LegacyBuildMenuPlugin.UseLegacyMenu.Value && !LegacyBuildMenuPlugin.StoodDown;

		private static bool TabManagerPresent
		{
			get
			{
				bool valueOrDefault = _tabManagerPresent == true;
				bool result;
				if (!_tabManagerPresent.HasValue)
				{
					valueOrDefault = Chainloader.PluginInfos.ContainsKey("com.jotunn.jotunn") || AppDomain.CurrentDomain.GetAssemblies().Any(delegate(Assembly a)
					{
						try
						{
							return a.GetType("PieceManager.PiecePrefabManager", throwOnError: false) != null;
						}
						catch
						{
							return false;
						}
					});
					_tabManagerPresent = valueOrDefault;
					result = valueOrDefault;
				}
				else
				{
					result = valueOrDefault;
				}
				return result;
			}
		}

		private static bool On(Hud? hud)
		{
			return Enabled && (Object)(object)hud != (Object)null && (Object)(object)hud.m_pieceSelectionWindow != (Object)null && (Object)(object)hud.m_buildUi != (Object)null;
		}

		private static void SetWindow(Hud hud, bool open)
		{
			hud.m_pieceSelectionWindow.SetActive(open);
			if ((Object)(object)hud.m_closePieceSelectionButton != (Object)null)
			{
				((Component)hud.m_closePieceSelectionButton).gameObject.SetActive(open);
			}
		}

		internal static void OnSettingChanged()
		{
			Hud instance = Hud.instance;
			if (!((Object)(object)instance == (Object)null))
			{
				if ((Object)(object)instance.m_pieceSelectionWindow != (Object)null)
				{
					SetWindow(instance, open: false);
				}
				if ((Object)(object)instance.m_buildUi != (Object)null && ((Component)instance.m_buildUi).gameObject.activeSelf)
				{
					instance.m_buildUi.Close();
				}
				Player localPlayer = Player.m_localPlayer;
				if ((Object)(object)localPlayer != (Object)null && (Object)(object)localPlayer.m_buildPieces != (Object)null)
				{
					localPlayer.UpdateAvailablePiecesList();
				}
			}
		}

		[HarmonyPatch(typeof(Hud), "TogglePieceSelection")]
		[HarmonyPrefix]
		private static bool Hud_TogglePieceSelection(Hud __instance)
		{
			if (!On(__instance))
			{
				return true;
			}
			__instance.m_hoveredPiece = null;
			if (__instance.m_pieceSelectionWindow.activeSelf)
			{
				PlayerController.SetTakeInputDelay(0.2f);
				SetWindow(__instance, open: false);
			}
			else
			{
				if (((Component)__instance.m_buildUi).gameObject.activeSelf)
				{
					__instance.m_buildUi.Close();
				}
				LegacyWindow.EnsureBuilt(__instance);
				SetWindow(__instance, open: true);
				LegacyWindow.ApplyWindow(__instance);
				__instance.UpdateBuild(Player.m_localPlayer, true);
			}
			return false;
		}

		[HarmonyPatch(typeof(Hud), "HidePieceSelection")]
		[HarmonyPrefix]
		private static bool Hud_HidePieceSelection()
		{
			Hud instance = Hud.instance;
			if (!On(instance))
			{
				return true;
			}
			instance.m_pressedPiece = null;
			instance.m_closePieceSelection = 2;
			return false;
		}

		[HarmonyPatch(typeof(Hud), "IsPieceSelectionVisible")]
		[HarmonyPrefix]
		private static bool Hud_IsPieceSelectionVisible(ref bool __result)
		{
			Hud instance = Hud.instance;
			if (!On(instance))
			{
				return true;
			}
			__result = instance.m_buildHud.activeSelf && instance.m_pieceSelectionWindow.activeSelf;
			return false;
		}

		[HarmonyPatch(typeof(Hud), "InBuildUi")]
		[HarmonyPostfix]
		private static void Hud_InBuildUi(ref bool __result)
		{
			if (!__result && On(Hud.instance))
			{
				__result = Hud.IsPieceSelectionVisible();
			}
		}

		[HarmonyPatch(typeof(BuildUi), "OpenBuildMenu")]
		[HarmonyPrefix]
		private static bool BuildUi_OpenBuildMenu()
		{
			return !On(Hud.instance);
		}

		[HarmonyPatch(typeof(Hud), "UpdateBuild")]
		[HarmonyPrefix]
		[HarmonyPriority(0)]
		[HarmonyAfter(new string[] { "org.bepinex.helpers.PieceManager", "com.jotunn.jotunn" })]
		private static bool Hud_UpdateBuild(Hud __instance, Player player, bool forceUpdateAllBuildStatuses)
		{
			if (!On(__instance))
			{
				return true;
			}
			try
			{
				UpdateBuild(__instance, player, forceUpdateAllBuildStatuses);
			}
			catch (Exception ex)
			{
				LegacyBuildMenuPlugin.LogErrorOnce("legacy UpdateBuild", ex);
			}
			return false;
		}

		private static void UpdateBuild(Hud hud, Player player, bool forceUpdateAllBuildStatuses)
		{
			//IL_0104: Unknown result type (might be due to invalid IL or missing references)
			//IL_0105: Unknown result type (might be due to invalid IL or missing references)
			//IL_0110: Unknown result type (might be due to invalid IL or missing references)
			if (((Component)hud.m_buildUi).gameObject.activeSelf)
			{
				hud.m_buildUi.Close();
			}
			if (!((Character)player).InPlaceMode())
			{
				hud.m_hoveredPiece = null;
				hud.m_buildHud.SetActive(false);
				SetWindow(hud, open: false);
				return;
			}
			if (hud.m_closePieceSelection > 0)
			{
				hud.m_closePieceSelection--;
				if (hud.m_closePieceSelection <= 0 && hud.m_pieceSelectionWindow.activeSelf)
				{
					hud.m_hoveredPiece = null;
					SetWindow(hud, open: false);
					Character.SetTakeInputDelay(0.2f);
					PlayerController.SetTakeInputDelay(0.2f);
				}
			}
			LegacyWindow.EnsureBuilt(hud);
			LegacyWindow.RefreshColumns(hud);
			Piece val = default(Piece);
			Vector2Int val2 = default(Vector2Int);
			int num = default(int);
			PieceCategory val3 = default(PieceCategory);
			PieceTable pieceTable = default(PieceTable);
			player.GetBuildSelection(ref val, ref val2, ref num, ref val3, ref pieceTable);
			hud.m_buildHud.SetActive(!hud.m_radialMenu.Active);
			if (hud.m_pieceSelectionWindow.activeSelf)
			{
				hud.UpdatePieceList(player, val2, val3, forceUpdateAllBuildStatuses);
				UpdateTabs(hud, player, pieceTable, val3);
				Localization.instance.Localize(hud.m_buildHud.transform);
			}
			if ((Object)(object)hud.m_hoveredPiece != (Object)null && (ZInput.IsGamepadActive() || !player.IsPieceAvailable(hud.m_hoveredPiece)))
			{
				hud.m_hoveredPiece = null;
			}
			hud.SetupPieceInfo(((Object)(object)hud.m_hoveredPiece != (Object)null) ? hud.m_hoveredPiece : val);
		}

		[HarmonyPatch(typeof(Hud), "UpdatePieceList")]
		[HarmonyPrefix]
		private static bool Hud_UpdatePieceList(Hud __instance, Player player, Vector2Int selectedNr, PieceCategory category, bool updateAllBuildStatuses)
		{
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			if (!On(__instance))
			{
				return true;
			}
			try
			{
				UpdatePieceList(__instance, player, selectedNr, category, updateAllBuildStatuses);
			}
			catch (Exception ex)
			{
				LegacyBuildMenuPlugin.LogErrorOnce("legacy UpdatePieceList", ex);
			}
			return false;
		}

		private static void UpdatePieceList(Hud hud, Player player, Vector2Int selectedNr, PieceCategory category, bool updateAllBuildStatuses)
		{
			//IL_0220: Unknown result type (might be due to invalid IL or missing references)
			//IL_0225: Unknown result type (might be due to invalid IL or missing references)
			//IL_0231: Unknown result type (might be due to invalid IL or missing references)
			//IL_0232: Unknown result type (might be due to invalid IL or missing references)
			//IL_0135: Unknown result type (might be due to invalid IL or missing references)
			//IL_013c: Expected O, but got Unknown
			//IL_0151: 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_016e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0184: Unknown result type (might be due to invalid IL or missing references)
			//IL_0189: Unknown result type (might be due to invalid IL or missing references)
			List<Piece> buildPieces = player.GetBuildPieces();
			int count = buildPieces.Count;
			int columns = LegacyWindow.Columns;
			float num = LegacyWindow.Spacing(hud);
			while (hud.m_pieceIcons.Count < Mathf.Max(count, 1))
			{
				hud.m_pieceIcons.Add(CreateIcon(hud));
			}
			Vector2 val4 = default(Vector2);
			for (int i = 0; i < hud.m_pieceIcons.Count; i++)
			{
				PieceIconData val = hud.m_pieceIcons[i];
				if ((Object)(object)val?.m_go == (Object)null)
				{
					continue;
				}
				if (i >= count)
				{
					val.m_marker.SetActive(false);
					((Behaviour)val.m_icon).enabled = false;
					val.m_tooltip.m_text = "";
					val.m_upgrade.SetActive(false);
					if (val.m_go.activeSelf)
					{
						val.m_go.SetActive(false);
					}
					continue;
				}
				int num2 = i % columns;
				int num3 = i / columns;
				Piece val2 = buildPieces[i];
				if (!val.m_go.activeSelf)
				{
					val.m_go.SetActive(true);
				}
				RectTransform val3 = (RectTransform)val.m_go.transform;
				((Vector2)(ref val4))..ctor(0f, 1f);
				val3.anchorMax = val4;
				val3.anchorMin = val4;
				val3.anchoredPosition = new Vector2((float)num2 * num, (float)(-num3) * num);
				val.m_marker.SetActive(new Vector2Int(num2, num3) == selectedNr);
				val.m_icon.sprite = val2.m_icon;
				((Behaviour)val.m_icon).enabled = true;
				val.m_tooltip.m_text = val2.m_name;
				val.m_upgrade.SetActive(val2.m_isUpgrade);
			}
			LegacyWindow.SetContentHeight(hud, count);
			UpdateBuildStatus(hud, buildPieces, player);
			if (updateAllBuildStatuses)
			{
				UpdateBuildStatusAll(hud, buildPieces, player);
			}
			if (hud.m_lastPieceCategory != category)
			{
				hud.m_lastPieceCategory = category;
				UpdateBuildStatusAll(hud, buildPieces, player);
				LegacyWindow.ScrollToTop();
			}
		}

		private static void UpdateBuildStatus(Hud hud, List<Piece> pieces, Player player)
		{
			//IL_008f: 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)
			if (hud.m_pieceIcons.Count != 0)
			{
				if (hud.m_pieceIconUpdateIndex >= hud.m_pieceIcons.Count)
				{
					hud.m_pieceIconUpdateIndex = 0;
				}
				int pieceIconUpdateIndex = hud.m_pieceIconUpdateIndex;
				PieceIconData val = hud.m_pieceIcons[pieceIconUpdateIndex];
				if ((Object)(object)val?.m_icon != (Object)null && pieceIconUpdateIndex < pieces.Count)
				{
					((Graphic)val.m_icon).color = (CanBuild(player, pieces[pieceIconUpdateIndex]) ? Color.white : Hud.s_colorRedBlueZeroAlpha);
				}
				hud.m_pieceIconUpdateIndex++;
			}
		}

		private static void UpdateBuildStatusAll(Hud hud, List<Piece> pieces, Player player)
		{
			//IL_0050: 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)
			for (int i = 0; i < hud.m_pieceIcons.Count; i++)
			{
				PieceIconData val = hud.m_pieceIcons[i];
				if (!((Object)(object)val?.m_icon == (Object)null))
				{
					((Graphic)val.m_icon).color = ((i >= pieces.Count || CanBuild(player, pieces[i])) ? Color.white : Hud.s_colorRedBlueZeroAlpha);
				}
			}
			hud.m_pieceIconUpdateIndex = 0;
		}

		private static bool CanBuild(Player player, Piece? piece)
		{
			if ((Object)(object)player == (Object)null || (Object)(object)piece == (Object)null)
			{
				return false;
			}
			try
			{
				return player.HaveRequirements(piece, (RequirementMode)0);
			}
			catch (Exception ex)
			{
				string prefabName = Utils.GetPrefabName(((Component)piece).gameObject);
				if (_reportedBadPieces.Add(prefabName + "#status"))
				{
					LegacyBuildMenuPlugin.Log.LogWarning((object)("Piece '" + prefabName + "' threw in HaveRequirements (" + ex.GetType().Name + "), treating it as unbuildable. Whichever mod adds it has a broken build requirement."));
				}
				return false;
			}
		}

		private static PieceIconData CreateIcon(Hud hud)
		{
			//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_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0046: Unknown result type (might be due to invalid IL or missing references)
			//IL_0061: Unknown result type (might be due to invalid IL or missing references)
			//IL_007d: Expected O, but got Unknown
			//IL_0083: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = Object.Instantiate<GameObject>(hud.m_pieceIconPrefab, (Transform)(object)hud.m_pieceListRoot);
			PieceIconData val2 = new PieceIconData
			{
				m_go = val,
				m_tooltip = val.GetComponent<UITooltip>(),
				m_icon = ((Component)val.transform.Find("icon")).GetComponent<Image>(),
				m_marker = ((Component)val.transform.Find("selected")).gameObject,
				m_upgrade = ((Component)val.transform.Find("upgrade")).gameObject
			};
			((Graphic)val2.m_icon).color = Hud.s_colorRedBlueZeroAlpha;
			UIInputHandler component = val.GetComponent<UIInputHandler>();
			component.m_onLeftDown = (Action<UIInputHandler>)Delegate.Combine(component.m_onLeftDown, new Action<UIInputHandler>(hud.OnLeftClickPiece));
			component.m_onRightDown = (Action<UIInputHandler>)Delegate.Combine(component.m_onRightDown, new Action<UIInputHandler>(hud.OnRightClickPiece));
			component.m_onPointerEnter = (Action<UIInputHandler>)Delegate.Combine(component.m_onPointerEnter, new Action<UIInputHandler>(hud.OnHoverPiece));
			component.m_onPointerExit = (Action<UIInputHandler>)Delegate.Combine(component.m_onPointerExit, new Action<UIInputHandler>(hud.OnHoverPieceExit));
			return val2;
		}

		[HarmonyPatch(typeof(Hud), "GetSelectedGrid")]
		[HarmonyPrefix]
		private static bool Hud_GetSelectedGrid(Hud __instance, UIInputHandler ih, ref Vector2Int __result)
		{
			//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_005b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0060: Unknown result type (might be due to invalid IL or missing references)
			if (!On(__instance))
			{
				return true;
			}
			int columns = LegacyWindow.Columns;
			__result = new Vector2Int(-1, -1);
			for (int i = 0; i < __instance.m_pieceIcons.Count; i++)
			{
				if ((Object)(object)__instance.m_pieceIcons[i]?.m_go == (Object)(object)((Component)ih).gameObject)
				{
					__result = new Vector2Int(i % columns, i / columns);
					break;
				}
			}
			return false;
		}

		[HarmonyPatch(typeof(PieceTable), "GetPiece", new Type[]
		{
			typeof(PieceCategory),
			typeof(Vector2Int)
		})]
		[HarmonyPrefix]
		private static bool PieceTable_GetPiece(PieceTable __instance, PieceCategory category, Vector2Int p, ref Piece? __result)
		{
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_0037: Expected I4, but got Unknown
			if (!On(Hud.instance))
			{
				return true;
			}
			List<List<Piece>> availablePiecesByCategory = __instance.m_availablePiecesByCategory;
			__result = null;
			if (availablePiecesByCategory.Count == 0)
			{
				return false;
			}
			int num = (int)category;
			if (num >= availablePiecesByCategory.Count)
			{
				num = 0;
			}
			int num2 = ((Vector2Int)(ref p)).y * LegacyWindow.Columns + ((Vector2Int)(ref p)).x;
			if (num2 >= 0 && num2 < availablePiecesByCategory[num].Count)
			{
				__result = availablePiecesByCategory[num][num2];
			}
			return false;
		}

		[HarmonyPatch(typeof(PieceTable), "GetPieceIndex")]
		[HarmonyPrefix]
		private static bool PieceTable_GetPieceIndex(PieceTable __instance, Piece p, ref Vector2Int index, ref PieceCategory category, ref bool __result)
		{
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: Expected I4, but got Unknown
			//IL_008d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0092: Unknown result type (might be due to invalid IL or missing references)
			if (!On(Hud.instance))
			{
				return true;
			}
			string prefabName = Utils.GetPrefabName(((Component)p).gameObject);
			int num = (int)__instance.GetSelectedCategory();
			__result = TryLocate(__instance, num, prefabName, ref index, ref category);
			int num2 = 0;
			while (!__result && num2 < __instance.m_availablePiecesByCategory.Count)
			{
				if (num2 != num)
				{
					__result = TryLocate(__instance, num2, prefabName, ref index, ref category);
				}
				num2++;
			}
			if (!__result)
			{
				index = Vector2Int.zero;
				category = (PieceCategory)0;
			}
			return false;
		}

		private static bool TryLocate(PieceTable table, int slot, string prefab, ref Vector2Int index, ref PieceCategory category)
		{
			//IL_0085: Unknown result type (might be due to invalid IL or missing references)
			//IL_008a: Unknown result type (might be due to invalid IL or missing references)
			if (slot < 0 || slot >= table.m_availablePiecesByCategory.Count || !table.m_categories.Contains((PieceCategory)slot))
			{
				return false;
			}
			List<Piece> list = table.m_availablePiecesByCategory[slot];
			int columns = LegacyWindow.Columns;
			for (int i = 0; i < list.Count; i++)
			{
				if (!((Object)(object)list[i] == (Object)null) && !(Utils.GetPrefabName(((Component)list[i]).gameObject) != prefab))
				{
					index = new Vector2Int(i % columns, i / columns);
					category = (PieceCategory)slot;
					return true;
				}
			}
			return false;
		}

		[HarmonyPatch(typeof(PieceTable), "LeftPiece")]
		[HarmonyPrefix]
		private static bool PieceTable_LeftPiece(PieceTable __instance)
		{
			return Nav(__instance, -1, 0);
		}

		[HarmonyPatch(typeof(PieceTable), "RightPiece")]
		[HarmonyPrefix]
		private static bool PieceTable_RightPiece(PieceTable __instance)
		{
			return Nav(__instance, 1, 0);
		}

		[HarmonyPatch(typeof(PieceTable), "UpPiece")]
		[HarmonyPrefix]
		private static bool PieceTable_UpPiece(PieceTable __instance)
		{
			return Nav(__instance, 0, -1);
		}

		[HarmonyPatch(typeof(PieceTable), "DownPiece")]
		[HarmonyPrefix]
		private static bool PieceTable_DownPiece(PieceTable __instance)
		{
			return Nav(__instance, 0, 1);
		}

		private static bool Nav(PieceTable table, int dx, int dy)
		{
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: Expected I4, but got Unknown
			//IL_0089: Unknown result type (might be due to invalid IL or missing references)
			//IL_008e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c3: Unknown result type (might be due to invalid IL or missing references)
			if (!On(Hud.instance))
			{
				return true;
			}
			int num = (int)table.GetSelectedCategory();
			if (num < 0 || num >= table.m_availablePiecesByCategory.Count || num >= table.m_selectedPiece.Length)
			{
				return true;
			}
			int count = table.m_availablePiecesByCategory[num].Count;
			if (count <= 1)
			{
				return false;
			}
			int columns = LegacyWindow.Columns;
			int num2 = LegacyWindow.RowCount(count);
			Vector2Int val = table.m_selectedPiece[num];
			((Vector2Int)(ref val)).x = (((Vector2Int)(ref val)).x + dx + columns) % columns;
			((Vector2Int)(ref val)).y = (((Vector2Int)(ref val)).y + dy + num2) % num2;
			table.m_selectedPiece[num] = val;
			return false;
		}

		[HarmonyPatch(typeof(PieceTable), "UpdateAvailable")]
		[HarmonyPostfix]
		[HarmonyPriority(0)]
		[HarmonyAfter(new string[] { "org.bepinex.helpers.PieceManager", "com.jotunn.jotunn" })]
		private static void PieceTable_UpdateAvailable_Search(PieceTable __instance)
		{
			//IL_00a7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ac: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e6: Unknown result type (might be due to invalid IL or missing references)
			PieceSearch query = LegacyWindow.Query;
			if (!Enabled || query.IsEmpty || (Object)(object)Player.m_localPlayer == (Object)null || (Object)(object)Player.m_localPlayer.m_buildPieces != (Object)(object)__instance)
			{
				return;
			}
			try
			{
				List<List<Piece>> availablePiecesByCategory = __instance.m_availablePiecesByCategory;
				for (int i = 0; i < availablePiecesByCategory.Count; i++)
				{
					availablePiecesByCategory[i].RemoveAll((Piece piece) => !query.Matches(piece));
					if (i < __instance.m_selectedPiece.Length)
					{
						Vector2Int val = __instance.m_selectedPiece[i];
						if (((Vector2Int)(ref val)).y * LegacyWindow.Columns + ((Vector2Int)(ref val)).x >= availablePiecesByCategory[i].Count)
						{
							__instance.m_selectedPiece[i] = Vector2Int.zero;
						}
					}
				}
			}
			catch (Exception ex)
			{
				LegacyBuildMenuPlugin.LogErrorOnce("build piece search filter", ex);
			}
		}

		[HarmonyPatch(typeof(Player), "CopyPiece")]
		[HarmonyPrefix]
		private static void Player_CopyPiece()
		{
			if (On(Hud.instance))
			{
				LegacyWindow.ClearSearch();
			}
		}

		[HarmonyPatch(typeof(Menu), "IsVisible")]
		[HarmonyPostfix]
		private static void Menu_IsVisible(ref bool __result)
		{
			if (!__result && On(Hud.instance) && LegacyWindow.IsSearchFocused)
			{
				__result = true;
			}
		}

		[HarmonyPatch(typeof(Menu), "IsActive")]
		[HarmonyPostfix]
		private static void Menu_IsActive(ref bool __result)
		{
			if (!__result && On(Hud.instance) && LegacyWindow.IsSearchFocused)
			{
				__result = true;
			}
		}

		[HarmonyPatch(typeof(ZInput), "GetMouseScrollWheel")]
		[HarmonyPostfix]
		private static void ZInput_GetMouseScrollWheel(ref float __result)
		{
			if (__result != 0f && On(Hud.instance) && Hud.IsPieceSelectionVisible() && LegacyWindow.ShouldEatWheel())
			{
				__result = 0f;
			}
		}

		private static void UpdateTabs(Hud hud, Player player, PieceTable pieceTable, PieceCategory category)
		{
			//IL_0082: Unknown result type (might be due to invalid IL or missing references)
			//IL_0087: Unknown result type (might be due to invalid IL or missing references)
			//IL_0096: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bd: Unknown result type (might be due to invalid IL or missing references)
			hud.m_pieceCategoryRoot.SetActive(pieceTable.m_categories.Count > 0);
			if (pieceTable.m_categories.Count == 0)
			{
				return;
			}
			EnsureTabCount(hud, pieceTable.m_categories.Count);
			for (int i = 0; i < hud.m_pieceCategoryTabs.Length; i++)
			{
				GameObject val = hud.m_pieceCategoryTabs[i];
				bool flag = i < pieceTable.m_categories.Count;
				val.SetActive(flag);
				if (!flag)
				{
					continue;
				}
				PieceCategory val2 = pieceTable.m_categories[i];
				string text = $"{TabLabel(pieceTable, i)} [<color=yellow>{player.GetAvailableBuildPiecesInCategory(val2)}</color>]";
				Transform val3 = val.transform.Find("Selected");
				bool flag2 = val2 == category;
				if ((Object)(object)val3 != (Object)null)
				{
					((Component)val3).gameObject.SetActive(flag2);
					if (flag2)
					{
						((Component)val3).GetComponentInChildren<TMP_Text>().text = text;
					}
				}
				if (!flag2 || (Object)(object)val3 == (Object)null)
				{
					val.GetComponentInChildren<TMP_Text>().text = text;
				}
			}
		}

		private static string TabLabel(PieceTable table, int i)
		{
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			string text = ((object)table.m_categories[i]/*cast due to .constrained prefix*/).ToString();
			string text2 = ((i < table.m_categoryLabels.Count) ? table.m_categoryLabels[i] : "");
			if (!string.IsNullOrWhiteSpace(text2) && !string.Equals(text2, text, StringComparison.OrdinalIgnoreCase))
			{
				return text2;
			}
			string text3 = "biome_" + text.ToLowerInvariant();
			if (Localization.instance.m_translations.ContainsKey(text3))
			{
				return "$" + text3;
			}
			return Regex.Replace(text, "(?<=[a-z])(?=[A-Z])", " ");
		}

		private static void EnsureTabCount(Hud hud, int needed)
		{
			if (TabManagerPresent)
			{
				return;
			}
			GameObject[] pieceCategoryTabs = hud.m_pieceCategoryTabs;
			if (pieceCategoryTabs.Length >= needed || pieceCategoryTabs.Length == 0)
			{
				return;
			}
			GameObject val = pieceCategoryTabs[^1];
			GameObject[] array = (GameObject[])(object)new GameObject[needed];
			Array.Copy(pieceCategoryTabs, array, pieceCategoryTabs.Length);
			for (int i = pieceCategoryTabs.Length; i < needed; i++)
			{
				GameObject val2 = Object.Instantiate<GameObject>(val, val.transform.parent);
				((Object)val2).name = "Tab" + i;
				UIInputHandler component = val2.GetComponent<UIInputHandler>();
				if ((Object)(object)component != (Object)null)
				{
					component.m_onLeftDown = (Action<UIInputHandler>)Delegate.Combine(component.m_onLeftDown, new Action<UIInputHandler>(hud.OnLeftClickCategory));
				}
				array[i] = val2;
			}
			hud.m_pieceCategoryTabs = array;
		}

		[HarmonyPatch(typeof(KeyHints), "UpdateHints")]
		[HarmonyPostfix]
		private static void KeyHints_UpdateHints(KeyHints __instance)
		{
			if (On(Hud.instance) && Hud.IsPieceSelectionVisible())
			{
				HideFavoriteHints(__instance.m_buildMenuHintsKB);
				HideFavoriteHints(__instance.m_buildMenuHintsGP);
			}
		}

		private static void HideFavoriteHints(GameObject[]? hints)
		{
			if (hints == null)
			{
				return;
			}
			foreach (GameObject val in hints)
			{
				if ((Object)(object)val != (Object)null && val.activeSelf && ((Object)val).name.IndexOf("Favorite", StringComparison.OrdinalIgnoreCase) >= 0)
				{
					val.SetActive(false);
				}
			}
		}

		[HarmonyPatch(typeof(Player), "UpdateBuildGuiInput")]
		[HarmonyPrefix]
		private static bool Player_UpdateBuildGuiInput(Player __instance)
		{
			if (!On(Hud.instance))
			{
				return true;
			}
			try
			{
				if (ZInput.IsNonClassicFunctionality() && ZInput.IsGamepadActive())
				{
					AlternativeLayoutInput(__instance);
				}
				else
				{
					DefaultInput(__instance);
				}
			}
			catch (Exception ex)
			{
				LegacyBuildMenuPlugin.LogErrorOnce("legacy build menu input", ex);
			}
			return false;
		}

		private static void DefaultInput(Player player)
		{
			if (!Hud.IsPieceSelectionVisible())
			{
				if (ZInput.GetButtonDown("BuildMenu") && !PlayerController.HasInputDelay && !Hud.InRadial())
				{
					Hud.instance.TogglePieceSelection();
				}
				else if (ZInput.GetButtonDown("JoyUse") && !PlayerController.HasInputDelay && !Hud.InRadial())
				{
					Hud.instance.TogglePieceSelection();
				}
				return;
			}
			if (ZInput.GetKeyDown((KeyCode)27, true) || ZInput.GetButtonDown("JoyButtonB") || ZInput.GetButtonDown("BuildMenu"))
			{
				Hud.HidePieceSelection();
			}
			if (ZInput.GetButtonDown("JoyUse"))
			{
				Hud.HidePieceSelection();
				player.PlayButtonSound();
			}
			MenuNavigation(player);
		}

		private static void AlternativeLayoutInput(Player player)
		{
			//IL_00ce: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d3: Unknown result type (might be due to invalid IL or missing references)
			//IL_0060: Unknown result type (might be due to invalid IL or missing references)
			//IL_0065: Unknown result type (might be due to invalid IL or missing references)
			PieceTable buildPieces = player.m_buildPieces;
			if (!Hud.IsPieceSelectionVisible())
			{
				if (ZInput.GetButtonDown("JoyBuildMenu") && !PlayerController.HasInputDelay && !Hud.InRadial() && player.m_lastBuildStateFrames > 1)
				{
					player.m_lastBuildStateFrames = 0;
					for (int i = 0; i < buildPieces.m_selectedPiece.Length; i++)
					{
						buildPieces.m_lastSelectedPiece[i] = buildPieces.m_selectedPiece[i];
					}
					Hud.instance.TogglePieceSelection();
				}
				return;
			}
			if (ZInput.GetKeyDown((KeyCode)27, true) || ZInput.GetButtonDown("JoyButtonB") || ZInput.GetButtonDown("BuildMenu"))
			{
				for (int j = 0; j < buildPieces.m_selectedPiece.Length; j++)
				{
					buildPieces.m_selectedPiece[j] = buildPieces.m_lastSelectedPiece[j];
				}
				Hud.HidePieceSelection();
				player.SetupPlacementGhost();
			}
			if (ZInput.GetButtonDown("JoyButtonA"))
			{
				Hud.HidePieceSelection();
				player.PlayButtonSound();
			}
			MenuNavigation(player);
		}

		private static void MenuNavigation(Player player)
		{
			PieceTable buildPieces = player.m_buildPieces;
			player.m_scrollCurrAmount += ZInput.GetMouseScrollWheel();
			if (ZInput.GetButtonDown("JoyTabLeft") || ZInput.GetButtonDown("TabLeft") || player.m_scrollCurrAmount > player.m_scrollAmountThreshold)
			{
				player.m_scrollCurrAmount = 0f;
				buildPieces.PrevCategory();
				player.UpdateAvailablePiecesList();
			}
			if (ZInput.GetButtonDown("JoyTabRight") || ZInput.GetButtonDown("TabRight") || player.m_scrollCurrAmount < 0f - player.m_scrollAmountThreshold)
			{
				player.m_scrollCurrAmount = 0f;
				buildPieces.NextCategory();
				player.UpdateAvailablePiecesList();
			}
			if (ZInput.GetButtonDown("JoyLStickLeft") || ZInput.GetButtonDown("JoyDPadLeft"))
			{
				buildPieces.LeftPiece();
				player.SetupPlacementGhost();
			}
			if (ZInput.GetButtonDown("JoyLStickRight") || ZInput.GetButtonDown("JoyDPadRight"))
			{
				buildPieces.RightPiece();
				player.SetupPlacementGhost();
			}
			if (ZInput.GetButtonDown("JoyLStickUp") || ZInput.GetButtonDown("JoyDPadUp"))
			{
				buildPieces.UpPiece();
				player.SetupPlacementGhost();
			}
			if (ZInput.GetButtonDown("JoyLStickDown") || ZInput.GetButtonDown("JoyDPadDown"))
			{
				buildPieces.DownPiece();
				player.SetupPlacementGhost();
			}
		}

		[HarmonyPatch(typeof(PieceTable), "UpdateAvailable")]
		[HarmonyPrefix]
		private static void PieceTable_UpdateAvailable(PieceTable __instance)
		{
			if (!Enabled)
			{
				return;
			}
			Piece val = default(Piece);
			foreach (GameObject piece in __instance.m_pieces)
			{
				if ((Object)(object)piece == (Object)null || !piece.TryGetComponent<Piece>(ref val))
				{
					continue;
				}
				Requirement[] resources = val.m_resources;
				if (resources == null)
				{
					val.m_resources = Array.Empty<Requirement>();
				}
				else if (!resources.All((Requirement r) => r != null && (Object)(object)r.m_resItem != (Object)null))
				{
					val.m_resources = resources.Where((Requirement r) => r != null && (Object)(object)r.m_resItem != (Object)null).ToArray();
					if (_reportedBadPieces.Add(((Object)piece).name))
					{
						LegacyBuildMenuPlugin.Log.LogWarning((object)("Piece '" + ((Object)piece).name + "' had requirements with no item, dropped them (they cost nothing anyway). Whichever mod adds it should fix its recipe."));
					}
				}
			}
		}

		[HarmonyPatch(typeof(Hud), "SetupPieceInfo")]
		[HarmonyFinalizer]
		private static Exception? Hud_SetupPieceInfo(Exception? __exception, Piece piece)
		{
			if (__exception == null || !Enabled)
			{
				return __exception;
			}
			string text = (((Object)(object)piece != (Object)null) ? ((Object)piece).name : "<null>");
			if (_reportedBadPieces.Add(text + "#info"))
			{
				LegacyBuildMenuPlugin.Log.LogWarning((object)("Piece '" + text + "' broke the build menu's info panel (" + __exception.GetType().Name + ": " + __exception.Message + "), ignoring it."));
			}
			return null;
		}
	}
	internal static class LegacyWindow
	{
		[CompilerGenerated]
		private static class <>O
		{
			public static Action<Vector2> <0>__OnResizeDrag;

			public static Action<Vector2> <1>__OnMoveDrag;

			public static UnityAction<string> <2>__OnSearchChanged;

			public static UnityAction <3>__ClearSearch;
		}

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

			public static UnityAction <>9__48_0;

			public static Func<Button, bool> <>9__48_1;

			public static Func<ButtonSfx, bool> <>9__49_0;

			internal void <StyleVanillaButton>b__48_0()
			{
				EventSystem current = EventSystem.current;
				if (current != null)
				{
					current.SetSelectedGameObject((GameObject)null);
				}
			}

			internal bool <StyleVanillaButton>b__48_1(Button b)
			{
				Graphic targetGraphic = ((Selectable)b).targetGraphic;
				Image val = (Image)(((object)((targetGraphic is Image) ? targetGraphic : null)) ?? ((object)((Component)b).GetComponent<Image>()));
				return (Object)(object)val != (Object)null && (Object)(object)val.sprite != (Object)null && ((Object)val.sprite).name.IndexOf("button", StringComparison.OrdinalIgnoreCase) >= 0;
			}

			internal bool <AttachClickSfx>b__49_0(ButtonSfx s)
			{
				return (Object)(object)s != (Object)null && (Object)(object)s.m_sfxPrefab != (Object)null;
			}
		}

		private const float SearchStripHeight = 30f;

		private const float StripGap = 2f;

		private const float ScrollbarGutter = 10f;

		private const float SearchDebounce = 0.2f;

		private static Hud? _builtFor;

		private static ScrollRect? _scrollRect;

		private static RectTransform? _searchStrip;

		private static TMP_InputField? _searchField;

		private static GameObject? _clearButton;

		private static Vector2 _origWindowSize;

		private static Vector2 _origWindowPos;

		private static Coroutine? _debounce;

		private static TMP_FontAsset? _font;

		internal static int Columns { get; private set; } = 15;

		internal static PieceSearch Query { get; private set; } = PieceSearch.Parse(null);

		internal static bool IsSearchFocused => (Object)(object)_searchField != (Object)null && _searchField.isFocused;

		internal static float Spacing(Hud hud)
		{
			return (hud.m_pieceIconSpacing > 0f) ? hud.m_pieceIconSpacing : 64f;
		}

		internal static int RowCount(int count)
		{
			return Mathf.Max(1, Mathf.CeilToInt((float)count / (float)Columns));
		}

		internal static void RefreshColumns(Hud hud)
		{
			//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)
			float num = Spacing(hud);
			float num2;
			if (!((Object)(object)_scrollRect != (Object)null) || !((Object)(object)_scrollRect.viewport != (Object)null))
			{
				num2 = 15f * num + 10f;
			}
			else
			{
				Rect rect = _scrollRect.viewport.rect;
				num2 = ((Rect)(ref rect)).width;
			}
			float num3 = num2;
			Columns = Mathf.Clamp(Mathf.FloorToInt((num3 - 10f) / num + 0.01f), 1, 64);
		}

		internal static void EnsureBuilt(Hud hud)
		{
			//IL_005c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0062: Expected O, but got Unknown
			//IL_0063: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: Unknown result type (might be due to invalid IL or missing references)
			//IL_006e: 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_0094: 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_00a4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ae: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bf: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cf: Unknown result type (might be due to invalid IL or missing references)
			//IL_00db: Unknown result type (might be due to invalid IL or missing references)
			//IL_011a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0129: Unknown result type (might be due to invalid IL or missing references)
			//IL_0164: Unknown result type (might be due to invalid IL or missing references)
			//IL_0173: Unknown result type (might be due to invalid IL or missing references)
			if (_builtFor == hud && (Object)(object)_builtFor != (Object)null)
			{
				return;
			}
			_builtFor = hud;
			_scrollRect = null;
			_searchStrip = null;
			_searchField = null;
			_clearButton = null;
			Query = PieceSearch.Parse(null);
			ModIndex.Invalidate();
			try
			{
				RectTransform val = (RectTransform)hud.m_pieceSelectionWindow.transform;
				_origWindowSize = val.sizeDelta;
				_origWindowPos = val.anchoredPosition;
				SetupScrollView(hud);
				if (LegacyBuildMenuPlugin.ShowSearchBar.Value)
				{
					float num = 32f;
					_origWindowSize += new Vector2(0f, num);
					_origWindowPos -= new Vector2(0f, num * 0.5f);
					val.sizeDelta = _origWindowSize;
					val.anchoredPosition = _origWindowPos;
					ReserveHeader(hud, num);
					CreateSearchStrip(hud);
				}
				if (LegacyBuildMenuPlugin.ResizableWindow.Value)
				{
					CreateGrip(hud, "LegacyBuildMenu_Resize", new Vector2(1f, 0f), new Vector2(-6f, 6f), "◢", OnResizeDrag);
					CreateGrip(hud, "LegacyBuildMenu_Move", new Vector2(0f, 0f), new Vector2(6f, 6f), "≡", OnMoveDrag);
				}
			}
			catch (Exception arg)
			{
				LegacyBuildMenuPlugin.Log.LogError((object)$"Couldn't set up the build menu window: {arg}");
			}
		}

		private static void SetupScrollView(Hud hud)
		{
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			//IL_0172: Unknown result type (might be due to invalid IL or missing references)
			//IL_0178: Expected O, but got Unknown
			//IL_018c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0192: Expected O, but got Unknown
			//IL_019d: 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_01c9: Unknown result type (might be due to invalid IL or missing references)
			//IL_01df: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f5: Unknown result type (might be due to invalid IL or missing references)
			//IL_0227: Unknown result type (might be due to invalid IL or missing references)
			//IL_024a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0251: Expected O, but got Unknown
			//IL_026c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0273: Expected O, but got Unknown
			//IL_0275: Unknown result type (might be due to invalid IL or missing references)
			//IL_0282: Unknown result type (might be due to invalid IL or missing references)
			//IL_028f: Unknown result type (might be due to invalid IL or missing references)
			//IL_02c2: Unknown result type (might be due to invalid IL or missing references)
			//IL_02f6: Unknown result type (might be due to invalid IL or missing references)
			//IL_0305: Unknown result type (might be due to invalid IL or missing references)
			//IL_014e: Unknown result type (might be due to invalid IL or missing references)
			RectTransform pieceListMask = hud.m_pieceListMask;
			RectTransform pieceListRoot = hud.m_pieceListRoot;
			if (!((Object)(object)pieceListMask == (Object)null) && !((Object)(object)pieceListRoot == (Object)null))
			{
				pieceListMask.offsetMax += new Vector2(10f, 0f);
				_scrollRect = ((Component)pieceListMask).GetComponent<ScrollRect>();
				if ((Object)(object)_scrollRect == (Object)null)
				{
					_scrollRect = ((Component)pieceListMask).gameObject.AddComponent<ScrollRect>();
				}
				_scrollRect.content = pieceListRoot;
				_scrollRect.viewport = pieceListMask;
				_scrollRect.horizontal = false;
				_scrollRect.vertical = true;
				_scrollRect.movementType = (MovementType)2;
				_scrollRect.inertia = true;
				_scrollRect.decelerationRate = 0.135f;
				_scrollRect.scrollSensitivity = Spacing(hud) * 4f;
				if ((Object)(object)((Component)pieceListMask).GetComponent<Mask>() == (Object)null && (Object)(object)((Component)pieceListMask).GetComponent<RectMask2D>() == (Object)null)
				{
					((Component)pieceListMask).gameObject.AddComponent<RectMask2D>();
				}
				if ((Object)(object)((Component)pieceListMask).GetComponent<Graphic>() == (Object)null)
				{
					Image val = ((Component)pieceListMask).gameObject.AddComponent<Image>();
					((Graphic)val).color = new Color(0f, 0f, 0f, 0f);
				}
				GameObject val2 = new GameObject("LegacyBuildMenu_Scrollbar", new Type[1] { typeof(RectTransform) });
				val2.transform.SetParent((Transform)(object)pieceListMask, false);
				RectTransform val3 = (RectTransform)val2.transform;
				val3.anchorMin = new Vector2(1f, 0f);
				val3.anchorMax = new Vector2(1f, 1f);
				val3.pivot = new Vector2(1f, 0.5f);
				val3.anchoredPosition = new Vector2(-1f, 0f);
				val3.sizeDelta = new Vector2(9f, 0f);
				Image val4 = val2.AddComponent<Image>();
				StyleTabImage(hud, val4);
				((Graphic)val4).color = new Color(0.191f, 0.078f, 0.078f, 1f);
				GameObject val5 = new GameObject("Handle", new Type[1] { typeof(RectTransform) });
				val5.transform.SetParent(val2.transform, false);
				RectTransform val6 = (RectTransform)val5.transform;
				val6.anchorMin = Vector2.zero;
				val6.anchorMax = Vector2.one;
				val6.sizeDelta = Vector2.zero;
				Image val7 = val5.AddComponent<Image>();
				StyleTabImage(hud, val7);
				((Graphic)val7).color = new Color(0.8529f, 0.725f, 0.5331f, 1f);
				Scrollbar val8 = val2.AddComponent<Scrollbar>();
				val8.handleRect = val6;
				val8.direction = (Direction)2;
				((Selectable)val8).targetGraphic = (Graphic)(object)val7;
				Navigation navigation = default(Navigation);
				((Navigation)(ref navigation)).mode = (Mode)0;
				((Selectable)val8).navigation = navigation;
				_scrollRect.verticalScrollbar = val8;
				_scrollRect.verticalScrollbarVisibility = (ScrollbarVisibility)1;
			}
		}

		internal static void SetContentHeight(Hud hud, int count)
		{
			//IL_0051: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)_scrollRect == (Object)null) && !((Object)(object)_scrollRect.content == (Object)null))
			{
				float num = Spacing(hud);
				_scrollRect.content.sizeDelta = new Vector2((float)Columns * num, (float)RowCount(count) * num + num * 0.25f);
			}
		}

		internal static void ScrollToTop()
		{
			//IL_0044: 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)
			if (!((Object)(object)_scrollRect == (Object)null) && !((Object)(object)_scrollRect.content == (Object)null))
			{
				_scrollRect.verticalNormalizedPosition = 1f;
				RectTransform content = _scrollRect.content;
				content.anchoredPosition = new Vector2(content.anchoredPosition.x, 0f);
			}
		}

		internal static bool ShouldEatWheel()
		{
			//IL_0045: Unknown result type (might be due to invalid IL or missing references)
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			//IL_005c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0061: Unknown result type (might be due to invalid IL or missing references)
			//IL_0086: 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)
			if ((Object)(object)_scrollRect == (Object)null || (Object)(object)_scrollRect.viewport == (Object)null || (Object)(object)_scrollRect.content == (Object)null)
			{
				return false;
			}
			Rect rect = _scrollRect.content.rect;
			float height = ((Rect)(ref rect)).height;
			rect = _scrollRect.viewport.rect;
			if (height <= ((Rect)(ref rect)).height + 1f)
			{
				return false;
			}
			return RectTransformUtility.RectangleContainsScreenPoint(_scrollRect.viewport, Vector2.op_Implicit(Input.mousePosition), (Camera)null);
		}

		private static void ReserveHeader(Hud hud, float height)
		{
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			RectTransform pieceListMask = hud.m_pieceListMask;
			pieceListMask.offsetMax = new Vector2(pieceListMask.offsetMax.x, pieceListMask.offsetMax.y - height);
		}

		private static void CreateSearchStrip(Hud hud)
		{
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: Expected O, but got Unknown
			//IL_004c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0056: Expected O, but got Unknown
			//IL_007a: Unknown result type (might be due to invalid IL or missing references)
			//IL_009d: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a3: Expected O, but got Unknown
			//IL_00bc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c3: Expected O, but got Unknown
			//IL_00c5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e9: Unknown result type (might be due to invalid IL or missing references)
			//IL_0100: Unknown result type (might be due to invalid IL or missing references)
			//IL_012e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0135: Expected O, but got Unknown
			//IL_0150: Unknown result type (might be due to invalid IL or missing references)
			//IL_0157: Expected O, but got Unknown
			//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_017d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0194: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f3: Unknown result type (might be due to invalid IL or missing references)
			//IL_0274: Unknown result type (might be due to invalid IL or missing references)
			//IL_0283: Unknown result type (might be due to invalid IL or missing references)
			TMP_FontAsset val = UiFont(hud);
			GameObject val2 = new GameObject("LegacyBuildMenu_Search", new Type[1] { typeof(RectTransform) });
			val2.SetActive(false);
			val2.transform.SetParent(hud.m_pieceSelectionWindow.transform, false);
			_searchStrip = (RectTransform)val2.transform;
			Image val3 = val2.AddComponent<Image>();
			StyleTabImage(hud, val3);
			((Graphic)val3).color = new Color(0f, 0f, 0f, 0.65f);
			GameObject val4 = new GameObject("InputField", new Type[1] { typeof(RectTransform) });
			val4.transform.SetParent(val2.transform, false);
			RectTransform val5 = (RectTransform)val4.transform;
			val5.anchorMin = Vector2.zero;
			val5.anchorMax = Vector2.one;
			val5.offsetMin = new Vector2(6f, 3f);
			val5.offsetMax = new Vector2(-36f, -3f);
			_searchField = val4.AddComponent<TMP_InputField>();
			GameObject val6 = new GameObject("TextArea", new Type[1] { typeof(RectTransform) });
			val6.transform.SetParent(val4.transform, false);
			RectTransform val7 = (RectTransform)val6.transform;
			val7.anchorMin = Vector2.zero;
			val7.anchorMax = Vector2.one;
			val7.offsetMin = new Vector2(8f, 0f);
			val7.offsetMax = new Vector2(-8f, 0f);
			val6.AddComponent<RectMask2D>();
			TMP_Text val8 = CreateText((Transform)(object)val7, "Placeholder", val, 14f, new Color(0.6f, 0.6f, 0.6f, 0.6f), (TextAlignmentOptions)4097);
			val8.text = "Search...     @mod     !material";
			TMP_Text textComponent = CreateText((Transform)(object)val7, "Text", val, 14f, Color.white, (TextAlignmentOptions)4097);
			_searchField.textViewport = val7;
			_searchField.textComponent = textComponent;
			_searchField.placeholder = (Graphic)(object)val8;
			if ((Object)(object)val != (Object)null)
			{
				_searchField.fontAsset = val;
			}
			_searchField.pointSize = 14f;
			_searchField.lineType = (LineType)0;
			_searchField.characterLimit = 100;
			TMP_InputField? searchField = _searchField;
			Navigation navigation = default(Navigation);
			((Navigation)(ref navigation)).mode = (Mode)0;
			((Selectable)searchField).navigation = navigation;
			((UnityEvent<string>)(object)_searchField.onValueChanged).AddListener((UnityAction<string>)OnSearchChanged);
			CreateClearButton(hud, val2.transform, val);
			val2.SetActive(true);
			Relayout(hud);
		}

		private static void CreateClearButton(Hud hud, Transform parent, TMP_FontAsset? font)
		{
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: Expected O, but got Unknown
			//IL_004b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0051: Expected O, but got Unknown
			//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_006f: 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_0078: 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_00a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_0109: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ec: Expected O, but got Unknown
			_clearButton = new GameObject("Clear", new Type[1] { typeof(RectTransform) });
			_clearButton.SetActive(false);
			_clearButton.transform.SetParent(parent, false);
			RectTransform val = (RectTransform)_clearButton.transform;
			Vector2 val2 = default(Vector2);
			((Vector2)(ref val2))..ctor(1f, 0.5f);
			val.pivot = val2;
			Vector2 anchorMin = (val.anchorMax = val2);
			val.anchorMin = anchorMin;
			val.anchoredPosition = new Vector2(-4f, 0f);
			val.sizeDelta = new Vector2(26f, 26f);
			Image img = _clearButton.AddComponent<Image>();
			Button val4 = _clearButton.AddComponent<Button>();
			StyleVanillaButton(hud, val4, img);
			ButtonClickedEvent onClick = val4.onClick;
			object obj = <>O.<3>__ClearSearch;
			if (obj == null)
			{
				UnityAction val5 = ClearSearch;
				<>O.<3>__ClearSearch = val5;
				obj = (object)val5;
			}
			((UnityEvent)onClick).AddListener((UnityAction)obj);
			AttachClickSfx(_clearButton);
			TMP_Text val6 = CreateText((Transform)(object)val, "Text", font, 18f, Color.white, (TextAlignmentOptions)514);
			val6.text = "X";
		}

		private static void Relayout(Hud hud)
		{
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Expected O, but got Unknown
			//IL_0047: Unknown result type (might be due to invalid IL or missing references)
			//IL_004c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0051: 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_0075: Unknown result type (might be due to invalid IL or missing references)
			//IL_008c: Unknown result type (might be due to invalid IL or missing references)
			//IL_009d: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d1: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)_searchStrip == (Object)null))
			{
				Canvas.ForceUpdateCanvases();
				RectTransform val = (RectTransform)hud.m_pieceSelectionWindow.transform;
				RectTransform pieceListMask = hud.m_pieceListMask;
				Vector3[] array = (Vector3[])(object)new Vector3[4];
				pieceListMask.GetWorldCorners(array);
				Vector3 val2 = ((Transform)val).InverseTransformPoint(array[1]);
				RectTransform? searchStrip = _searchStrip;
				RectTransform? searchStrip2 = _searchStrip;
				Vector2 val3 = default(Vector2);
				((Vector2)(ref val3))..ctor(0.5f, 0.5f);
				searchStrip2.anchorMax = val3;
				searchStrip.anchorMin = val3;
				_searchStrip.pivot = new Vector2(0.5f, 0f);
				RectTransform? searchStrip3 = _searchStrip;
				Rect rect = pieceListMask.rect;
				searchStrip3.sizeDelta = new Vector2(((Rect)(ref rect)).width, 30f);
				_searchStrip.anchoredPosition = new Vector2(0f, val2.y + 2f);
			}
		}

		private static void OnSearchChanged(string text)
		{
			if ((Object)(object)_clearButton != (Object)null)
			{
				_clearButton.SetActive(!string.IsNullOrEmpty(text));
			}
			if (!((Object)(object)Hud.instance == (Object)null))
			{
				if (_debounce != null)
				{
					((MonoBehaviour)Hud.instance).StopCoroutine(_debounce);
				}
				_debounce = ((MonoBehaviour)Hud.instance).StartCoroutine(ApplySearchLater(text));
			}
		}

		private static IEnumerator ApplySearchLater(string text)
		{
			yield return (object)new WaitForSecondsRealtime(0.2f);
			_debounce = null;
			ApplySearch(text);
		}

		private static void ApplySearch(string text)
		{
			Query = PieceSearch.Parse(text);
			Player localPlayer = Player.m_localPlayer;
			if ((Object)(object)localPlayer != (Object)null && (Object)(object)localPlayer.m_buildPieces != (Object)null)
			{
				localPlayer.UpdateAvailablePiecesList();
			}
			ScrollToTop();
		}

		internal static void ClearSearch()
		{
			if (!((Object)(object)_searchField == (Object)null) && !string.IsNullOrEmpty(_searchField.text))
			{
				_searchField.text = "";
				if (_debounce != null && (Object)(object)Hud.instance != (Object)null)
				{
					((MonoBehaviour)Hud.instance).StopCoroutine(_debounce);
				}
				_debounce = null;
				ApplySearch("");
			}
		}

		private static void CreateGrip(Hud hud, string name, Vector2 corner, Vector2 offset, string glyph, Action<Vector2> onDrag)
		{
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: Expected O, but got Unknown
			//IL_004b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0051: Expected O, but got Unknown
			//IL_0054: 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_0056: 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_0060: Unknown result type (might be due to invalid IL or missing references)
			//IL_0061: Unknown result type (might be due to invalid IL or missing references)
			//IL_0069: Unknown result type (might be due to invalid IL or missing references)
			//IL_0072: Unknown result type (might be due to invalid IL or missing references)
			//IL_0084: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bf: 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_00fb: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = new GameObject(name, new Type[1] { typeof(RectTransform) });
			val.transform.SetParent(hud.m_pieceSelectionWindow.transform, false);
			RectTransform val2 = (RectTransform)val.transform;
			Vector2 val3 = (val2.pivot = corner);
			Vector2 anchorMin = (val2.anchorMax = val3);
			val2.anchorMin = anchorMin;
			val2.anchoredPosition = offset;
			val2.sizeDelta = new Vector2(34f, 34f);
			Image val6 = val.AddComponent<Image>();
			val6.sprite = GripHandle.RoundedRect();
			val6.type = (Type)1;
			((Graphic)val6).color = new Color(0.565f, 0.792f, 0.976f, 0.85f);
			val.AddComponent<Shadow>().effectDistance = new Vector2(2f, -2f);
			TMP_Text val7 = CreateText((Transform)(object)val2, "Icon", UiFont(hud), 22f, Color.white, (TextAlignmentOptions)514);
			val7.text = glyph;
			((Graphic)val7).raycastTarget = false;
			CanvasGroup val8 = val.AddComponent<CanvasGroup>();
			val8.alpha = 0f;
			GripHandle gripHandle = val.AddComponent<GripHandle>();
			gripHandle.Dragged = onDrag;
			gripHandle.Ended = delegate
			{
				KeepOnScreen(hud);
			};
			val.transform.SetAsLastSibling();
		}

		private static Vector2 ClampSizeOffset(Vector2 o)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			return new Vector2(Mathf.Clamp(o.x, -300f, 900f), Mathf.Clamp(o.y, -150f, 600f));
		}

		private static void OnResizeDrag(Vector2 delta)
		{
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: Expected O, but got Unknown
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_003b: Unknown result type (might be due to invalid IL or missing references)
			//IL_003c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0042: Unknown result type (might be due to invalid IL or missing references)
			//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)
			//IL_0053: Unknown result type (might be due to invalid IL or missing references)
			Hud instance = Hud.instance;
			if (!((Object)(object)instance == (Object)null))
			{
				RectTransform val = (RectTransform)instance.m_pieceSelectionWindow.transform;
				Vector2 val2 = val.sizeDelta - _origWindowSize;
				LegacyBuildMenuPlugin.WindowSize.Value = ClampSizeOffset(val2 + new Vector2(delta.x, 0f - delta.y));
				ApplyWindow(instance);
			}
		}

		private static void OnMoveDrag(Vector2 delta)
		{
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			Hud instance = Hud.instance;
			if (!((Object)(object)instance == (Object)null))
			{
				ConfigEntry<Vector2> windowPos = LegacyBuildMenuPlugin.WindowPos;
				windowPos.Value += delta;
				ApplyWindow(instance);
			}
		}

		internal static void ApplyWindow(Hud hud)
		{
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: Expected O, but got Unknown
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			//IL_0061: 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_0066: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: Unknown result type (might be due to invalid IL or missing references)
			//IL_006d: Unknown result type (might be due to invalid IL or missing references)
			//IL_006e: Unknown result type (might be due to invalid IL or missing references)
			//IL_007a: Unknown result type (might be due to invalid IL or missing references)
			//IL_007f: Unknown result type (might be due to invalid IL or missing references)
			//IL_008b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0098: Unknown result type (might be due to invalid IL or missing references)
			//IL_009d: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a3: Unknown result type (might be due to invalid IL or missing references)
			if (_builtFor == hud)
			{
				RectTransform val = (RectTransform)hud.m_pieceSelectionWindow.transform;
				Vector2 val2 = (LegacyBuildMenuPlugin.ResizableWindow.Value ? ClampSizeOffset(LegacyBuildMenuPlugin.WindowSize.Value) : Vector2.zero);
				Vector2 val3 = (LegacyBuildMenuPlugin.ResizableWindow.Value ? LegacyBuildMenuPlugin.WindowPos.Value : Vector2.zero);
				val.sizeDelta = _origWindowSize + val2;
				val.anchoredPosition = _origWindowPos + new Vector2(val2.x * 0.5f, (0f - val2.y) * 0.5f) + val3;
				KeepOnScreen(hud);
				Relayout(hud);
				RefreshColumns(hud);
			}
		}

		private static void KeepOnScreen(Hud hud)
		{
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0012: Expected O, but got Unknown
			//IL_004f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0055: Expected O, but got Unknown
			//IL_0056: Unknown result type (might be due to invalid IL or missing references)
			//IL_005b: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_0081: Unknown result type (might be due to invalid IL or missing references)
			//IL_0087: Unknown result type (might be due to invalid IL or missing references)
			//IL_008c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0091: 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_00d7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cc: Unknown result type (might be due to invalid IL or missing references)
			//IL_010d: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f5: Unknown result type (might be due to invalid IL or missing references)
			//IL_0143: 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_0161: Unknown result type (might be due to invalid IL or missing references)
			//IL_0198: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a1: 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_01b7: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c5: Unknown result type (might be due to invalid IL or missing references)
			RectTransform val = (RectTransform)hud.m_pieceSelectionWindow.transform;
			if (!((Component)val).gameObject.activeInHierarchy)
			{
				return;
			}
			Canvas componentInParent = ((Component)val).GetComponentInParent<Canvas>();
			if (!((Object)(object)componentInParent == (Object)null))
			{
				RectTransform val2 = (RectTransform)((Component)componentInParent.rootCanvas).transform;
				Rect rect = val2.rect;
				Canvas.ForceUpdateCanvases();
				Vector3[] array = (Vector3[])(object)new Vector3[4];
				val.GetWorldCorners(array);
				Vector3 val3 = ((Transform)val2).InverseTransformPoint(array[0]);
				Vector3 val4 = ((Transform)val2).InverseTransformPoint(array[2]);
				float num = 0f;
				float num2 = 0f;
				if (val3.x < ((Rect)(ref rect)).xMin + 8f)
				{
					num += ((Rect)(ref rect)).xMin + 8f - val3.x;
				}
				if (val4.x > ((Rect)(ref rect)).xMax - 8f)
				{
					num -= val4.x - (((Rect)(ref rect)).xMax - 8f);
				}
				if (val3.y < ((Rect)(ref rect)).yMin + 8f)
				{
					num2 += ((Rect)(ref rect)).yMin + 8f - val3.y;
				}
				if (val4.y > ((Rect)(ref rect)).yMax - 8f)
				{
					num2 -= val4.y - (((Rect)(ref rect)).yMax - 8f);
				}
				if (num != 0f || num2 != 0f)
				{
					val.anchoredPosition += new Vector2(num, num2);
					ConfigEntry<Vector2> windowPos = LegacyBuildMenuPlugin.WindowPos;
					windowPos.Value += new Vector2(num, num2);
				}
			}
		}

		private static TMP_FontAsset? UiFont(Hud hud)
		{
			if ((Object)(object)_font != (Object)null)
			{
				return _font;
			}
			_font = (((Object)(object)hud.m_buildSelection != (Object)null) ? hud.m_buildSelection.font : null);
			if ((Object)(object)_font == (Object)null && (Object)(object)hud.m_pieceDescription != (Object)null)
			{
				_font = hud.m_pieceDescription.font;
			}
			if ((Object)(object)_font == (Object)null)
			{
				TMP_Text componentInChildren = hud.m_pieceSelectionWindow.GetComponentInChildren<TMP_Text>(true);
				_font = ((componentInChildren != null) ? componentInChildren.font : null);
			}
			return _font;
		}

		private static TMP_Text CreateText(Transform parent, string name, TMP_FontAsset? font, float size, Color color, TextAlignmentOptions align)
		{
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Expected O, but got Unknown
			//IL_0054: Unknown result type (might be due to invalid IL or missing references)
			//IL_005d: Unknown result type (might be due to invalid IL or missing references)
			//IL_006d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0079: Unknown result type (might be due to invalid IL or missing references)
			//IL_0085: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = new GameObject(name, new Type[1] { typeof(RectTransform) });
			val.SetActive(false);
			val.transform.SetParent(parent, false);
			TextMeshProUGUI val2 = val.AddComponent<TextMeshProUGUI>();
			if ((Object)(object)font != (Object)null)
			{
				((TMP_Text)val2).font = font;
			}
			((TMP_Text)val2).fontSize = size;
			((Graphic)val2).color = color;
			((TMP_Text)val2).alignment = align;
			RectTransform rectTransform = ((TMP_Text)val2).rectTransform;
			rectTransform.anchorMin = Vector2.zero;
			rectTransform.anchorMax = Vector2.one;
			rectTransform.sizeDelta = Vector2.zero;
			val.SetActive(true);
			return (TMP_Text)(object)val2;
		}

		private static void StyleTabImage(Hud hud, Image img)
		{
			if (hud.m_pieceCategoryTabs != null && hud.m_pieceCategoryTabs.Length != 0 && !((Object)(object)hud.m_pieceCategoryTabs[0] == (Object)null))
			{
				Image component = hud.m_pieceCategoryTabs[0].GetComponent<Image>();
				if (!((Object)(object)component == (Object)null) && !((Object)(object)component.sprite == (Object)null))
				{
					img.sprite = component.sprite;
					img.type = (Type)1;
				}
			}
		}

		private static void StyleVanillaButton(Hud hud, Button btn, Image img)
		{
			//IL_0004: Unknown result type (might be due to invalid IL or missing references)
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			//IL_003f: Expected O, but got Unknown
			//IL_00c2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cf: Unknown result type (might be due to invalid IL or missing references)
			//IL_00dc: Unknown result type (might be due to invalid IL or missing references)
			Navigation navigation = default(Navigation);
			((Navigation)(ref navigation)).mode = (Mode)0;
			((Selectable)btn).navigation = navigation;
			ButtonClickedEvent onClick = btn.onClick;
			object obj = <>c.<>9__48_0;
			if (obj == null)
			{
				UnityAction val = delegate
				{
					EventSystem current = EventSystem.current;
					if (current != null)
					{
						current.SetSelectedGameObject((GameObject)null);
					}
				};
				<>c.<>9__48_0 = val;
				obj = (object)val;
			}
			((UnityEvent)onClick).AddListener((UnityAction)obj);
			Button val2 = ((IEnumerable<Button>)Resources.FindObjectsOfTypeAll<Button>()).FirstOrDefault((Func<Button, bool>)delegate(Button b)
			{
				Graphic targetGraphic2 = ((Selectable)b).targetGraphic;
				Image val4 = (Image)(((object)((targetGraphic2 is Image) ? targetGraphic2 : null)) ?? ((object)((Component)b).GetComponent<Image>()));
				return (Object)(object)val4 != (Object)null && (Object)(object)val4.sprite != (Object)null && ((Object)val4.sprite).name.IndexOf("button", StringComparison.OrdinalIgnoreCase) >= 0;
			});
			if ((Object)(object)val2 == (Object)null)
			{
				StyleTabImage(hud, img);
				((Selectable)btn).targetGraphic = (Graphic)(object)img;
				return;
			}
			Graphic targetGraphic = ((Selectable)val2).targetGraphic;
			Image val3 = (Image)(((object)((targetGraphic is Image) ? targetGraphic : null)) ?? ((object)((Component)val2).GetComponent<Image>()));
			img.sprite = val3.sprite;
			img.type = (Type)1;
			((Selectable)btn).targetGraphic = (Graphic)(object)img;
			((Selectable)btn).transition = ((Selectable)val2).transition;
			((Selectable)btn).spriteState = ((Selectable)val2).spriteState;
			((Selectable)btn).colors = ((Selectable)val2).colors;
		}

		private static void AttachClickSfx(GameObject go)
		{
			ButtonSfx val = ((IEnumerable<ButtonSfx>)Resources.FindObjectsOfTypeAll<ButtonSfx>()).FirstOrDefault((Func<ButtonSfx, bool>)((ButtonSfx s) => (Object)(object)s != (Object)null && (Object)(object)s.m_sfxPrefab != (Object)null));
			if (!((Object)(object)val == (Object)null) && !((Object)(object)go.GetComponent<ButtonSfx>() != (Object)null))
			{
				go.AddComponent<ButtonSfx>().m_sfxPrefab = val.m_sfxPrefab;
			}
		}
	}
	internal sealed class PieceSearch
	{
		private readonly List<string> _words = new List<string>();

		private readonly List<string> _mods = new List<string>();

		private readonly List<string> _materials = new List<string>();

		public bool IsEmpty => _words.Count == 0 && _mods.Count == 0 && _materials.Count == 0;

		public static PieceSearch Parse(string? text)
		{
			PieceSearch pieceSearch = new PieceSearch();
			if (string.IsNullOrWhiteSpace(text))
			{
				return pieceSearch;
			}
			string[] array = text.ToLowerInvariant().Split((char[]?)null, StringSplitOptions.RemoveEmptyEntries);
			foreach (string text2 in array)
			{
				if (text2.Length > 1 && text2[0] == '@')
				{
					pieceSearch._mods.Add(text2.Substring(1));
				}
				else if (text2.Length > 1 && text2[0] == '!')
				{
					pieceSearch._materials.Add(text2.Substring(1));
				}
				else if (text2 != "@" && text2 != "!")
				{
					pieceSearch._words.Add(text2);
				}
			}
			return pieceSearch;
		}

		public bool Matches(Piece piece)
		{
			if ((Object)(object)piece == (Object)null)
			{
				return false;
			}
			if (piece.m_repairPiece || piece.m_removePiece)
			{
				return true;
			}
			if (_words.Count > 0)
			{
				string text = Utils.GetPrefabName(((Component)piece).gameObject).ToLowerInvariant();
				string text2 = Localization.instance.Localize(piece.m_name).ToLowerInvariant();
				string text3 = piece.m_name.ToLowerInvariant();
				string text4 = Localization.instance.Localize(piece.m_description).ToLowerInvariant();
				foreach (string word in _words)
				{
					if (!text2.Contains(word) && !text.Contains(word) && !text3.Contains(word) && !text4.Contains(word))
					{
						return false;
					}
				}
			}
			foreach (string material in _materials)
			{
				if (!CostsMaterial(piece, material))
				{
					return false;
				}
			}
			if (_mods.Count > 0)
			{
				string[] source = ModIndex.KeysFor(piece);
				foreach (string m in _mods)
				{
					if (!source.Any((string k) => k.Contains(m)))
					{
						return false;
					}
				}
			}
			return true;
		}

		private static bool CostsMaterial(Piece piece, string token)
		{
			Requirement[] resources = piece.m_resources;
			foreach (Requirement val in resources)
			{
				if (!((Object)(object)val?.m_resItem == (Object)null))
				{
					if (Localization.instance.Localize(val.m_resItem.m_itemData.m_shared.m_name).ToLowerInvariant().Contains(token))
					{
						return true;
					}
					if (Utils.GetPrefabName(((Component)val.m_resItem).gameObject).ToLowerInvariant().Contains(token))
					{
						return true;
					}
				}
			}
			return false;
		}
	}
	internal static class ModIndex
	{
		private static readonly Dictionary<string, string[]> _byPrefab = new Dictionary<string, string[]>();

		private static readonly Dictionary<string, string[]> _cache = new Dictionary<string, string[]>();

		private static bool _built;

		private static readonly Dictionary<PluginInfo, HashSet<string>> _shippedFiles = new Dictionary<PluginInfo, HashSet<string>>();

		private static MethodInfo? _jotunnGetPiece;

		private static object? _jotunnManager;

		private static bool _jotunnResolved;

		internal static void Invalidate()
		{
			_built = false;
			_byPrefab.Clear();
			_cache.Clear();
		}

		internal static string[] KeysFor(Piece piece)
		{
			string prefabName = Utils.GetPrefabName(((Component)piece).gameObject);
			string key = prefabName.ToLowerInvariant();
			if (_cache.TryGetValue(key, out string[] value))
			{
				return value;
			}
			if (!_built)
			{
				Build();
			}
			if (!_byPrefab.TryGetValue(key, out value))
			{
				value = JotunnKeys(prefabName) ?? Array.Empty<string>();
			}
			_cache[key] = value;
			return value;
		}

		private static void Build()
		{
			_built = true;
			try
			{
				List<PluginInfo> source = Chainloader.PluginInfos.Values.Where((PluginInfo p) => (Object)(object)((p != null) ? p.Instance : null) != (Object)null).ToList();
				Dictionary<string, string[]> dictionary = new Dictionary<string, string[]>(StringComparer.OrdinalIgnoreCase);
				AssetBundle[] array = AssetBundle.GetAllLoadedAssetBundles().ToArray();
				AssetBundle[] array2 = array;
				foreach (AssetBundle bundle in array2)
				{
					if (!((Object)(object)bundle == (Object)null) && !string.IsNullOrEmpty(((Object)bundle).name))
					{
						PluginInfo val = ((IEnumerable<PluginInfo>)source).FirstOrDefault((Func<PluginInfo, bool>)((PluginInfo p) => ShipsBundle(p, ((Object)bundle).name)));
						if (val != null)
						{
							dictionary[((Object)bundle).name] = KeysOf(val);
						}
					}
				}
				AssetBundle[] array3 = array;
				foreach (AssetBundle val2 in array3)
				{
					if ((Object)(object)val2 == (Object)null || !dictionary.TryGetValue(((Object)val2).name, out var value))
					{
						continue;
					}
					string[] allAssetNames;
					try
					{
						allAssetNames = val2.GetAllAssetNames();
					}
					catch
					{
						continue;
					}
					string[] array4 = allAssetNames;
					foreach (string text in array4)
					{
						if (text.EndsWith(".prefab", StringComparison.OrdinalIgnoreCase))
						{
							_byPrefab[Path.GetFileNameWithoutExtension(text).ToLowerInvariant()] = value;
						}
					}
				}
			}
			catch (Exception ex)
			{
				LegacyBuildMenuPlugin.Log.LogWarning((object)("Couldn't map build pieces to mods, @ search will be patchy: " + ex.Message));
			}
		}

		private static bool ShipsBundle(PluginInfo plugin, string bundleName)
		{
			Assembly assembly = ((object)plugin.Instance).GetType().Assembly;
			try
			{
				if (assembly.GetManifestResourceNames().Any((string r) => r.EndsWith(bundleName, StringComparison.OrdinalIgnoreCase)))
				{
					return true;
				}
			}
			catch
			{
			}
			if (!_shippedFiles.TryGetValue(plugin, out HashSet<string> value))
			{
				value = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
				try
				{
					string directoryName = Path.GetDirectoryName(plugin.Location);
					if (!string.IsNullOrEmpty(directoryName) && !string.Equals(Path.GetFullPath(directoryName), Path.GetFullPath(Paths.PluginPath), StringComparison.OrdinalIgnoreCase))
					{
						string[] files = Directory.GetFiles(directoryName, "*", SearchOption.AllDirectories);
						foreach (string path in files)
						{
							value.Add(Path.GetFileName(path));
						}
					}
				}
				catch
				{
				}
				_shippedFiles[plugin] = value;
			}
			return value.Contains(bundleName);
		}

		private static string[] KeysOf(PluginInfo plugin)
		{
			string text = ((object)plugin.Instance).GetType().Assembly.GetName().Name ?? "";
			return (from s in new string[3]
				{
					plugin.Metadata.Name,
					plugin.Metadata.GUID,
					text
				}
				where !string.IsNullOrEmpty(s)
				select s.ToLowerInvariant().Replace(" ", "")).Distinct().ToArray();
		}

		private static string[]? JotunnKeys(string prefab)
		{
			if (!_jotunnResolved)
			{
				_jotunnResolved = true;
				try
				{
					Type type = AccessTools.TypeByName("Jotunn.Managers.PieceManager");
					_jotunnManager = type?.GetProperty("Instance", BindingFlags.Static | BindingFlags.Public)?.GetValue(null);
					_jotunnGetPiece = type?.GetMethod("GetPiece", new Type[1] { typeof(string) });
				}
				catch
				{
					_jotunnGetPiece = null;
				}
			}
			if (_jotunnGetPiece == null || _jotunnManager == null)
			{
				return null;
			}
			try
			{
				object obj2 = _jotunnGetPiece.Invoke(_jotunnManager, new object[1] { prefab });
				object obj3 = obj2?.GetType().GetProperty("SourceMod")?.GetValue(obj2);
				BepInPlugin val = (BepInPlugin)((obj3 is BepInPlugin) ? obj3 : null);
				if (val == null)
				{
					return null;
				}
				PluginInfo value;
				PluginInfo val2 = (Chainloader.PluginInfos.TryGetValue(val.GUID, out value) ? value : null);
				return (val2 != null) ? KeysOf(val2) : new string[2]
				{
					val.Name.ToLowerInvariant().Replace(" ", ""),
					val.GUID.ToLowerInvariant()
				};
			}
			catch
			{
				return null;
			}
		}
	}
	[BepInPlugin("Azumatt.LegacyBuildMenu", "LegacyBuildMenu", "1.0.0")]
	public class LegacyBuildMenuPlugin : BaseUnityPlugin
	{
		internal const string ModName = "LegacyBuildMenu";

		internal const string ModVersion = "1.0.0";

		internal const string Author = "Azumatt";

		private const string ModGUID = "Azumatt.LegacyBuildMenu";

		private const string AAABuildMenuGuid = "Azumatt.AAABuildMenu";

		private readonly Harmony _harmony = new Harmony("Azumatt.LegacyBuildMenu");

		internal static readonly ManualLogSource Log = Logger.CreateLogSource("LegacyBuildMenu");

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

		internal static ConfigEntry<bool> UseLegacyMenu = null;

		internal static ConfigEntry<bool> ShowSearchBar = null;

		internal static ConfigEntry<bool> ResizableWindow = null;

		internal static ConfigEntry<Vector2> WindowSize = null;

		internal static ConfigEntry<Vector2> WindowPos = null;

		internal static bool StoodDown;

		internal static void LogErrorOnce(string where, Exception ex)
		{
			if (_loggedOnce.Add(where))
			{
				Log.LogError((object)$"Error in {where} (only the first one gets logged): {ex}");
			}
		}

		public void Awake()
		{
			//IL_00c5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e9: Unknown result type (might be due to invalid IL or missing references)
			UseLegacyMenu = ((BaseUnityPlugin)this).Config.Bind<bool>("1 - General", "Use Legacy Build Menu", true, "Use the pre-1.0 build menu instead of the one Valheim 1.0 ships. Off gives you the 1.0 menu back without a restart.");
			UseLegacyMenu.SettingChanged += delegate
			{
				LegacyMenu.OnSettingChanged();
			};
			ShowSearchBar = ((BaseUnityPlugin)this).Config.Bind<bool>("1 - General", "Show Search Bar", true, "Search bar above the pieces. @modname finds a mod's pieces, !material finds what costs that material, anything else matches the name. Needs a relog.");
			ResizableWindow = ((BaseUnityPlugin)this).Config.Bind<bool>("2 - Window", "Resizable Window", true, "Drag the bottom-right corner to resize the build menu and the bottom-left one to move it. Off puts it back to the vanilla size and spot.");
			ResizableWindow.SettingChanged += delegate
			{
				if ((Object)(object)Hud.instance != (Object)null)
				{
					LegacyWindow.ApplyWindow(Hud.instance);
				}
			};
			WindowSize = ((BaseUnityPlugin)this).Config.Bind<Vector2>("2 - Window", "Window Size Offset", Vector2.zero, "Set by dragging the resize corner.");
			WindowPos = ((BaseUnityPlugin)this).Config.Bind<Vector2>("2 - Window", "Window Position Offset", Vector2.zero, "Set by dragging the move corner.");
			_harmony.PatchAll(Assembly.GetExecutingAssembly());
		}

		private void Start()
		{
			if (Chainloader.PluginInfos.ContainsKey("Azumatt.AAABuildMenu"))
			{
				StoodDown = true;
				Log.LogWarning((object)"AAABuildMenu is installed and has its own classic build menu option. LegacyBuildMenu is standing down, use one or the other.");
			}
		}
	}
}