Decompiled source of TabSecret v0.1.0

TabSecret.dll

Decompiled a day ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using System.Text;
using System.Text.RegularExpressions;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using Jotunn.Entities;
using Jotunn.Utils;
using Microsoft.CodeAnalysis;
using Momoti.TabSecret.Classification;
using Momoti.TabSecret.Configuration;
using Momoti.TabSecret.Core;
using Momoti.TabSecret.Diagnostics;
using Momoti.TabSecret.Features;
using Momoti.TabSecret.Lang;
using Momoti.TabSecret.Patches;
using Momoti.TabSecret.Persistence;
using Momoti.TabSecret.Stations;
using Momoti.TabSecret.UI;
using TMPro;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.Events;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("0.0.0.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace Momoti.TabSecret
{
	[BepInPlugin("com.momoti.tabsecret", "TabSecret", "0.1.0")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	public class Plugin : BaseUnityPlugin
	{
		private Harmony _harmony;

		private void Awake()
		{
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0036: Expected O, but got Unknown
			ModLog.Init(((BaseUnityPlugin)this).Logger);
			TabSecretSettings.Bind(((BaseUnityPlugin)this).Config);
			Loc.Init();
			Reflect.Resolve();
			RuleSet.Load();
			_harmony = new Harmony("com.momoti.tabsecret");
			JotunnBridge.Enable();
			_harmony.PatchAll(typeof(Plugin).Assembly);
			PlayerControllerPatches.Apply(_harmony);
			((Component)this).gameObject.AddComponent<DumpHotkey>();
			ModLog.Info("TabSecret 0.1.0 loaded (step 5 r2: search, tabs, input gate)");
		}

		private void OnDestroy()
		{
			if (_harmony != null)
			{
				_harmony.UnpatchSelf();
			}
		}
	}
}
namespace Momoti.TabSecret.UI
{
	internal static class CategoryListView
	{
		private static GameObject _root;

		private static ScrollRect _scroll;

		private static RectTransform _content;

		private static GameObject _rowTemplate;

		private static float _rowHeight;

		private static float _rowSpace;

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

		public static void Build(RectTransform recipeList, float rowHeight, float rowSpace)
		{
			_rowHeight = rowHeight;
			_rowSpace = rowSpace;
			_rows.Clear();
			GameObject val = Object.Instantiate<GameObject>(((Component)recipeList).gameObject, ((Transform)recipeList).parent);
			((Object)val).name = "TabSecret_CategoryList";
			UiUtil.DestroyComponentsByName(val, "UIGamePad");
			_scroll = val.GetComponentInChildren<ScrollRect>(true);
			if (!((Object)(object)_scroll == (Object)null))
			{
				UiUtil.DestroyComponentsByName(((Component)_scroll).gameObject, "ScrollRectEnsureVisible", "UIGamePad");
				UiUtil.DestroyChild(((Component)_scroll).transform, "RecipeElement");
				_content = _scroll.content;
				for (int num = ((Transform)_content).childCount - 1; num >= 0; num--)
				{
					Object.Destroy((Object)(object)((Component)((Transform)_content).GetChild(num)).gameObject);
				}
				_rowTemplate = Object.Instantiate<GameObject>(UiTemplates.TabButton, val.transform);
				((Object)_rowTemplate).name = "TabSecret_RowTemplate";
				UiUtil.StripTabClone(_rowTemplate);
				_rowTemplate.SetActive(false);
				_root = val;
				_root.SetActive(false);
			}
		}

		public static void Populate(List<TabDefinition> tabs, string activeKey)
		{
			//IL_00ea: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ff: Unknown result type (might be due to invalid IL or missing references)
			//IL_0114: 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_0141: 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)
			//IL_0211: 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_01a5: Expected O, but got Unknown
			//IL_01c7: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d1: Expected O, but got Unknown
			//IL_0190: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)_root == (Object)null || (Object)(object)_content == (Object)null || (Object)(object)_rowTemplate == (Object)null)
			{
				return;
			}
			foreach (GameObject row in _rows)
			{
				row.SetActive(false);
				Object.Destroy((Object)(object)row);
			}
			_rows.Clear();
			int num = 0;
			foreach (TabDefinition tab in tabs)
			{
				if (!(tab.Key == activeKey))
				{
					GameObject val = Object.Instantiate<GameObject>(_rowTemplate, (Transform)(object)_content);
					UiUtil.NoNavigation(val);
					((Object)val).name = "Tab_" + tab.Key;
					val.SetActive(true);
					Transform transform = val.transform;
					Transform obj = ((transform is RectTransform) ? transform : null);
					((RectTransform)obj).anchorMin = new Vector2(0f, 1f);
					((RectTransform)obj).anchorMax = new Vector2(1f, 1f);
					((RectTransform)obj).pivot = new Vector2(0f, 1f);
					((RectTransform)obj).sizeDelta = new Vector2(0f, _rowHeight);
					((RectTransform)obj).anchoredPosition = new Vector2(0f, (float)(-num) * _rowSpace);
					TMP_Text component = ((Component)val.transform.Find("Text")).GetComponent<TMP_Text>();
					component.text = tab.Title;
					UiUtil.FitLabel(component);
					Button component2 = val.GetComponent<Button>();
					if (tab.Key == "new")
					{
						UiUtil.SetAccent(val, accent: true, Color.white);
					}
					component2.onClick = new ButtonClickedEvent();
					((Selectable)component2).interactable = true;
					string key = tab.Key;
					((UnityEvent)component2.onClick).AddListener((UnityAction)delegate
					{
						CraftMenuController.SetTab(key);
					});
					_rows.Add(val);
					num++;
				}
			}
			Transform transform2 = ((Component)_scroll).transform;
			Rect rect = ((RectTransform)((transform2 is RectTransform) ? transform2 : null)).rect;
			float height = ((Rect)(ref rect)).height;
			_content.SetSizeWithCurrentAnchors((Axis)1, Mathf.Max(height, (float)num * _rowSpace));
			_scroll.verticalNormalizedPosition = 1f;
		}

		public static void SetOpen(bool open)
		{
			if ((Object)(object)_root != (Object)null)
			{
				_root.SetActive(open);
			}
		}
	}
	internal static class CategoryMainButtonView
	{
		[CompilerGenerated]
		private static class <>O
		{
			public static UnityAction <0>__OnClick;
		}

		private static GameObject _root;

		private static TMP_Text _label;

		private static Color _normalColor = Color.white;

		public static void Build(Transform parent, Vector2 position, Vector2 size)
		{
			//IL_002e: 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_003d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0047: Expected O, but got Unknown
			//IL_005d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0062: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: Expected O, but got Unknown
			//IL_0088: 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)
			GameObject obj = Object.Instantiate<GameObject>(UiTemplates.TabButton, parent);
			((Object)obj).name = "TabSecret_CategoryMainButton";
			UiUtil.StripTabClone(obj);
			obj.SetActive(true);
			Transform transform = obj.transform;
			UiUtil.PlaceTopLeft((RectTransform)(object)((transform is RectTransform) ? transform : null), position, size);
			Button component = obj.GetComponent<Button>();
			component.onClick = new ButtonClickedEvent();
			ButtonClickedEvent onClick = component.onClick;
			object obj2 = <>O.<0>__OnClick;
			if (obj2 == null)
			{
				UnityAction val = OnClick;
				<>O.<0>__OnClick = val;
				obj2 = (object)val;
			}
			((UnityEvent)onClick).AddListener((UnityAction)obj2);
			((Selectable)component).interactable = true;
			if ((Object)(object)((Selectable)component).targetGraphic != (Object)null)
			{
				_normalColor = ((Selectable)component).targetGraphic.color;
			}
			_label = ((Component)obj.transform.Find("Text")).GetComponent<TMP_Text>();
			UiUtil.FitLabel(_label);
			_root = obj;
			UiUtil.NoNavigation(obj);
		}

		public static void SetLabel(string text)
		{
			if ((Object)(object)_label != (Object)null)
			{
				_label.text = text;
			}
		}

		public static void SetAccent(bool accent)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			UiUtil.SetAccent(_root, accent, _normalColor);
		}

		public static void SetVisible(bool visible)
		{
			if ((Object)(object)_root != (Object)null)
			{
				_root.SetActive(visible);
			}
		}

		private static void OnClick()
		{
			CraftMenuController.ToggleCategoryList();
		}
	}
	internal static class CraftMenuController
	{
		public static string ActiveTabKey = "all";

		public static string SearchText = "";

		public static bool CategoryListOpen;

		private static InventoryGui _gui;

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

		private static StationKind _kind = StationKind.Vanilla;

		private static List<TabDefinition> _tabs = new List<TabDefinition>();

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

		private static string _nameCacheLanguage = "";

		public static void OnOpen(InventoryGui gui)
		{
			_gui = gui;
			LayoutBuilder.EnsureBuilt(gui);
			if (LayoutBuilder.Ok)
			{
				ActiveTabKey = "all";
				_pinnedNew.Clear();
				SearchText = "";
				CategoryListOpen = false;
				SearchFieldView.SetText("");
				SearchFieldView.RefreshTexts();
				LayoutBuilder.SetCategoryListOpen(open: false);
			}
		}

		public static void OnRecipeListBuilding(InventoryGui gui, List<Recipe> recipes)
		{
			_gui = gui;
			LayoutBuilder.EnsureBuilt(gui);
			if (!LayoutBuilder.Ok)
			{
				return;
			}
			bool num = gui.InCraftTab();
			LayoutBuilder.SetCraftMode(num);
			if (!num)
			{
				CategoryListOpen = false;
				LayoutBuilder.SetCategoryListOpen(open: false);
				return;
			}
			_kind = ResolveKind();
			bool includeNew = NewTabProvider.Any(recipes) || (ActiveTabKey == "new" && _pinnedNew.Count > 0);
			_tabs = TabSetBuilder.Build(recipes, _kind, includeNew);
			TabDefinition tabDefinition = FindTab(ActiveTabKey);
			if (tabDefinition == null)
			{
				ActiveTabKey = "all";
				_pinnedNew.Clear();
				tabDefinition = FindTab("all");
			}
			CategoryMainButtonView.SetLabel(tabDefinition.Title);
			CategoryMainButtonView.SetAccent(ActiveTabKey == "new");
			FilterInPlace(recipes);
			if (CategoryListOpen)
			{
				CategoryListView.Populate(_tabs, ActiveTabKey);
			}
		}

		public static void SetTab(string key)
		{
			ActiveTabKey = key;
			_pinnedNew.Clear();
			if (key == "new")
			{
				foreach (string item in SeenRecipeStore.All)
				{
					_pinnedNew.Add(item);
				}
			}
			CategoryListOpen = false;
			LayoutBuilder.SetCategoryListOpen(open: false);
			RequestRebuild();
		}

		public static void SetSearch(string text)
		{
			SearchText = text ?? "";
			if (CategoryListOpen)
			{
				CategoryListOpen = false;
				LayoutBuilder.SetCategoryListOpen(open: false);
			}
			if ((Object)(object)LayoutBuilder.Runner != (Object)null)
			{
				float delaySeconds = ((TabSecretSettings.SearchDebounce != null) ? TabSecretSettings.SearchDebounce.Value : 0.12f);
				LayoutBuilder.Runner.ScheduleRebuild(delaySeconds);
			}
		}

		public static void ToggleCategoryList()
		{
			CategoryListOpen = !CategoryListOpen;
			if (CategoryListOpen)
			{
				CategoryListView.Populate(_tabs, ActiveTabKey);
			}
			LayoutBuilder.SetCategoryListOpen(CategoryListOpen);
		}

		public static void RequestRebuild()
		{
			if ((Object)(object)_gui != (Object)null)
			{
				Reflect.UpdateCraftingPanel(_gui);
			}
		}

		public static void OnTypingFrame()
		{
			if (ZInput.GetKeyDown((KeyCode)27, true))
			{
				SearchFieldView.Deselect();
			}
		}

		private static StationKind ResolveKind()
		{
			Player localPlayer = Player.m_localPlayer;
			return StationResolver.Resolve(((Object)(object)localPlayer != (Object)null) ? localPlayer.GetCurrentCraftingStation() : null)?.Kind ?? StationKind.Vanilla;
		}

		private static TabDefinition FindTab(string key)
		{
			foreach (TabDefinition tab in _tabs)
			{
				if (tab.Key == key)
				{
					return tab;
				}
			}
			return null;
		}

		private static void FilterInPlace(List<Recipe> recipes)
		{
			string needle = SearchText.Trim().ToLowerInvariant();
			bool byTab = ActiveTabKey != "all";
			bool flag = needle.Length > 0;
			if (byTab || flag)
			{
				EnsureNameCache();
				recipes.RemoveAll((Recipe recipe) => !Matches(recipe, byTab, needle));
			}
		}

		private static bool Matches(Recipe recipe, bool byTab, string needle)
		{
			if ((Object)(object)recipe == (Object)null || (Object)(object)recipe.m_item == (Object)null)
			{
				return true;
			}
			if (byTab && !InActiveTab(recipe))
			{
				return false;
			}
			if (needle.Length > 0 && NameOf(recipe).IndexOf(needle, StringComparison.Ordinal) < 0)
			{
				return false;
			}
			return true;
		}

		private static bool InActiveTab(Recipe recipe)
		{
			if (ActiveTabKey == "new")
			{
				if (!recipe.m_noCraftOnlyUpgrade)
				{
					if (!NewTabProvider.IsNew(recipe))
					{
						return _pinnedNew.Contains(((Object)((Component)recipe.m_item).gameObject).name);
					}
					return true;
				}
				return false;
			}
			return RuleEngine.Classify(recipe, _kind) == ActiveTabKey;
		}

		private static string NameOf(Recipe recipe)
		{
			string name = recipe.m_item.m_itemData.m_shared.m_name;
			if (!_nameCache.TryGetValue(name, out var value))
			{
				value = Localization.instance.Localize(name).ToLowerInvariant();
				_nameCache[name] = value;
			}
			return value;
		}

		private static void EnsureNameCache()
		{
			string selectedLanguage = Localization.instance.GetSelectedLanguage();
			if (!(selectedLanguage == _nameCacheLanguage))
			{
				_nameCache.Clear();
				_nameCacheLanguage = selectedLanguage;
			}
		}
	}
	internal static class InputGuard
	{
		public static bool IsTyping
		{
			get
			{
				if (!SearchFieldView.IsFocused)
				{
					return QuantityFieldView.IsFocused;
				}
				return true;
			}
		}
	}
	internal static class LayoutBuilder
	{
		private static InventoryGui _gui;

		private static bool _attempted;

		private static bool _ok;

		private static RectTransform _recipeList;

		private static Vector2 _origOffsetMax;

		private static float _origBase;

		private static float _usedHeight;

		private static bool _shrunk;

		private static bool _craftMode = true;

		private static bool _categoryOpen;

		public static UiRunner Runner { get; private set; }

		public static bool Ok => _ok;

		public static void EnsureBuilt(InventoryGui gui)
		{
			if ((Object)(object)gui == (Object)null || (_attempted && (Object)(object)_gui == (Object)(object)gui))
			{
				return;
			}
			_gui = gui;
			_attempted = true;
			_ok = false;
			_shrunk = false;
			try
			{
				Build(gui);
				_ok = true;
			}
			catch (Exception ex)
			{
				ModLog.ErrorOnce("layout-build", "TabSecret UI build failed, vanilla menu stays unchanged: " + ex);
				SetShrunk(shrink: false);
			}
		}

		public static void SetCraftMode(bool craft)
		{
			if (_ok)
			{
				_craftMode = craft;
				SetShrunk(craft);
				RefreshVisibility();
			}
		}

		public static void SetCategoryListOpen(bool open)
		{
			if (_ok)
			{
				_categoryOpen = open;
				RefreshVisibility();
			}
		}

		private static void Build(InventoryGui gui)
		{
			//IL_01dd: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00aa: Unknown result type (might be due to invalid IL or missing references)
			//IL_00dd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ec: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fd: Unknown result type (might be due to invalid IL or missing references)
			//IL_0114: 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_015b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0163: Unknown result type (might be due to invalid IL or missing references)
			//IL_0176: 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_0135: 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)
			if (!UiTemplates.Resolve(gui))
			{
				throw new InvalidOperationException("vanilla tab button not found");
			}
			RectTransform recipeListRoot = gui.m_recipeListRoot;
			_recipeList = (RectTransform)(((Object)(object)recipeListRoot != (Object)null && (Object)(object)((Transform)recipeListRoot).parent != (Object)null) ? /*isinst with value type is only supported in some contexts*/: null);
			if ((Object)(object)_recipeList == (Object)null)
			{
				throw new InvalidOperationException("RecipeList not found");
			}
			float num = Reflect.GetFloat(gui, "m_recipeListSpace", 34f);
			RectTransform val = (RectTransform)(((Object)(object)gui.m_recipeElementPrefab != (Object)null) ? /*isinst with value type is only supported in some contexts*/: null);
			float num2;
			Rect rect;
			if (!((Object)(object)val != (Object)null))
			{
				num2 = 32f;
			}
			else
			{
				rect = val.rect;
				num2 = ((Rect)(ref rect)).height;
			}
			float num3 = num2;
			float num4 = Mathf.Max(0f, num - num3);
			_origBase = Reflect.GetFloat(gui, "m_recipeListBaseSize", 0f);
			_origOffsetMax = _recipeList.offsetMax;
			Vector2 anchoredPosition = _recipeList.anchoredPosition;
			rect = _recipeList.rect;
			float width = ((Rect)(ref rect)).width;
			Transform parent = ((Transform)_recipeList).parent;
			float num5 = anchoredPosition.y;
			if ((Object)(object)UiTemplates.SearchField != (Object)null)
			{
				SearchFieldView.Build(parent, new Vector2(anchoredPosition.x, num5), new Vector2(width, num));
				num5 -= num + num4;
			}
			CategoryMainButtonView.Build(parent, new Vector2(anchoredPosition.x, num5), new Vector2(width, num3));
			num5 -= num3 + num4;
			_usedHeight = anchoredPosition.y - num5;
			SetShrunk(shrink: true);
			CategoryListView.Build(_recipeList, num3, num);
			try
			{
				QuantityFieldView.Build(gui);
			}
			catch (Exception ex)
			{
				ModLog.ErrorOnce("quantity-build", "QuantityField build failed, vanilla Craft button stays: " + ex);
			}
			GameObject val2 = new GameObject("TabSecret_Runner", new Type[1] { typeof(RectTransform) });
			val2.transform.SetParent(parent, false);
			Runner = val2.AddComponent<UiRunner>();
			_craftMode = true;
			_categoryOpen = false;
			RefreshVisibility();
		}

		private static void SetShrunk(bool shrink)
		{
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: 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)
			if (!((Object)(object)_recipeList == (Object)null) && shrink != _shrunk)
			{
				Vector2 origOffsetMax = _origOffsetMax;
				_recipeList.offsetMax = (Vector2)(shrink ? new Vector2(origOffsetMax.x, origOffsetMax.y - _usedHeight) : origOffsetMax);
				Reflect.SetFloat(_gui, "m_recipeListBaseSize", shrink ? (_origBase - _usedHeight) : _origBase);
				_shrunk = shrink;
			}
		}

		private static void RefreshVisibility()
		{
			SearchFieldView.SetVisible(_craftMode);
			CategoryMainButtonView.SetVisible(_craftMode);
			QuantityFieldView.SetCraftMode(_craftMode);
			bool flag = _craftMode && _categoryOpen;
			CategoryListView.SetOpen(flag);
			if ((Object)(object)_recipeList != (Object)null)
			{
				((Component)_recipeList).gameObject.SetActive(!flag);
			}
		}
	}
	internal static class NewBadgeView
	{
		private const string BadgeName = "TabSecret_NewBadge";

		public static void Attach(GameObject element)
		{
			//IL_00e7: 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_012f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0144: Unknown result type (might be due to invalid IL or missing references)
			//IL_0159: Unknown result type (might be due to invalid IL or missing references)
			//IL_016d: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)element == (Object)null)
			{
				return;
			}
			Transform val = element.transform.Find("icon");
			Transform val2 = (((Object)(object)val != (Object)null) ? val : element.transform);
			if ((Object)(object)val2.Find("TabSecret_NewBadge") != (Object)null)
			{
				return;
			}
			Transform val3 = element.transform.Find("name");
			if (!((Object)(object)val3 == (Object)null) && !((Object)(object)((Component)val3).GetComponent<TMP_Text>() == (Object)null))
			{
				GameObject val4 = Object.Instantiate<GameObject>(((Component)val3).gameObject, val2, false);
				((Object)val4).name = "TabSecret_NewBadge";
				for (int num = val4.transform.childCount - 1; num >= 0; num--)
				{
					Object.Destroy((Object)(object)((Component)val4.transform.GetChild(num)).gameObject);
				}
				TMP_Text component = val4.GetComponent<TMP_Text>();
				component.text = Loc.T("$momoti_tabsecret_ui_new_badge");
				component.enableAutoSizing = false;
				component.fontSize = 10f;
				component.fontStyle = (FontStyles)1;
				((Graphic)component).color = Color.white;
				component.alignment = (TextAlignmentOptions)260;
				((Graphic)component).raycastTarget = false;
				component.overflowMode = (TextOverflowModes)0;
				RectTransform rectTransform = component.rectTransform;
				rectTransform.anchorMin = new Vector2(1f, 1f);
				rectTransform.anchorMax = new Vector2(1f, 1f);
				rectTransform.pivot = new Vector2(1f, 1f);
				rectTransform.sizeDelta = new Vector2(60f, 14f);
				rectTransform.anchoredPosition = new Vector2(-1f, -1f);
			}
		}

		public static void Remove(GameObject element)
		{
			if ((Object)(object)element == (Object)null)
			{
				return;
			}
			Transform[] componentsInChildren = element.GetComponentsInChildren<Transform>(true);
			foreach (Transform val in componentsInChildren)
			{
				if (((Object)val).name == "TabSecret_NewBadge")
				{
					Object.Destroy((Object)(object)((Component)val).gameObject);
					break;
				}
			}
		}
	}
	internal static class QuantityFieldView
	{
		private struct RectState
		{
			public Vector2 AnchorMin;

			public Vector2 AnchorMax;

			public Vector2 Pivot;

			public Vector2 OffsetMin;

			public Vector2 OffsetMax;

			public void Save(RectTransform r)
			{
				//IL_0002: Unknown result type (might be due to invalid IL or missing references)
				//IL_0007: Unknown result type (might be due to invalid IL or missing references)
				//IL_000e: 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_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_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_0032: Unknown result type (might be due to invalid IL or missing references)
				//IL_0037: Unknown result type (might be due to invalid IL or missing references)
				AnchorMin = r.anchorMin;
				AnchorMax = r.anchorMax;
				Pivot = r.pivot;
				OffsetMin = r.offsetMin;
				OffsetMax = r.offsetMax;
			}

			public void Restore(RectTransform r)
			{
				//IL_0002: 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_0026: 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)
				r.anchorMin = AnchorMin;
				r.anchorMax = AnchorMax;
				r.pivot = Pivot;
				r.offsetMin = OffsetMin;
				r.offsetMax = OffsetMax;
			}
		}

		[CompilerGenerated]
		private static class <>O
		{
			public static UnityAction<string> <0>__OnEndEdit;

			public static OnValidateInput <1>__ValidateDigit;

			public static UnityAction<string> <2>__OnChanged;
		}

		public const int MaxValue = 999;

		private const float Gap = 4f;

		private static InventoryGui _gui;

		private static GameObject _root;

		private static TMP_InputField _input;

		private static RectTransform _button;

		private static RectTransform _parent;

		private const float HeightFactor = 0.7f;

		private static RectTransform _progressBar;

		private static RectTransform _progress;

		private static Vector3 _worldMin;

		private static Vector3 _worldMax;

		private static RectState _buttonState;

		private static RectState _progressState;

		private static Vector3 _progressScale = Vector3.one;

		private static readonly Dictionary<Transform, Vector3> _textScales = new Dictionary<Transform, Vector3>();

		private static Sprite _triangleLeft;

		private static Sprite _triangleRight;

		public static bool IsFocused
		{
			get
			{
				if ((Object)(object)_input != (Object)null)
				{
					return _input.isFocused;
				}
				return false;
			}
		}

		public static int Value
		{
			get
			{
				if ((Object)(object)_input == (Object)null || !int.TryParse(_input.text, out var result))
				{
					return 1;
				}
				return Math.Max(1, Math.Min(999, result));
			}
		}

		public static void Reset()
		{
			SetValue(1);
		}

		public static void SetValue(int value)
		{
			if ((Object)(object)_input != (Object)null)
			{
				_input.SetTextWithoutNotify(Math.Max(1, Math.Min(999, value)).ToString());
			}
		}

		public static void Build(InventoryGui gui)
		{
			//IL_0088: 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_0094: Unknown result type (might be due to invalid IL or missing references)
			//IL_0099: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f5: Unknown result type (might be due to invalid IL or missing references)
			//IL_0145: 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_01e9: Expected O, but got Unknown
			//IL_01ee: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f8: Expected O, but got Unknown
			//IL_024d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0252: Unknown result type (might be due to invalid IL or missing references)
			//IL_0258: Expected O, but got Unknown
			//IL_0327: Unknown result type (might be due to invalid IL or missing references)
			//IL_0331: Unknown result type (might be due to invalid IL or missing references)
			//IL_0354: Unknown result type (might be due to invalid IL or missing references)
			//IL_035e: Unknown result type (might be due to invalid IL or missing references)
			TMP_InputField searchField = UiTemplates.SearchField;
			if ((Object)(object)searchField == (Object)null || (Object)(object)gui == (Object)null || (Object)(object)gui.m_craftButton == (Object)null)
			{
				return;
			}
			_gui = gui;
			Transform transform = ((Component)gui.m_craftButton).transform;
			_button = (RectTransform)(object)((transform is RectTransform) ? transform : null);
			_parent = (RectTransform)(((Object)(object)_button != (Object)null) ? /*isinst with value type is only supported in some contexts*/: null);
			if ((Object)(object)_parent == (Object)null)
			{
				return;
			}
			Vector3[] array = (Vector3[])(object)new Vector3[4];
			_button.GetWorldCorners(array);
			_worldMin = array[0];
			_worldMax = array[2];
			_buttonState.Save(_button);
			_progress = Reflect.CraftProgressPanel(gui);
			if ((Object)(object)_progress != (Object)null && (Object)/*isinst with value type is only supported in some contexts*/ != (Object)null)
			{
				_progressState.Save(_progress);
				_progressScale = ((Transform)_progress).localScale;
			}
			else
			{
				_progress = null;
			}
			_textScales.Clear();
			if ((Object)(object)_progress != (Object)null)
			{
				TMP_Text[] componentsInChildren = ((Component)_progress).GetComponentsInChildren<TMP_Text>(true);
				foreach (TMP_Text val in componentsInChildren)
				{
					_textScales[val.transform] = val.transform.localScale;
				}
			}
			_progressBar = (((Object)(object)_progress != (Object)null) ? Reflect.CraftProgressBar(gui) : null);
			if ((Object)(object)_progressBar != (Object)null && !((Transform)_progressBar).IsChildOf((Transform)(object)_progress))
			{
				_progressBar = null;
			}
			GameObject val2 = Object.Instantiate<GameObject>(((Component)searchField).gameObject, (Transform)(object)_parent);
			((Object)val2).name = "TabSecret_QuantityField";
			UiUtil.DestroyChild(val2.transform, "SearchBarHint");
			val2.SetActive(true);
			_input = val2.GetComponent<TMP_InputField>();
			_input.onValueChanged = new OnChangeEvent();
			_input.onEndEdit = new SubmitEvent();
			((UnityEvent<string>)(object)_input.onEndEdit).AddListener((UnityAction<string>)OnEndEdit);
			_input.contentType = (ContentType)0;
			_input.characterValidation = (CharacterValidation)0;
			TMP_InputField input = _input;
			object obj = <>O.<1>__ValidateDigit;
			if (obj == null)
			{
				OnValidateInput val3 = ValidateDigit;
				<>O.<1>__ValidateDigit = val3;
				obj = (object)val3;
			}
			input.onValidateInput = (OnValidateInput)obj;
			((UnityEvent<string>)(object)_input.onValueChanged).AddListener((UnityAction<string>)OnChanged);
			_input.characterLimit = 3;
			_input.SetTextWithoutNotify("1");
			if ((Object)(object)_input.textComponent != (Object)null)
			{
				_input.textComponent.alignment = (TextAlignmentOptions)514;
			}
			Graphic placeholder = _input.placeholder;
			TMP_Text val4 = (TMP_Text)(object)((placeholder is TMP_Text) ? placeholder : null);
			if ((Object)(object)val4 != (Object)null)
			{
				val4.text = "1";
				val4.alignment = (TextAlignmentOptions)514;
			}
			_root = val2;
			if ((Object)(object)_input.textViewport != (Object)null)
			{
				_input.textViewport.offsetMin = new Vector2(20f, _input.textViewport.offsetMin.y);
				_input.textViewport.offsetMax = new Vector2(-20f, _input.textViewport.offsetMax.y);
			}
			AddArrow(val2.transform, left: true, -1);
			AddArrow(val2.transform, left: false, 1);
			UiUtil.NoNavigation(val2);
			SfxCopier.Copy(UiTemplates.TabButton, val2);
		}

		public static void SetCraftMode(bool craft)
		{
			if (!((Object)(object)_root == (Object)null) && !((Object)(object)_button == (Object)null))
			{
				_root.SetActive(craft);
				if (craft)
				{
					ApplyCompact();
				}
				else
				{
					RestoreVanilla();
				}
			}
		}

		private static void ApplyCompact()
		{
			//IL_0027: 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)
			float num = _worldMax.x - _worldMin.x;
			float num2 = Mathf.Min(num * 0.5f, Mathf.Max(70f * ((Transform)_button).lossyScale.x, num * 0.4f));
			float num3 = 4f * ((Transform)_button).lossyScale.x;
			float num4 = num - num2 - num3;
			float num5 = (_worldMax.y - _worldMin.y) * 0.7f;
			float num6 = (_worldMax.y + _worldMin.y) * 0.5f;
			float wy = num6 - num5 * 0.5f;
			float wy2 = num6 + num5 * 0.5f;
			Transform transform = _root.transform;
			Place((RectTransform)(object)((transform is RectTransform) ? transform : null), _worldMin.x, wy, _worldMin.x + num4, wy2);
			Place(_button, _worldMax.x - num2, wy, _worldMax.x, wy2);
			if ((Object)(object)_progress != (Object)null)
			{
				FitProgress(_worldMax.x - num2, wy, _worldMax.x, wy2);
			}
		}

		private static void RestoreVanilla()
		{
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			_buttonState.Restore(_button);
			if ((Object)(object)_progress != (Object)null)
			{
				_progressState.Restore(_progress);
				((Transform)_progress).localScale = _progressScale;
				ResetTexts(1f);
			}
		}

		private static void FitProgress(float wx0, float wy0, float wx1, float wy1)
		{
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_006a: Unknown result type (might be due to invalid IL or missing references)
			//IL_006f: 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_0078: Unknown result type (might be due to invalid IL or missing references)
			//IL_007e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0083: 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_00ce: 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_00d0: 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_00e4: 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_00ed: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ff: Unknown result type (might be due to invalid IL or missing references)
			//IL_010e: Unknown result type (might be due to invalid IL or missing references)
			//IL_011d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0123: Unknown result type (might be due to invalid IL or missing references)
			//IL_012a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0134: 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_0141: Unknown result type (might be due to invalid IL or missing references)
			//IL_0174: Unknown result type (might be due to invalid IL or missing references)
			//IL_0179: 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_0182: Unknown result type (might be due to invalid IL or missing references)
			//IL_0193: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ac: 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)
			//IL_01d4: Unknown result type (might be due to invalid IL or missing references)
			//IL_0204: 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_0250: Unknown result type (might be due to invalid IL or missing references)
			//IL_025b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0260: Unknown result type (might be due to invalid IL or missing references)
			//IL_0265: Unknown result type (might be due to invalid IL or missing references)
			//IL_0271: Unknown result type (might be due to invalid IL or missing references)
			//IL_0276: Unknown result type (might be due to invalid IL or missing references)
			//IL_0278: Unknown result type (might be due to invalid IL or missing references)
			//IL_027a: Unknown result type (might be due to invalid IL or missing references)
			//IL_027f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0284: Unknown result type (might be due to invalid IL or missing references)
			//IL_028c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0291: Unknown result type (might be due to invalid IL or missing references)
			//IL_0298: Unknown result type (might be due to invalid IL or missing references)
			//IL_029f: Unknown result type (might be due to invalid IL or missing references)
			//IL_02a4: Unknown result type (might be due to invalid IL or missing references)
			_progressState.Restore(_progress);
			((Transform)_progress).localScale = _progressScale;
			Vector3[] corners = (Vector3[])(object)new Vector3[4];
			Vector2 min = default(Vector2);
			Vector2 max = default(Vector2);
			Rect rect;
			if ((Object)(object)_progressBar != (Object)null)
			{
				((Vector2)(ref min))..ctor(float.MaxValue, float.MaxValue);
				((Vector2)(ref max))..ctor(float.MinValue, float.MinValue);
				Include(_progressBar, corners, ref min, ref max);
			}
			else
			{
				rect = _progress.rect;
				min = ((Rect)(ref rect)).min;
				rect = _progress.rect;
				max = ((Rect)(ref rect)).max;
				RectTransform[] componentsInChildren = ((Component)_progress).GetComponentsInChildren<RectTransform>(true);
				foreach (RectTransform val in componentsInChildren)
				{
					if ((Object)(object)val != (Object)(object)_progress)
					{
						Include(val, corners, ref min, ref max);
					}
				}
			}
			Vector2 val2 = (min + max) * 0.5f;
			rect = _progress.rect;
			Vector2 val3 = val2 - ((Rect)(ref rect)).center;
			Vector2 val4 = default(Vector2);
			((Vector2)(ref val4))..ctor(((Transform)_progress).lossyScale.x, ((Transform)_progress).lossyScale.y);
			float num = (max.x - min.x) * val4.x;
			float num2 = (max.y - min.y) * val4.y;
			float num3 = (wx1 - wx0) / Mathf.Max(num, 0.0001f);
			float num4 = (wy1 - wy0) / Mathf.Max(num2, 0.0001f);
			rect = _progress.rect;
			Vector2 size = ((Rect)(ref rect)).size;
			_progress.anchorMin = new Vector2(0.5f, 0.5f);
			_progress.anchorMax = new Vector2(0.5f, 0.5f);
			_progress.pivot = new Vector2(0.5f, 0.5f);
			_progress.sizeDelta = size;
			((Transform)_progress).localScale = new Vector3(_progressScale.x * num3, _progressScale.y * num4, _progressScale.z);
			ResetTexts(num4 / Mathf.Max(num3, 0.0001f));
			Vector3 val5 = default(Vector3);
			((Vector3)(ref val5))..ctor((wx0 + wx1) * 0.5f, (wy0 + wy1) * 0.5f, _worldMin.z);
			Vector3 val6 = ((Transform)_progress).TransformPoint(new Vector3(val3.x, val3.y, 0f));
			Vector3 val7 = ((Transform)(RectTransform)((Transform)_progress).parent).InverseTransformVector(val5 - val6);
			RectTransform progress = _progress;
			progress.anchoredPosition += new Vector2(val7.x, val7.y);
		}

		private static void ResetTexts(float ratio)
		{
			//IL_002d: 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_0047: 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)
			foreach (KeyValuePair<Transform, Vector3> textScale in _textScales)
			{
				if (!((Object)(object)textScale.Key == (Object)null))
				{
					textScale.Key.localScale = new Vector3(textScale.Value.x * ratio, textScale.Value.y, textScale.Value.z);
				}
			}
		}

		private static void Include(RectTransform child, Vector3[] corners, ref Vector2 min, ref Vector2 max)
		{
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_0041: 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)
			child.GetWorldCorners(corners);
			for (int i = 0; i < 4; i++)
			{
				Vector3 val = ((Transform)_progress).InverseTransformPoint(corners[i]);
				min = Vector2.Min(min, Vector2.op_Implicit(val));
				max = Vector2.Max(max, Vector2.op_Implicit(val));
			}
		}

		private static void Place(RectTransform rect, float wx0, float wy0, float wx1, float wy1)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Expected O, but got Unknown
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_0037: Unknown result type (might be due to invalid IL or missing references)
			//IL_003c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			//IL_005d: 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_007d: 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_008a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0090: Unknown result type (might be due to invalid IL or missing references)
			//IL_0097: 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_00a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bb: 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_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_00d6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00db: Unknown result type (might be due to invalid IL or missing references)
			RectTransform val = (RectTransform)((Transform)rect).parent;
			Vector3 val2 = ((Transform)val).InverseTransformPoint(new Vector3(wx0, wy0, _worldMin.z));
			Vector3 val3 = ((Transform)val).InverseTransformPoint(new Vector3(wx1, wy1, _worldMin.z));
			rect.anchorMin = new Vector2(0.5f, 0.5f);
			rect.anchorMax = new Vector2(0.5f, 0.5f);
			rect.pivot = new Vector2(0.5f, 0.5f);
			rect.sizeDelta = new Vector2(val3.x - val2.x, val3.y - val2.y);
			Vector2 val4 = new Vector2((val2.x + val3.x) * 0.5f, (val2.y + val3.y) * 0.5f);
			Rect rect2 = val.rect;
			rect.anchoredPosition = val4 - ((Rect)(ref rect2)).center;
		}

		private static void OnChanged(string text)
		{
			try
			{
				string text2 = DigitsOnly(text);
				if (text2 != text)
				{
					_input.SetTextWithoutNotify(text2);
				}
				Reflect.RefreshRecipe(_gui);
			}
			catch (Exception ex)
			{
				ModLog.ErrorOnce("quantity-refresh", "Recipe refresh failed: " + ex);
			}
		}

		private static char ValidateDigit(string text, int charIndex, char addedChar)
		{
			if (addedChar < '0' || addedChar > '9')
			{
				return '\0';
			}
			return addedChar;
		}

		private static string DigitsOnly(string text)
		{
			if (string.IsNullOrEmpty(text))
			{
				return text;
			}
			StringBuilder stringBuilder = new StringBuilder(text.Length);
			foreach (char c in text)
			{
				if (c >= '0' && c <= '9')
				{
					stringBuilder.Append(c);
				}
			}
			return stringBuilder.ToString();
		}

		private static void AddArrow(Transform parent, bool left, int delta)
		{
			//IL_0042: Unknown result type (might be due to invalid IL or missing references)
			//IL_0048: Expected O, but got Unknown
			//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)
			//IL_0075: 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_0094: Unknown result type (might be due to invalid IL or missing references)
			//IL_009e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c8: 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_011e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0123: 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_0146: 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_0174: Unknown result type (might be due to invalid IL or missing references)
			//IL_017f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0188: Unknown result type (might be due to invalid IL or missing references)
			//IL_0196: 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
			GameObject val = new GameObject(left ? "TabSecret_QtyDown" : "TabSecret_QtyUp", new Type[3]
			{
				typeof(RectTransform),
				typeof(Image),
				typeof(Button)
			});
			val.transform.SetParent(parent, false);
			RectTransform val2 = (RectTransform)val.transform;
			val2.anchorMin = new Vector2(left ? 0f : 1f, 0.2f);
			val2.anchorMax = new Vector2(left ? 0f : 1f, 0.8f);
			val2.pivot = new Vector2(left ? 0f : 1f, 0.5f);
			val2.sizeDelta = new Vector2(14f, 0f);
			val2.anchoredPosition = new Vector2(left ? 4f : (-4f), 0f);
			Image component = val.GetComponent<Image>();
			component.sprite = Triangle(left);
			component.preserveAspect = true;
			((Graphic)component).raycastTarget = true;
			Button component2 = val.GetComponent<Button>();
			((Selectable)component2).targetGraphic = (Graphic)(object)component;
			ColorBlock defaultColorBlock = ColorBlock.defaultColorBlock;
			((ColorBlock)(ref defaultColorBlock)).normalColor = new Color(1f, 1f, 1f, 0.85f);
			((ColorBlock)(ref defaultColorBlock)).highlightedColor = Color.white;
			((ColorBlock)(ref defaultColorBlock)).pressedColor = new Color(0.75f, 0.75f, 0.75f, 1f);
			((ColorBlock)(ref defaultColorBlock)).selectedColor = ((ColorBlock)(ref defaultColorBlock)).normalColor;
			((Selectable)component2).colors = defaultColorBlock;
			Navigation navigation = default(Navigation);
			((Navigation)(ref navigation)).mode = (Mode)0;
			((Selectable)component2).navigation = navigation;
			int step = delta;
			((UnityEvent)component2.onClick).AddListener((UnityAction)delegate
			{
				Step(step);
			});
			SfxCopier.Copy(UiTemplates.TabButton, val);
		}

		private static void Step(int delta)
		{
			SetValue(Value + delta);
			Reflect.RefreshRecipe(_gui);
		}

		private static Sprite Triangle(bool left)
		{
			//IL_00df: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00eb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f9: Unknown result type (might be due to invalid IL or missing references)
			//IL_0113: Unknown result type (might be due to invalid IL or missing references)
			//IL_0122: Unknown result type (might be due to invalid IL or missing references)
			//IL_0131: Expected O, but got Unknown
			//IL_00b4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b9: Unknown result type (might be due to invalid IL or missing references)
			Sprite val = (left ? _triangleLeft : _triangleRight);
			if ((Object)(object)val != (Object)null)
			{
				return val;
			}
			Color32[] array = (Color32[])(object)new Color32[1024];
			for (int i = 0; i < 32; i++)
			{
				for (int j = 0; j < 32; j++)
				{
					float num = (left ? (31 - j) : j);
					float num2 = Mathf.Clamp01(12.5f * (27f - num) / 21f - Mathf.Abs((float)i - 15.5f) + 0.5f) * Mathf.Clamp01(num - 5.5f) * Mathf.Clamp01(27.5f - num);
					array[i * 32 + j] = new Color32(byte.MaxValue, byte.MaxValue, byte.MaxValue, (byte)Mathf.RoundToInt(num2 * 255f));
				}
			}
			Texture2D val2 = new Texture2D(32, 32, (TextureFormat)4, false)
			{
				wrapMode = (TextureWrapMode)1,
				filterMode = (FilterMode)1
			};
			val2.SetPixels32(array);
			val2.Apply();
			Sprite val3 = Sprite.Create(val2, new Rect(0f, 0f, 32f, 32f), new Vector2(0.5f, 0.5f), 100f);
			if (left)
			{
				_triangleLeft = val3;
			}
			else
			{
				_triangleRight = val3;
			}
			return val3;
		}

		private static void OnEndEdit(string text)
		{
			SetValue(Value);
		}
	}
	internal static class SearchFieldView
	{
		private static GameObject _root;

		private static TMP_InputField _input;

		public static bool IsFocused
		{
			get
			{
				if ((Object)(object)_input != (Object)null)
				{
					return _input.isFocused;
				}
				return false;
			}
		}

		public static void Build(Transform parent, Vector2 position, Vector2 size)
		{
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			//IL_004b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0061: Unknown result type (might be due to invalid IL or missing references)
			//IL_006b: Expected O, but got Unknown
			TMP_InputField searchField = UiTemplates.SearchField;
			if (!((Object)(object)searchField == (Object)null))
			{
				GameObject val = Object.Instantiate<GameObject>(((Component)searchField).gameObject, parent);
				((Object)val).name = "TabSecret_SearchField";
				UiUtil.DestroyChild(val.transform, "SearchBarHint");
				val.SetActive(true);
				Transform transform = val.transform;
				UiUtil.PlaceTopLeft((RectTransform)(object)((transform is RectTransform) ? transform : null), position, size);
				_input = val.GetComponent<TMP_InputField>();
				_input.onValueChanged = new OnChangeEvent();
				((UnityEvent<string>)(object)_input.onValueChanged).AddListener((UnityAction<string>)OnChanged);
				_input.characterLimit = 64;
				_input.SetTextWithoutNotify("");
				_root = val;
				UiUtil.NoNavigation(val);
				SfxCopier.Copy(UiTemplates.TabButton, val);
				RefreshTexts();
			}
		}

		public static void RefreshTexts()
		{
			if (!((Object)(object)_input == (Object)null))
			{
				Graphic placeholder = _input.placeholder;
				TMP_Text val = (TMP_Text)(object)((placeholder is TMP_Text) ? placeholder : null);
				if ((Object)(object)val != (Object)null)
				{
					val.text = Loc.T("$momoti_tabsecret_ui_search_placeholder");
				}
			}
		}

		public static void SetText(string text)
		{
			if ((Object)(object)_input != (Object)null)
			{
				_input.SetTextWithoutNotify(text ?? "");
			}
		}

		public static void Deselect()
		{
			if ((Object)(object)EventSystem.current != (Object)null)
			{
				EventSystem.current.SetSelectedGameObject((GameObject)null);
			}
		}

		public static void SetVisible(bool visible)
		{
			if ((Object)(object)_root != (Object)null)
			{
				_root.SetActive(visible);
			}
		}

		private static void OnChanged(string text)
		{
			CraftMenuController.SetSearch(text);
		}
	}
	internal static class SfxCopier
	{
		public static void Copy(GameObject from, GameObject to)
		{
			if ((Object)(object)from == (Object)null || (Object)(object)to == (Object)null)
			{
				return;
			}
			ButtonSfx component = from.GetComponent<ButtonSfx>();
			if (!((Object)(object)component == (Object)null))
			{
				ButtonSfx val = to.GetComponent<ButtonSfx>();
				if ((Object)(object)val == (Object)null)
				{
					val = to.AddComponent<ButtonSfx>();
				}
				FieldInfo[] fields = typeof(ButtonSfx).GetFields(BindingFlags.Instance | BindingFlags.Public);
				foreach (FieldInfo fieldInfo in fields)
				{
					fieldInfo.SetValue(val, fieldInfo.GetValue(component));
				}
			}
		}
	}
	internal sealed class UiRunner : MonoBehaviour
	{
		private Coroutine _pending;

		public void ScheduleRebuild(float delaySeconds)
		{
			if (_pending != null)
			{
				((MonoBehaviour)this).StopCoroutine(_pending);
			}
			_pending = ((MonoBehaviour)this).StartCoroutine(RebuildAfter(delaySeconds));
		}

		private IEnumerator RebuildAfter(float delaySeconds)
		{
			yield return (object)new WaitForSecondsRealtime(delaySeconds);
			_pending = null;
			CraftMenuController.RequestRebuild();
		}
	}
	internal static class UiTemplates
	{
		public static GameObject TabButton;

		public static TMP_InputField SearchField;

		public static bool Resolve(InventoryGui gui)
		{
			TabButton = (((Object)(object)gui != (Object)null && (Object)(object)gui.m_tabUpgrade != (Object)null) ? ((Component)gui.m_tabUpgrade).gameObject : null);
			SearchField = Reflect.GetBuildSearchField();
			if ((Object)(object)SearchField == (Object)null)
			{
				ModLog.Warn("Build menu search field not found: the search field will not be shown");
			}
			return (Object)(object)TabButton != (Object)null;
		}
	}
	internal static class UiUtil
	{
		public static readonly Color NewAccent = new Color(1f, 0.6f, 0.15f, 1f);

		public static void NoNavigation(GameObject root)
		{
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)root == (Object)null))
			{
				Selectable[] componentsInChildren = root.GetComponentsInChildren<Selectable>(true);
				foreach (Selectable obj in componentsInChildren)
				{
					Navigation navigation = default(Navigation);
					((Navigation)(ref navigation)).mode = (Mode)0;
					obj.navigation = navigation;
				}
			}
		}

		public static void SetAccent(GameObject buttonObject, bool accent, Color normal)
		{
			//IL_0036: 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)
			Button val = (((Object)(object)buttonObject != (Object)null) ? buttonObject.GetComponent<Button>() : null);
			if ((Object)(object)val != (Object)null && (Object)(object)((Selectable)val).targetGraphic != (Object)null)
			{
				((Selectable)val).targetGraphic.color = (accent ? NewAccent : normal);
			}
		}

		public static void PlaceTopLeft(RectTransform rect, Vector2 position, Vector2 size)
		{
			//IL_000b: 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_0035: 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_0047: Unknown result type (might be due to invalid IL or missing references)
			rect.anchorMin = new Vector2(0f, 1f);
			rect.anchorMax = new Vector2(0f, 1f);
			rect.pivot = new Vector2(0f, 1f);
			rect.sizeDelta = size;
			rect.anchoredPosition = position;
		}

		public static void DestroyComponentsByName(GameObject go, params string[] typeNames)
		{
			Component[] components = go.GetComponents<Component>();
			foreach (Component val in components)
			{
				if ((Object)(object)val == (Object)null)
				{
					continue;
				}
				string name = ((object)val).GetType().Name;
				for (int j = 0; j < typeNames.Length; j++)
				{
					if (name == typeNames[j])
					{
						Object.Destroy((Object)(object)val);
						break;
					}
				}
			}
		}

		public static void DestroyChild(Transform parent, string childName)
		{
			Transform val = parent.Find(childName);
			if ((Object)(object)val != (Object)null)
			{
				Object.Destroy((Object)(object)((Component)val).gameObject);
			}
		}

		public static void StripTabClone(GameObject go)
		{
			DestroyComponentsByName(go, "UIGamePad", "ButtonTextColor");
			DestroyChild(go.transform, "gamepad_hint");
			DestroyChild(go.transform, "Selected");
		}

		public static void FitLabel(TMP_Text text)
		{
			if (!((Object)(object)text == (Object)null))
			{
				text.textWrappingMode = (TextWrappingModes)0;
				text.overflowMode = (TextOverflowModes)1;
				text.enableAutoSizing = true;
				text.fontSizeMin = 8f;
			}
		}
	}
}
namespace Momoti.TabSecret.Stations
{
	internal sealed class StationInfo
	{
		public readonly string PrefabName;

		public readonly string Token;

		public readonly StationKind Kind;

		public StationInfo(string prefabName, string token, StationKind kind)
		{
			PrefabName = prefabName;
			Token = token;
			Kind = kind;
		}
	}
	internal enum StationKind
	{
		Vanilla,
		Cooking,
		Modded
	}
	internal static class StationResolver
	{
		private static readonly Dictionary<string, StationInfo> _cache = new Dictionary<string, StationInfo>();

		private static int _recipeCount = -1;

		public static StationInfo Resolve(CraftingStation station)
		{
			if ((Object)(object)station == (Object)null)
			{
				return null;
			}
			int num = (((Object)(object)ObjectDB.instance != (Object)null && ObjectDB.instance.m_recipes != null) ? ObjectDB.instance.m_recipes.Count : 0);
			if (num != _recipeCount)
			{
				_cache.Clear();
				_recipeCount = num;
			}
			string text = PrefabName(((Object)((Component)station).gameObject).name);
			if (_cache.TryGetValue(text, out var value))
			{
				return value;
			}
			StationKind stationKind = (IsCooking(station, text) ? StationKind.Cooking : ((!VanillaSnapshot.IsVanillaStation(text)) ? StationKind.Modded : StationKind.Vanilla));
			if (stationKind == StationKind.Modded)
			{
				ModLog.Info("Station " + text + " is modded (not in vanilla snapshot)");
			}
			value = new StationInfo(text, station.m_name, stationKind);
			_cache[text] = value;
			return value;
		}

		public static void ClearCache()
		{
			_cache.Clear();
			_recipeCount = -1;
		}

		private static string PrefabName(string name)
		{
			if (name == null || !name.EndsWith("(Clone)"))
			{
				return name;
			}
			return name.Substring(0, name.Length - "(Clone)".Length).Trim();
		}

		private static bool IsCooking(CraftingStation station, string prefab)
		{
			RuleSet current = RuleSet.Current;
			if (current.CookingStationsRemove.Contains(prefab))
			{
				return false;
			}
			if (current.CookingStationsAdd.Contains(prefab))
			{
				return Log(prefab, "json add", 0f);
			}
			if (current.CookingSkills.Contains(((object)Unsafe.As<SkillType, SkillType>(ref station.m_craftingSkill)/*cast due to .constrained prefix*/).ToString()))
			{
				return Log(prefab, "skill " + ((object)Unsafe.As<SkillType, SkillType>(ref station.m_craftingSkill)/*cast due to .constrained prefix*/).ToString(), 0f);
			}
			float num = FoodShare(prefab);
			if (num >= current.CookingThreshold)
			{
				return Log(prefab, "food share", num);
			}
			return false;
		}

		private static float FoodShare(string prefab)
		{
			if ((Object)(object)ObjectDB.instance == (Object)null || ObjectDB.instance.m_recipes == null)
			{
				return 0f;
			}
			int num = 0;
			int num2 = 0;
			foreach (Recipe recipe in ObjectDB.instance.m_recipes)
			{
				if (!((Object)(object)recipe == (Object)null) && recipe.m_enabled && !((Object)(object)recipe.m_item == (Object)null) && !((Object)(object)recipe.m_craftingStation == (Object)null) && !(PrefabName(((Object)((Component)recipe.m_craftingStation).gameObject).name) != prefab))
				{
					num++;
					if (FoodSorter.IsFood(recipe))
					{
						num2++;
					}
				}
			}
			if (num != 0)
			{
				return (float)num2 / (float)num;
			}
			return 0f;
		}

		private static bool Log(string prefab, string reason, float value)
		{
			ModLog.Info("Station " + prefab + " is cooking (" + reason + ((value > 0f) ? (" " + value.ToString("0.00")) : "") + ")");
			return true;
		}
	}
	internal static class VanillaSnapshot
	{
		private static readonly HashSet<string> _vanillaItems = new HashSet<string>();

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

		public static int VanillaItemCount => _vanillaItems.Count;

		public static int VanillaStationCount => _vanillaStations.Count;

		public static bool ItemsCaptured { get; private set; }

		public static bool StationsCaptured { get; private set; }

		public static void CaptureItems(ObjectDB other)
		{
			if ((Object)(object)other == (Object)null || other.m_items == null)
			{
				return;
			}
			_vanillaItems.Clear();
			foreach (GameObject item in other.m_items)
			{
				if ((Object)(object)item != (Object)null)
				{
					_vanillaItems.Add(((Object)item).name);
				}
			}
			ItemsCaptured = true;
		}

		public static void CaptureStations(List<GameObject> prefabs)
		{
			if (prefabs == null)
			{
				return;
			}
			_vanillaStations.Clear();
			foreach (GameObject prefab in prefabs)
			{
				if ((Object)(object)prefab != (Object)null && (Object)(object)prefab.GetComponent<CraftingStation>() != (Object)null)
				{
					_vanillaStations.Add(((Object)prefab).name);
				}
			}
			StationsCaptured = true;
		}

		public static bool IsVanillaItem(string prefabName)
		{
			if (ItemsCaptured)
			{
				return _vanillaItems.Contains(prefabName);
			}
			return true;
		}

		public static bool IsVanillaStation(string prefabName)
		{
			if (StationsCaptured)
			{
				return _vanillaStations.Contains(prefabName);
			}
			return true;
		}
	}
}
namespace Momoti.TabSecret.Persistence
{
	internal static class SeenRecipeStore
	{
		private static readonly HashSet<string> _newSet = new HashSet<string>();

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

		private static Player _owner;

		public static int PieceCount => _newPieces.Count;

		public static int Count => _newSet.Count;

		public static IEnumerable<string> All => _newSet;

		public static bool IsReadyFor(Player player)
		{
			if ((Object)(object)player != (Object)null)
			{
				return (Object)(object)player == (Object)(object)_owner;
			}
			return false;
		}

		public static bool IsNew(string prefabName)
		{
			if (prefabName != null)
			{
				return _newSet.Contains(prefabName);
			}
			return false;
		}

		public static void MarkNew(string prefabName)
		{
			if (!string.IsNullOrEmpty(prefabName))
			{
				_newSet.Add(prefabName);
			}
		}

		public static void MarkSeen(string prefabName)
		{
			if (prefabName != null)
			{
				_newSet.Remove(prefabName);
			}
		}

		public static bool IsNewPiece(string pieceName)
		{
			if (pieceName != null)
			{
				return _newPieces.Contains(pieceName);
			}
			return false;
		}

		public static void MarkNewPiece(string pieceName)
		{
			if (!string.IsNullOrEmpty(pieceName))
			{
				_newPieces.Add(pieceName);
			}
		}

		public static void MarkPieceSeen(string pieceName)
		{
			if (pieceName != null)
			{
				_newPieces.Remove(pieceName);
			}
		}

		public static void Load(Player player)
		{
			_newSet.Clear();
			_newPieces.Clear();
			_owner = player;
			if ((Object)(object)player == (Object)null)
			{
				return;
			}
			if (!player.m_customData.TryGetValue("TabSecret.Init", out var _))
			{
				player.m_customData["TabSecret.Init"] = "1";
				player.m_customData["TabSecret.New.v1"] = string.Empty;
				player.m_customData["TabSecret.NewPieces.v1"] = string.Empty;
				ModLog.Info("SeenRecipeStore: first run on this character, nothing is marked new");
				return;
			}
			string[] array;
			if (player.m_customData.TryGetValue("TabSecret.NewPieces.v1", out var value2) && !string.IsNullOrEmpty(value2))
			{
				array = value2.Split(new char[1] { ';' });
				foreach (string text in array)
				{
					if (text.Length > 0)
					{
						_newPieces.Add(text);
					}
				}
			}
			if (!player.m_customData.TryGetValue("TabSecret.New.v1", out var value3) || string.IsNullOrEmpty(value3))
			{
				return;
			}
			array = value3.Split(new char[1] { ';' });
			foreach (string text2 in array)
			{
				if (text2.Length != 0 && (!((Object)(object)ObjectDB.instance != (Object)null) || !((Object)(object)ObjectDB.instance.GetItemPrefab(text2) == (Object)null)))
				{
					_newSet.Add(text2);
				}
			}
			ModLog.Info("SeenRecipeStore: " + _newSet.Count + " recipes marked new");
		}

		public static void Save(Player player)
		{
			if (IsReadyFor(player))
			{
				player.m_customData["TabSecret.Init"] = "1";
				player.m_customData["TabSecret.New.v1"] = string.Join(";", new List<string>(_newSet).ToArray());
				player.m_customData["TabSecret.NewPieces.v1"] = string.Join(";", new List<string>(_newPieces).ToArray());
			}
		}
	}
}
namespace Momoti.TabSecret.Patches
{
	internal static class ContainerPatches
	{
		[HarmonyPatch(typeof(Container), "RPC_OpenResponse")]
		private static class OpenResponsePatch
		{
			private static void Postfix(Container __instance, bool __1)
			{
				if (!__1)
				{
					return;
				}
				try
				{
					ChestLearning.OnContainerOpened(__instance);
				}
				catch (Exception ex)
				{
					ModLog.ErrorOnce("patch-chest-open", "ChestLearning open failed: " + ex);
				}
			}
		}

		public const bool Active = true;
	}
	internal static class HudPatches
	{
		[HarmonyPatch(typeof(BuildUiPieceButton), "Setup")]
		private static class SetupPatch
		{
			private static void Postfix(BuildUiPieceButton __instance)
			{
				try
				{
					NewPieceBadges.Refresh(__instance);
				}
				catch (Exception ex)
				{
					ModLog.ErrorOnce("patch-piecebutton-setup", "BuildUiPieceButton.Setup postfix failed: " + ex);
				}
			}
		}

		[HarmonyPatch(typeof(BuildUiPieceButton), "OnPointerEnter")]
		private static class PointerEnterPatch
		{
			private static void Postfix(BuildUiPieceButton __instance)
			{
				try
				{
					NewPieceBadges.OnHover(__instance);
				}
				catch (Exception ex)
				{
					ModLog.ErrorOnce("patch-piecebutton-hover", "BuildUiPieceButton.OnPointerEnter postfix failed: " + ex);
				}
			}
		}

		public const bool Active = true;
	}
	internal static class InputGuardPatches
	{
		public const bool Active = false;
	}
	internal static class InventoryGuiPatches
	{
		[HarmonyPatch(typeof(InventoryGui), "SetupCrafting")]
		private static class SetupCraftingPatch
		{
			private static void Prefix(InventoryGui __instance)
			{
				try
				{
					CraftMenuController.OnOpen(__instance);
					QuantityCraft.OnMenuToggled();
					ChestLearning.Stop();
				}
				catch (Exception ex)
				{
					ModLog.ErrorOnce("patch-setupcrafting", "SetupCrafting prefix failed: " + ex);
				}
			}
		}

		[HarmonyPatch(typeof(InventoryGui), "UpdateRecipeList")]
		private static class UpdateRecipeListPatch
		{
			private static void Prefix(InventoryGui __instance, List<Recipe> recipes)
			{
				try
				{
					CraftMenuController.OnRecipeListBuilding(__instance, recipes);
				}
				catch (Exception ex)
				{
					ModLog.ErrorOnce("patch-updaterecipelist", "UpdateRecipeList prefix failed: " + ex);
				}
			}
		}

		[HarmonyPatch(typeof(InventoryGui), "Update")]
		private static class UpdatePatch
		{
			private static bool Prefix(InventoryGui __instance)
			{
				if (!InputGuard.IsTyping)
				{
					return true;
				}
				if (Reflect.CraftTimer(__instance) >= 0f)
				{
					return true;
				}
				CraftMenuController.OnTypingFrame();
				return false;
			}
		}

		[HarmonyPatch(typeof(InventoryGui), "OnCraftPressed")]
		private static class CraftPressedPatch
		{
			private static void Prefix(InventoryGui __instance)
			{
				try
				{
					QuantityCraft.BeforeCraftPressed(__instance);
				}
				catch (Exception ex)
				{
					ModLog.ErrorOnce("patch-craftpressed-pre", "OnCraftPressed prefix failed: " + ex);
				}
			}

			private static void Postfix(InventoryGui __instance)
			{
				try
				{
					QuantityCraft.AfterCraftPressed(__instance);
				}
				catch (Exception ex)
				{
					ModLog.ErrorOnce("patch-craftpressed-post", "OnCraftPressed postfix failed: " + ex);
				}
			}
		}

		[HarmonyPatch(typeof(InventoryGui), "DoCrafting")]
		private static class DoCraftingPatch
		{
			private static void Postfix(InventoryGui __instance)
			{
				QuantityCraft.Restore(__instance);
			}
		}

		[HarmonyPatch(typeof(InventoryGui), "OnCraftCancelPressed")]
		private static class CraftCancelPatch
		{
			private static void Postfix(InventoryGui __instance)
			{
				QuantityCraft.Restore(__instance);
			}
		}

		[HarmonyPatch(typeof(InventoryGui), "Hide")]
		private static class HidePatch
		{
			private static void Postfix(InventoryGui __instance)
			{
				QuantityCraft.Restore(__instance);
				QuantityCraft.OnMenuToggled();
			}
		}

		[HarmonyPatch(typeof(InventoryGui), "SetRecipe")]
		private static class SetRecipePatch
		{
			private static void Postfix(InventoryGui __instance)
			{
				try
				{
					QuantityCraft.OnRecipeSelected(__instance);
				}
				catch (Exception ex)
				{
					ModLog.ErrorOnce("patch-setrecipe", "SetRecipe postfix failed: " + ex);
				}
			}
		}

		[HarmonyPatch(typeof(InventoryGui), "UpdateRecipe")]
		private static class UpdateRecipePatch
		{
			private static void Prefix(InventoryGui __instance)
			{
				try
				{
					QuantityCraft.BeforeUpdateRecipe(__instance);
				}
				catch (Exception ex)
				{
					ModLog.ErrorOnce("patch-updaterecipe-pre", "UpdateRecipe prefix failed: " + ex);
				}
			}

			private static void Postfix(InventoryGui __instance)
			{
				try
				{
					QuantityCraft.AfterUpdateRecipe(__instance);
				}
				catch (Exception ex)
				{
					ModLog.ErrorOnce("patch-updaterecipe-post", "UpdateRecipe postfix failed: " + ex);
				}
			}
		}

		[HarmonyPatch(typeof(InventoryGui), "OnRepairPressed")]
		private static class RepairPressedPatch
		{
			private static void Prefix(InventoryGui __instance)
			{
				try
				{
					RepairAll.Handled = RepairAll.TryRepairAll(__instance);
				}
				catch (Exception ex)
				{
					RepairAll.Handled = false;
					ModLog.ErrorOnce("patch-repair", "RepairAll failed, vanilla repair runs: " + ex);
				}
			}

			private static void Postfix()
			{
				RepairAll.Handled = false;
			}
		}

		[HarmonyPatch(typeof(InventoryGui), "RepairOneItem")]
		private static class RepairOneItemPatch
		{
			private static bool Prefix()
			{
				return !RepairAll.Handled;
			}
		}

		[HarmonyPatch(typeof(InventoryGui), "AddRecipeToList")]
		private static class AddRecipeToListPatch
		{
			private static void Postfix(InventoryGui __instance)
			{
				try
				{
					if (SeenRecipeStore.Count != 0 && __instance.InCraftTab() && Reflect.LastRecipeElement(__instance, out var recipe, out var element) && (Object)(object)recipe.m_item != (Object)null && SeenRecipeStore.IsNew(((Object)((Component)recipe.m_item).gameObject).name))
					{
						NewBadgeView.Attach(element);
					}
				}
				catch (Exception ex)
				{
					ModLog.ErrorOnce("patch-addrecipe", "AddRecipeToList postfix failed: " + ex);
				}
			}
		}

		[HarmonyPatch(typeof(InventoryGui), "OnSelectedRecipe")]
		private static class SelectedRecipeClickPatch
		{
			private static void Postfix(InventoryGui __instance)
			{
				try
				{
					if (SeenRecipeStore.Count == 0 || !__instance.InCraftTab())
					{
						return;
					}
					ItemData upgradeItem;
					Recipe val = Reflect.SelectedRecipe(__instance, out upgradeItem);
					if (!((Object)(object)val == (Object)null) && !((Object)(object)val.m_item == (Object)null))
					{
						string name = ((Object)((Component)val.m_item).gameObject).name;
						if (SeenRecipeStore.IsNew(name))
						{
							SeenRecipeStore.MarkSeen(name);
							SeenRecipeStore.Save(Player.m_localPlayer);
							NewBadgeView.Remove(Reflect.SelectedElement(__instance));
						}
					}
				}
				catch (Exception ex)
				{
					ModLog.ErrorOnce("patch-selectedclick", "OnSelectedRecipe postfix failed: " + ex);
				}
			}
		}
	}
	internal static class LocalizationPatches
	{
		public const bool Active = false;
	}
	internal static class ObjectDbPatches
	{
		[HarmonyPatch(typeof(ObjectDB), "CopyOtherDB")]
		private static class CopyOtherDbPatch
		{
			[HarmonyPriority(800)]
			private static void Prefix(ObjectDB other)
			{
				try
				{
					if (!VanillaSnapshot.ItemsCaptured)
					{
						VanillaSnapshot.CaptureItems(other);
						ModLog.Info("Vanilla item snapshot captured: " + VanillaSnapshot.VanillaItemCount + " items");
					}
				}
				catch (Exception ex)
				{
					ModLog.Error("CopyOtherDB prefix: " + ex.Message);
				}
			}

			private static void Postfix()
			{
				StationResolver.ClearCache();
				ClassificationCache.Clear();
				ModSourceResolver.ClearCache();
				ChestLearning.ClearCache();
			}
		}

		public const bool Active = true;
	}
	internal static class PlayerControllerPatches
	{
		public static void Apply(Harmony harmony)
		{
			//IL_0046: Unknown result type (might be due to invalid IL or missing references)
			//IL_0053: Expected O, but got Unknown
			MethodInfo methodInfo = AccessTools.Method(typeof(PlayerController), "TakeInput", (Type[])null, (Type[])null);
			if (methodInfo == null)
			{
				ModLog.Warn("PlayerController.TakeInput not found: movement while typing is NOT blocked (see docs/ANALYST_REQUEST_2.md)");
				return;
			}
			MethodInfo methodInfo2 = AccessTools.Method(typeof(PlayerControllerPatches), "TakeInputPostfix", (Type[])null, (Type[])null);
			harmony.Patch((MethodBase)methodInfo, (HarmonyMethod)null, new HarmonyMethod(methodInfo2), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			ModLog.Info("PlayerController.TakeInput patched (input gate while typing)");
		}

		private static void TakeInputPostfix(ref bool __result)
		{
			if (__result && InputGuard.IsTyping)
			{
				__result = false;
			}
		}
	}
	internal static class PlayerPatches
	{
		[HarmonyPatch(typeof(Player), "OnSpawned")]
		private static class OnSpawnedPatch
		{
			private static void Postfix(Player __instance)
			{
				try
				{
					if ((Object)(object)__instance == (Object)(object)Player.m_localPlayer)
					{
						SeenRecipeStore.Load(__instance);
					}
				}
				catch (Exception ex)
				{
					ModLog.ErrorOnce("patch-onspawned", "OnSpawned postfix failed: " + ex);
				}
			}
		}

		[HarmonyPatch(typeof(Player), "AddKnownRecipe")]
		private static class AddKnownRecipePatch
		{
			private static void Prefix(Player __instance, Recipe __0, out bool __state)
			{
				__state = true;
				try
				{
					string text = Token(__0);
					__state = text == null || __instance.IsRecipeKnown(text) || !SeenRecipeStore.IsReadyFor(__instance);
				}
				catch (Exception ex)
				{
					ModLog.ErrorOnce("patch-addknown-pre", "AddKnownRecipe prefix failed: " + ex);
				}
			}

			private static void Postfix(Player __instance, Recipe __0, bool __state)
			{
				if (__state)
				{
					return;
				}
				try
				{
					string text = Token(__0);
					if (text != null && __instance.IsRecipeKnown(text))
					{
						SeenRecipeStore.MarkNew(((Object)((Component)__0.m_item).gameObject).name);
						SeenRecipeStore.Save(__instance);
					}
				}
				catch (Exception ex)
				{
					ModLog.ErrorOnce("patch-addknown-post", "AddKnownRecipe postfix failed: " + ex);
				}
			}

			private static string Token(Recipe recipe)
			{
				if (!((Object)(object)recipe == (Object)null) && !((Object)(object)recipe.m_item == (Object)null))
				{
					return recipe.m_item.m_itemData.m_shared.m_name;
				}
				return null;
			}
		}

		[HarmonyPatch(typeof(Player), "AddKnownPiece")]
		private static class AddKnownPiecePatch
		{
			private static void Prefix(Player __instance, Piece __0, out bool __state)
			{
				__state = true;
				try
				{
					__state = (Object)(object)__0 == (Object)null || __instance.IsRecipeKnown(__0.m_name) || !SeenRecipeStore.IsReadyFor(__instance);
				}
				catch (Exception ex)
				{
					ModLog.ErrorOnce("patch-addpiece-pre", "AddKnownPiece prefix failed: " + ex);
				}
			}

			private static void Postfix(Player __instance, Piece __0, bool __state)
			{
				if (__state)
				{
					return;
				}
				try
				{
					if (__instance.IsRecipeKnown(__0.m_name))
					{
						SeenRecipeStore.MarkNewPiece(__0.m_name);
						SeenRecipeStore.Save(__instance);
					}
				}
				catch (Exception ex)
				{
					ModLog.ErrorOnce("patch-addpiece-post", "AddKnownPiece postfix failed: " + ex);
				}
			}
		}

		public const bool Active = true;
	}
	internal static class ZNetScenePatches
	{
		[HarmonyPatch(typeof(ZNetScene), "Awake")]
		private static class AwakePatch
		{
			[HarmonyPriority(800)]
			private static void Prefix(ZNetScene __instance)
			{
				try
				{
					if (!VanillaSnapshot.StationsCaptured)
					{
						VanillaSnapshot.CaptureStations(__instance.m_prefabs);
						ModLog.Info("Vanilla station snapshot captured: " + VanillaSnapshot.VanillaStationCount + " stations");
					}
				}
				catch (Exception ex)
				{
					ModLog.Error("ZNetScene.Awake prefix: " + ex.Message);
				}
			}
		}

		public const bool Active = true;
	}
}
namespace Momoti.TabSecret.Lang
{
	internal static class LanguageIds
	{
		public static readonly string[] All = new string[13]
		{
			"English", "French", "German", "Spanish", "Russian", "Chinese", "Turkish", "Japanese", "Portuguese_Brazilian", "Ukrainian",
			"Italian", "Korean", "Polish"
		};

		public const string Fallback = "English";
	}
	internal static class Loc
	{
		private static readonly Dictionary<string, Dictionary<string, string>> _byLanguage = new Dictionary<string, Dictionary<string, string>>();

		public static void Init()
		{
			_byLanguage.Clear();
			Assembly assembly = typeof(Loc).Assembly;
			string[] all = LanguageIds.All;
			foreach (string text in all)
			{
				string resource = "Momoti.TabSecret.Translations." + text + "." + text + ".json";
				Dictionary<string, string> dictionary = ReadMap(assembly, resource);
				if (dictionary != null)
				{
					_byLanguage[text] = dictionary;
				}
			}
			ModLog.Info("Translations loaded: " + _byLanguage.Count + " of " + LanguageIds.All.Length + " files");
		}

		public static void LoadLanguage(string languageId, string json)
		{
			Dictionary<string, string> dictionary = ParseMap(json);
			if (dictionary != null)
			{
				_byLanguage[languageId] = dictionary;
			}
		}

		public static string T(string token)
		{
			if (string.IsNullOrEmpty(token))
			{
				return "";
			}
			string key = ((token[0] == '$') ? token.Substring(1) : token);
			if (TryGet(CurrentLanguage(), key, out var value))
			{
				return value;
			}
			if (TryGet("English", key, out value))
			{
				return value;
			}
			return token;
		}

		public static string F(string token, params object[] args)
		{
			return string.Format(T(token), args);
		}

		private static string CurrentLanguage()
		{
			Localization instance = Localization.instance;
			if (instance == null)
			{
				return "English";
			}
			return instance.GetSelectedLanguage();
		}

		private static bool TryGet(string language, string key, out string value)
		{
			if (_byLanguage.TryGetValue(language, out var value2))
			{
				return value2.TryGetValue(key, out value);
			}
			value = null;
			return false;
		}

		private static Dictionary<string, string> ReadMap(Assembly asm, string resource)
		{
			try
			{
				using Stream stream = asm.GetManifestResourceStream(resource);
				if (stream == null)
				{
					ModLog.Warn("Missing translation resource: " + resource);
					return null;
				}
				using StreamReader streamReader = new StreamReader(stream, Encoding.UTF8);
				return ParseMap(streamReader.ReadToEnd());
			}
			catch (Exception ex)
			{
				ModLog.Error("Translation load failed (" + resource + "): " + ex.Message);
				return null;
			}
		}

		private static Dictionary<string, string> ParseMap(string json)
		{
			if (!(JsonLite.Parse(json) is Dictionary<string, object> dictionary))
			{
				return null;
			}
			Dictionary<string, string> dictionary2 = new Dictionary<string, string>();
			foreach (KeyValuePair<string, object> item in dictionary)
			{
				if (item.Value is string value)
				{
					dictionary2[item.Key] = value;
				}
			}
			return dictionary2;
		}
	}
	internal static class Tokens
	{
		public const string TabPrefix = "$momoti_tabsecret_tab_";

		public const string UiNew = "$momoti_tabsecret_ui_new";

		public const string UiSearchPlaceholder = "$momoti_tabsecret_ui_search_placeholder";

		public const string UiNewBadge = "$momoti_tabsecret_ui_new_badge";

		public const string MsgRepairedN = "$momoti_tabsecret_msg_repaired_n";

		public const string MsgCraftClamped = "$momoti_tabsecret_msg_craft_clamped";

		public static string ForTab(string tabKey)
		{
			if (!(tabKey == "new"))
			{
				return "$momoti_tabsecret_tab_" + tabKey;
			}
			return "$momoti_tabsecret_ui_new";
		}
	}
}
namespace Momoti.TabSecret.Features
{
	internal static class ChestLearning
	{
		private static readonly HashSet<string> _names = new HashSet<string>();

		private static Inventory _watched;

		public static void OnContainerOpened(Container container)
		{
			Stop();
			if (!((Object)(object)container == (Object)null) && TabSecretSettings.ChestLearning.Value)
			{
				Inventory inventory = container.GetInventory();
				if (inventory != null)
				{
					_watched = inventory;
					Inventory watched = _watched;
					watched.m_onChanged = (Action)Delegate.Combine(watched.m_onChanged, new Action(OnChanged));
					Scan(inventory);
				}
			}
		}

		public static void Stop()
		{
			if (_watched != null)
			{
				Inventory watched = _watched;
				watched.m_onChanged = (Action)Delegate.Remove(watched.m_onChanged, new Action(OnChanged));
			}
			_watched = null;
		}

		public static void ClearCache()
		{
		}

		private static void OnChanged()
		{
			try
			{
				if (_watched != null && TabSecretSettings.ChestLearning.Value)
				{
					Scan(_watched);
				}
			}
			catch (Exception ex)
			{
				ModLog.ErrorOnce("chest-scan", "ChestLearning scan failed: " + ex);
			}
		}

		private static void Scan(Inventory inventory)
		{
			Player localPlayer = Player.m_localPlayer;
			if ((Object)(object)localPlayer == (Object)null)
			{
				return;
			}
			bool flag = false;
			_names.Clear();
			foreach (ItemData allItem in inventory.GetAllItems())
			{
				if (allItem != null && allItem.m_shared != null)
				{
					string name = allItem.m_shared.m_name;
					if (_names.Add(name) && !localPlayer.IsKnownMaterial(name))
					{
						localPlayer.AddKnownItem(allItem);
						flag = true;
					}
				}
			}
			if (flag)
			{
				CraftMenuController.RequestRebuild();
			}
		}
	}
	internal static class NewPieceBadges
	{
		private const string BadgeName = "TabSecret_NewBadge";

		private static bool _resolved;

		private static FieldInfo _buildSelection;

		public static void Refresh(BuildUiPieceButton button)
		{
			if ((Object)(object)button == (Object)null)
			{
				return;
			}
			Piece piece = button.Piece;
			bool num = (Object)(object)piece != (Object)null && SeenRecipeStore.PieceCount > 0 && SeenRecipeStore.IsNewPiece(piece.m_name);
			Transform val = ((Component)button).transform.Find("TabSecret_NewBadge");
			if (num)
			{
				if ((Object)(object)val == (Object)null)
				{
					val = CreateBadge(((Component)button).gameObject);
				}
				if ((Object)(object)val != (Object)null)
				{
					((Component)val).gameObject.SetActive(true);
				}
			}
			else if ((Object)(object)val != (Object)null)
			{
				((Component)val).gameObject.SetActive(false);
			}
		}

		public static void OnHover(BuildUiPieceButton button)
		{
			if (!((Object)(object)button == (Object)null) && !((Object)(object)button.Piece == (Object)null) && SeenRecipeStore.PieceCount != 0 && SeenRecipeStore.IsNewPiece(button.Piece.m_name))
			{
				SeenRecipeStore.MarkPieceSeen(button.Piece.m_name);
				SeenRecipeStore.Save(Player.m_localPlayer);
				Transform val = ((Component)button).transform.Find("TabSecret_NewBadge");
				if ((Object)(object)val != (Object)null)
				{
					((Component)val).gameObject.SetActive(false);
				}
			}
		}

		private static Transform CreateBadge(GameObject button)
		{
			//IL_00f5: Unknown result type (might be due to invalid IL or missing references)
			//IL_0128: Unknown result type (might be due to invalid IL or missing references)
			//IL_013d: 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_0167: Unknown result type (might be due to invalid IL or missing references)
			//IL_017b: Unknown result type (might be due to invalid IL or missing references)
			if (!_resolved)
			{
				_resolved = true;
				_buildSelection = AccessTools.Field(typeof(Hud), "m_buildSelection");
				if (_buildSelection == null)
				{
					ModLog.Warn("Hud.m_buildSelection not found: new labels in the build menu are disabled");
				}
			}
			if (_buildSelection == null || (Object)(object)Hud.instance == (Object)null)
			{
				return null;
			}
			object? value = _buildSelection.GetValue(Hud.instance);
			TMP_Text val = (TMP_Text)((value is TMP_Text) ? value : null);
			if ((Object)(object)val == (Object)null)
			{
				return null;
			}
			GameObject val2 = Object.Instantiate<GameObject>(((Component)val).gameObject, button.transform, false);
			((Object)val2).name = "TabSecret_NewBadge";
			for (int num = val2.transform.childCount - 1; num >= 0; num--)
			{
				Object.Destroy((Object)(object)((Component)val2.transform.GetChild(num)).gameObject);
			}
			TMP_Text component = val2.GetComponent<TMP_Text>();
			component.text = Loc.T("$momoti_tabsecret_ui_new_badge");
			component.enableAutoSizing = false;
			component.fontSize = 10f;
			component.fontStyle = (FontStyles)1;
			((Graphic)component).color = Color.white;
			component.alignment = (TextAlignmentOptions)260;
			((Graphic)component).raycastTarget = false;
			component.overflowMode = (TextOverflowModes)0;
			RectTransform rectTransform = component.rectTransform;
			rectTransform.anchorMin = new Vector2(1f, 1f);
			rectTransform.anchorMax = new Vector2(1f, 1f);
			rectTransform.pivot = new Vector2(1f, 1f);
			rectTransform.sizeDelta = new Vector2(60f, 14f);
			rectTransform.anchoredPosition = new Vector2(-2f, -2f);
			return val2.transform;
		}
	}
	internal static class QuantityCraft
	{
		private const float BatchFactor = 0.9f;

		private static bool _active;

		private static Recipe _lastRecipe;

		private static bool _pending;

		private static int _origAmount;

		private static float _origDuration;

		private static bool _override;

		private static bool _shiftHeld;

		private static int _savedValue = 1;

		public static void BeforeCraftPressed(InventoryGui gui)
		{
			_pending = false;
			CaptureVanilla(gui);
			Restore(gui);
			if (!LayoutBuilder.Ok || !Reflect.CanSetMultiCrafting)
			{
				return;
			}
			int value = QuantityFieldView.Value;
			if (value <= 1)
			{
				return;
			}
			ItemData upgradeItem;
			Recipe val = Reflect.SelectedRecipe(gui, out upgradeItem);
			Player localPlayer = Player.m_localPlayer;
			if ((Object)(object)val == (Object)null || (Object)(object)val.m_item == (Object)null || upgradeItem != null || (Object)(object)localPlayer == (Object)null)
			{
				return;
			}
			int num = ClampMax(localPlayer, val, value);
			if (num > 0)
			{
				if (num < value)
				{
					QuantityFieldView.SetValue(num);
					((Character)localPlayer).Message((MessageType)2, string.Format(Loc.T("$momoti_tabsecret_msg_craft_clamped"), num), 0, (Sprite)null, false);
				}
				if (num > 1)
				{
					gui.m_multiCraftAmount = num;
					gui.m_multiCraftDuration = gui.m_craftDuration * (float)num * 0.9f;
					_active = true;
					_pending = true;
				}
			}
		}

		public static void AfterCraftPressed(InventoryGui gui)
		{
			if (_pending)
			{
				_pending = false;
				Reflect.SelectedRecipe(gui, out var upgradeItem);
				if (Reflect.CraftTimer(gui) == 0f && upgradeItem == null)
				{
					Reflect.SetMultiCrafting(gui, value: true);
				}
				else
				{
					Restore(gui);
				}
			}
		}

		public static void BeforeUpdateRecipe(InventoryGui gui)
		{
			_override = false;
			if (!LayoutBuilder.Ok || !Reflect.CanSetTouchMulti || !Reflect.CanSetMultiCrafting)
			{
				return;
			}
			CaptureVanilla(gui);
			bool flag = ZInput.GetButton("AltPlace") || ZInput.GetButton("JoyLStick");
			if (!_shiftHeld && !flag && QuantityFieldView.Value <= 1)
			{
				return;
			}
			ItemData upgradeItem;
			bool num = (Object)(object)Reflect.SelectedRecipe(gui, out upgradeItem) != (Object)null && upgradeItem == null && gui.InCraftTab();
			SyncShift(num);
			if (num && !(Reflect.CraftTimer(gui) >= 0f))
			{
				int value = QuantityFieldView.Value;
				if (value > 1)
				{
					gui.m_multiCraftAmount = value;
					Reflect.SetTouchMultiCrafting(gui, value: true);
					_override = true;
				}
			}
		}

		public static void AfterUpdateRecipe(InventoryGui gui)
		{
			if (_override)
			{
				_override = false;
				Reflect.SetTouchMultiCrafting(gui, value: false);
				if (Reflect.CraftTimer(gui) < 0f && _origAmount > 0)
				{
					gui.m_multiCraftAmount = _origAmount;
				}
				TMP_Text val = (((Object)(object)gui.m_craftButton != (Object)null) ? ((Component)gui.m_craftButton).GetComponentInChildren<TMP_Text>() : null);
				if ((Object)(object)val != (Object)null)
				{
					val.text = Localization.instance.Localize("$inventory_craftbutton");
				}
			}
		}

		private static void SyncShift(bool craftable)
		{
			bool flag = craftable && (ZInput.GetButton("AltPlace") || ZInput.GetButton("JoyLStick"));
			if (!QuantityFieldView.IsFocused)
			{
				if (flag && !_shiftHeld)
				{
					_savedValue = QuantityFieldView.Value;
					QuantityFieldView.SetValue(_origAmount);
					_shiftHeld = true;
				}
				else if (!flag && _shiftHeld)
				{
					QuantityFieldView.SetValue(_savedValue);
					_shiftHeld = false;
				}
			}
		}

		private static void CaptureVanilla(InventoryGui gui)
		{
			if (_origAmount == 0)
			{
				_origAmount = gui.m_multiCraftAmount;
				_origDuration = gui.m_multiCraftDuration;
			}
		}

		public static void OnRecipeSelected(InventoryGui gui)
		{
			ItemData upgradeItem;
			Recipe val = Reflect.SelectedRecipe(gui, out upgradeItem);
			if (!((Object)(object)val == (Object)(object)_lastRecipe))
			{
				_lastRecipe = val;
				QuantityFieldView.Reset();
			}
		}

		public static void OnMenuToggled()
		{
			_lastRecipe = null;
			_shiftHeld = false;
			QuantityFieldView.Reset();
		}

		public static void Restore(InventoryGui gui)
		{
			if (_active && !((Object)(object)gui == (Object)null) && _origAmount != 0)
			{
				gui.m_multiCraftAmount = _origAmount;
				gui.m_multiCraftDuration = _origDuration;
				_active = false;
			}
		}

		public static int ClampMax(Player player, Recipe recipe, int wanted)
		{
			if (!CanCraft(player, recipe, 1))
			{
				return 0;
			}
			int num = 1;
			int num2 = wanted;
			while (num < num2)
			{
				int num3 = (num + num2 + 1) / 2;
				if (CanCraft(player, recipe, num3))
				{
					num = num3;
				}
				else
				{
					num2 = num3 - 1;
				}
			}
			return num;
		}

		private static bool CanCraft(Player player, Recipe recipe, int n)
		{
			if (!player.NoCostCheat() && !ZoneSystem.instance.GetGlobalKey((GlobalKeys)25) && !player.HaveRequirements(recipe, false, 1, n))
			{
				return false;
			}
			int num = default(int);
			ItemData val = default(ItemData);
			int amount = recipe.GetAmount(1, ref num, ref val, n);
			return ((Humanoid)player).GetInventory().CanAddItem(((Component)recipe.m_item).gameObject, amount);
		}
	}
	internal static class RepairAll
	{
		private static readonly List<ItemData> _worn = new List<ItemData>();

		private static readonly List<ItemData> _repairable = new List<ItemData>();

		public static bool Handled;

		public static bool TryRepairAll(InventoryGui gui)
		{
			//IL_015c: 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_016f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0175: Unknown result type (might be due to invalid IL or missing references)
			if (!TabSecretSettings.RepairAll.Value)
			{
				return false;
			}
			Player localPlayer = Player.m_localPlayer;
			if ((Object)(object)localPlayer == (Object)null)
			{
				return false;
			}
			CraftingStation currentCraftingStation = localPlayer.GetCurrentCraftingStation();
			if (((Object)(object)currentCraftingStation == (Object)null && !localPlayer.NoCostCheat()) || ((Object)(object)currentCraftingStation != (Object)null && !currentCraftingStation.CheckUsable(localPlayer, false)))
			{
				return false;
			}
			Func<ItemData, bool> func = AccessTools.MethodDelegate<Func<ItemData, bool>>(AccessTools.Method(typeof(InventoryGui), "CanRepair", (Type[])null, (Type[])null), (object)gui, true);
			_worn.Clear();
			_repairable.Clear();
			((Humanoid)localPlayer).GetInventory().GetWornItems(_worn);
			foreach (ItemData item in _worn)
			{
				if (func(item))
				{
					_repairable.Add(item);
				}
			}
			if (_repairable.Count == 0)
			{
				return false;
			}
			float num = 0f;
			foreach (ItemData item2 in _repairable)
			{
				num += 1f - item2.m_durability / item2.GetMaxDurability();
				item2.m_durability = item2.GetMaxDurability();
			}
			((Character)localPlayer).RaiseSkill((SkillType)107, num);
			if ((Object)(object)currentCraftingStation != (Object)null)
			{
				currentCraftingStation.m_repairItemDoneEffects.Create(((Component)currentCraftingStation).transform.position, Quaternion.identity, (Transform)null, 1f, -1, default(ZDOID));
			}
			string text = ((_repairable.Count == 1) ? Localization.instance.Localize("$msg_repaired", new string[1] { _repairable[0].m_shared.m_name }) : string.Format(Loc.T("$momoti_tabsecret_msg_repaired_n"), _repairable.Count));
			((Character)localPlayer).Message((MessageType)2, text, 0, (Sprite)null, false);
			return true;
		}
	}
}
namespace Momoti.TabSecret.Diagnostics
{
	internal class DumpHotkey : MonoBehaviour
	{
		private void Update()
		{
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			ConfigEntry<bool> dumpEnabled = TabSecretSettings.DumpEnabled;
			if (dumpEnabled == null || !dumpEnabled.Value)
			{
				return;
			}
			try
			{
				if (ZInput.GetKeyDown(TabSecretSettings.DumpKey.Value, true))
				{
					DumpWriter.Run();
				}
			}
			catch (Exception)
			{
			}
		}
	}
	internal static class DumpWriter
	{
		private const int MaxDepth = 14;

		public static void Run()
		{
			StringBuilder stringBuilder = new StringBuilder(131072);
			stringBuilder.AppendLine("# TabSecret dump");
			stringBuilder.AppendLine("time: " + DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"));
			stringBuilder.AppendLine("unity app version: " + Application.version);
			stringBuilder.AppendLine("screen: " + Screen.width + "x" + Screen.height);
			Section(stringBuilder, "LANGUAGES", DumpLanguages);
			Section(stringBuilder, "CURRENT STATION", DumpCurrentStation);
			Section(stringBuilder, "STATION PREFABS", DumpStations);
			Section(stringBuilder, "RECIPES", DumpRecipes);
			Section(stringBuilder, "INVENTORYGUI UI", DumpInventoryGui);
			Section(stringBuilder, "BUILD UI SEARCH FIELD", DumpBuildSearchField);
			try
			{
				string text = Path.Combine(Paths.BepInExRootPath, "TabSecret_dump.txt");
				File.WriteAllText(text, stringBuilder.ToString(), new UTF8Encoding(encoderShouldEmitUTF8Identifier: false));
				ModLog.Info("Dump written: " + text);
			}
			catch (Exception ex)
			{
				ModLog.Error("Dump write failed: " + ex);
			}
		}

		private static void Section(StringBuilder sb, string title, Action<StringBuilder> body)
		{
			sb.AppendLine();
			sb.AppendLine("## " + title);
			try
			{
				body(sb);
			}
			catch (Exception ex)
			{
				sb.AppendLine("ERROR: " + ex.Message);
			}
		}

		private static void DumpLanguages(StringBuilder sb)
		{
			Localization instance = Localization.instance;
			if (instance == null)
			{
				sb.AppendLine("Localization.instance == null");
				return;
			}
			sb.AppendLine("selected: " + instance.GetSelectedLanguage());
			List<string> languages = instance.GetLanguages();
			sb.AppendLine("available: " + ((languages != null) ? string.Join(", ", languages.ToArray()) : "null"));
		}

		private static void DumpCurrentStation(StringBuilder sb)
		{
			Player localPlayer = Player.m_localPlayer;
			if ((Object)(object)localPlayer == (Object)null)
			{
				sb.AppendLine("no local player");
				return;
			}
			CraftingStation currentCraftingStation = localPlayer.GetCurrentCraftingStation();
			if ((Object)(object)currentCraftingStation == (Object)null)
			{
				sb.AppendLine("current station: none");
			}
			else
			{
				sb.AppendLine("current station: " + ((Object)((Component)currentCraftingStation).gameObject).name + " | m_name=" + currentCraftingStation.m_name + " | level=" + currentCraftingStation.GetLevel(true));
			}
			sb.AppendLine("InventoryGui visible: " + InventoryGui.IsVisible());
		}

		private static void DumpStations(StringBuilder sb)
		{
			//IL_00e6: Unknown result type (might be due to invalid IL or missing references)
			ZNetScene instance = ZNetScene.instance;
			if ((Object)(object)instance == (Object)null)
			{
				sb.AppendLine("ZNetScene.instance == null");
				return;
			}
			int num = 0;
			foreach (GameObject prefab in instance.m_prefabs)
			{
				if ((Object)(object)prefab == (Object)null)
				{
					continue;
				}
				CraftingStation component = prefab.GetComponent<CraftingStation>();
				CookingStation component2 = prefab.GetComponent<CookingStation>();
				if (!((Object)(object)component == (Object)null) || !((Object)(object)component2 == (Object)null))
				{
					sb.Append(((Object)prefab).name);
					if ((Object)(object)component != (Object)null)
					{
						sb.Append(" | CraftingStation m_name=").Append(component.m_name).Append(" hasCraftTab=")
							.Append(component.m_hasCraftTab)
							.Append(" canRepair=")
							.Append(component.m_canRepair)
							.Append(" upgrader=")
							.Append(component.m_upgrader)
							.Append(" skill=")
							.Append(component.m_craftingSkill);
					}
					if ((Object)(object)component2 != (Object)null)
					{
						sb.Append(" | CookingStation conversions=").Append((component2.m_conversion != null) ? component2.m_conversion.Count : 0);
					}
					sb.AppendLine();
					num++;
				}
			}
			sb.AppendLine("total: " + num);
		}

		private static void DumpRecipes(StringBuilder sb)
		{
			//IL_0228: Unknown result type (might be due to invalid IL or missing references)
			ObjectDB instance = ObjectDB.instance;
			if ((Object)(object)instance == (Object)null)
			{
				sb.Appen