Decompiled source of HelpBookPlus v1.0.5

plugins\HelpBookPlus.dll

Decompiled a week ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
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 BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using HelpBookPlus.Data;
using HelpBookPlus.Input;
using HelpBookPlus.Localization;
using HelpBookPlus.UI;
using Microsoft.CodeAnalysis;
using TMPro;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: IgnoresAccessChecksTo("assembly_guiutils")]
[assembly: IgnoresAccessChecksTo("assembly_utils")]
[assembly: IgnoresAccessChecksTo("assembly_valheim")]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: AssemblyCompany("PONEIS")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyDescription("In-game recipe book: ESC menu button (or H / helpbookplus) to browse craft recipes")]
[assembly: AssemblyFileVersion("1.0.5.0")]
[assembly: AssemblyInformationalVersion("1.0.5+ecbcf15cbb3340fb98e6d428933452b20ca86f1d")]
[assembly: AssemblyProduct("HelpBookPlus")]
[assembly: AssemblyTitle("HelpBookPlus")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.5.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 HelpBookPlus
{
	internal static class ModConfig
	{
		internal static ConfigEntry<bool> Enabled;

		internal static ConfigEntry<bool> ShowEscButton;

		internal static ConfigEntry<KeyCode> OpenKey;

		internal static ConfigEntry<string> Language;

		internal static void Bind(ConfigFile config)
		{
			Enabled = config.Bind<bool>("General", "Enabled", true, "Master switch for HelpBookPlus.");
			ShowEscButton = config.Bind<bool>("Controls", "ShowEscButton", true, "Show a Recipes button in the ESC pause menu (recommended).");
			OpenKey = config.Bind<KeyCode>("Controls", "OpenKey", (KeyCode)0, "Optional hotkey to open/close the recipe book. Default None (use ESC menu). Set to H if you want a key.");
			Language = config.Bind<string>("Localization", "Language", "Auto", "Language for HelpBookPlus UI. Auto follows the game. Values: Auto, English, Portuguese.");
			Language.SettingChanged += delegate
			{
				Loc.ApplyLanguagePreference();
			};
		}
	}
	[BepInPlugin("poneis.valheim.HelpBookPlus", "HelpBookPlus", "1.0.5")]
	public class Plugin : BaseUnityPlugin
	{
		public const string PluginGUID = "poneis.valheim.HelpBookPlus";

		public const string PluginName = "HelpBookPlus";

		public const string PluginVersion = "1.0.5";

		internal static Plugin Instance { get; private set; }

		internal static ManualLogSource Log { get; private set; }

		private void Awake()
		{
			Instance = this;
			Log = ((BaseUnityPlugin)this).Logger;
			ModConfig.Bind(((BaseUnityPlugin)this).Config);
			Loc.Init();
			Harmony.CreateAndPatchAll(Assembly.GetExecutingAssembly(), "poneis.valheim.HelpBookPlus");
			((Component)this).gameObject.AddComponent<BookInputListener>();
			HelpBookWindow.Ensure();
			Log.LogInfo((object)"HelpBookPlus 1.0.5 loaded.");
		}
	}
	[HarmonyPatch]
	internal static class ObjectDbInvalidatePatch
	{
		[HarmonyPostfix]
		[HarmonyPatch(typeof(ObjectDB), "CopyOtherDB")]
		private static void CopyOtherDBPostfix()
		{
			RecipeCatalog.Invalidate();
		}
	}
}
namespace HelpBookPlus.UI
{
	internal static class HelpBookMenuButton
	{
		[CompilerGenerated]
		private static class <>O
		{
			public static UnityAction <0>__OnClicked;
		}

		internal const string ObjectName = "HelpBookPlus_Recipes";

		private static Button _button;

		private static TMP_Text _label;

		internal static void Ensure(Menu menu)
		{
			//IL_00a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b3: Expected O, but got Unknown
			//IL_00cd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d8: Expected O, but got Unknown
			if ((Object)(object)menu == (Object)null)
			{
				return;
			}
			Button val = menu.m_settingsButton ?? menu.m_saveButton;
			if ((Object)(object)val == (Object)null)
			{
				return;
			}
			if ((Object)(object)_button != (Object)null && Object.op_Implicit((Object)(object)_button))
			{
				RefreshLabel();
				return;
			}
			GameObject gameObject = ((Component)val).gameObject;
			Transform parent = gameObject.transform.parent;
			GameObject val2 = Object.Instantiate<GameObject>(gameObject, parent);
			((Object)val2).name = "HelpBookPlus_Recipes";
			int siblingIndex = gameObject.transform.GetSiblingIndex();
			val2.transform.SetSiblingIndex(siblingIndex);
			_button = val2.GetComponent<Button>();
			_label = val2.GetComponentInChildren<TMP_Text>(true);
			if ((Object)(object)_button != (Object)null)
			{
				_button.onClick = new ButtonClickedEvent();
				ButtonClickedEvent onClick = _button.onClick;
				object obj = <>O.<0>__OnClicked;
				if (obj == null)
				{
					UnityAction val3 = OnClicked;
					<>O.<0>__OnClicked = val3;
					obj = (object)val3;
				}
				((UnityEvent)onClick).AddListener((UnityAction)obj);
			}
			RefreshLabel();
			Plugin.Log.LogInfo((object)"ESC 'Recipes' button injected.");
		}

		internal static void UpdateVisibility(Menu menu)
		{
			if (!ModConfig.ShowEscButton.Value)
			{
				if ((Object)(object)_button != (Object)null && Object.op_Implicit((Object)(object)_button))
				{
					((Component)_button).gameObject.SetActive(false);
				}
				return;
			}
			Ensure(menu);
			if (!((Object)(object)_button == (Object)null) && Object.op_Implicit((Object)(object)_button))
			{
				if (!((Component)_button).gameObject.activeSelf)
				{
					((Component)_button).gameObject.SetActive(true);
				}
				RefreshLabel();
				if ((Object)(object)menu != (Object)null)
				{
					menu.m_rebuildLayout = true;
				}
			}
		}

		internal static void RefreshLabel()
		{
			if (!((Object)(object)_label == (Object)null) && Object.op_Implicit((Object)(object)_label))
			{
				_label.text = Loc.T("hbp_btn_recipes");
			}
		}

		private static void OnClicked()
		{
			if (!ModConfig.Enabled.Value)
			{
				return;
			}
			try
			{
				if ((Object)(object)Menu.instance != (Object)null && Menu.IsVisible())
				{
					Menu.instance.Hide();
				}
			}
			catch
			{
			}
			HelpBookWindow.Open();
		}

		internal static void Reset()
		{
			_button = null;
			_label = null;
		}
	}
	internal sealed class HelpBookWindow : MonoBehaviour
	{
		private string _search = string.Empty;

		private Vector2 _sideScroll;

		private Vector2 _listScroll;

		private Vector2 _detailScroll;

		private int _selected = -1;

		private List<RecipeEntry> _filtered = new List<RecipeEntry>();

		private RecipeSortMode _sort;

		private RecipeTypeFilter _typeFilter;

		private string _stationKey;

		private GUIStyle _titleStyle;

		private GUIStyle _headerStyle;

		private GUIStyle _groupStyle;

		private GUIStyle _bodyStyle;

		private GUIStyle _boxStyle;

		private GUIStyle _sideBtn;

		private GUIStyle _sideBtnActive;

		private Texture2D _panelTex;

		private Texture2D _activeTex;

		private Texture2D _groupTex;

		private bool _stylesReady;

		internal static HelpBookWindow Instance { get; private set; }

		internal static bool IsOpen { get; private set; }

		internal static void Ensure()
		{
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Expected O, but got Unknown
			if (!((Object)(object)Instance != (Object)null))
			{
				GameObject val = new GameObject("HelpBookPlus_UI");
				Object.DontDestroyOnLoad((Object)val);
				Instance = val.AddComponent<HelpBookWindow>();
			}
		}

		internal static void Toggle()
		{
			if (IsOpen)
			{
				Close();
			}
			else
			{
				Open();
			}
		}

		internal static void Open()
		{
			if (ModConfig.Enabled.Value)
			{
				Ensure();
				Loc.ApplyLanguagePreference();
				RecipeCatalog.EnsureBuilt(force: true);
				IsOpen = true;
				Instance._search = string.Empty;
				Instance._selected = -1;
				Instance._stationKey = null;
				Instance._typeFilter = RecipeTypeFilter.All;
				Instance._sort = RecipeSortMode.NameAsc;
				Instance.RefreshFilter(resetSelection: true);
				ShowMouse();
			}
		}

		internal static void Close()
		{
			IsOpen = false;
			RestoreMouse();
		}

		private void LateUpdate()
		{
			if (IsOpen)
			{
				ShowMouse();
			}
		}

		private static void ShowMouse()
		{
			Cursor.lockState = (CursorLockMode)0;
			Cursor.visible = true;
		}

		private static void RestoreMouse()
		{
			try
			{
				if (InventoryGui.IsVisible() || Menu.IsVisible() || Console.IsVisible() || TextInput.IsVisible())
				{
					ShowMouse();
					return;
				}
			}
			catch
			{
			}
			Cursor.lockState = (CursorLockMode)1;
			Cursor.visible = false;
		}

		private void OnGUI()
		{
			//IL_007f: Unknown result type (might be due to invalid IL or missing references)
			//IL_009f: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ae: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fd: Unknown result type (might be due to invalid IL or missing references)
			if (IsOpen)
			{
				EnsureStyles();
				float num = Mathf.Clamp((float)Screen.width * 0.82f, 880f, 1400f);
				float num2 = Mathf.Clamp((float)Screen.height * 0.75f, 520f, 860f);
				Rect val = default(Rect);
				((Rect)(ref val))..ctor(((float)Screen.width - num) * 0.5f, ((float)Screen.height - num2) * 0.5f, num, num2);
				GUI.color = new Color(0f, 0f, 0f, 0.55f);
				GUI.DrawTexture(new Rect(0f, 0f, (float)Screen.width, (float)Screen.height), (Texture)(object)Texture2D.whiteTexture);
				GUI.color = Color.white;
				GUI.Box(val, GUIContent.none, _boxStyle);
				GUILayout.BeginArea(new Rect(((Rect)(ref val)).x + 14f, ((Rect)(ref val)).y + 10f, ((Rect)(ref val)).width - 28f, ((Rect)(ref val)).height - 20f));
				GUILayout.Label(Loc.T("hbp_title"), _titleStyle, Array.Empty<GUILayoutOption>());
				GUILayout.Space(4f);
				GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
				GUILayout.Label(Loc.T("hbp_search"), _headerStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(80f) });
				string text = GUILayout.TextField(_search ?? string.Empty, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.ExpandWidth(true) });
				if (text != _search)
				{
					_search = text;
					RefreshFilter(resetSelection: true);
				}
				GUILayout.Label(Loc.Tf("hbp_count", _filtered.Count), _bodyStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(120f) });
				GUILayout.EndHorizontal();
				GUILayout.Space(8f);
				if ((Object)(object)ObjectDB.instance == (Object)null || RecipeCatalog.Entries.Count == 0)
				{
					GUILayout.Label(Loc.T("hbp_not_ready"), _bodyStyle, Array.Empty<GUILayoutOption>());
				}
				else
				{
					GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
					DrawSidebar(((Rect)(ref val)).width * 0.22f);
					GUILayout.Space(8f);
					DrawList(((Rect)(ref val)).width * 0.3f);
					GUILayout.Space(8f);
					DrawDetailPane();
					GUILayout.EndHorizontal();
				}
				GUILayout.FlexibleSpace();
				GUILayout.Label(Loc.T("hbp_close_hint"), _bodyStyle, Array.Empty<GUILayoutOption>());
				GUILayout.EndArea();
			}
		}

		private void DrawSidebar(float width)
		{
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			GUILayout.BeginVertical(GUI.skin.box, (GUILayoutOption[])(object)new GUILayoutOption[2]
			{
				GUILayout.Width(width),
				GUILayout.ExpandHeight(true)
			});
			_sideScroll = GUILayout.BeginScrollView(_sideScroll, Array.Empty<GUILayoutOption>());
			GUILayout.Label(Loc.T("hbp_sort"), _headerStyle, Array.Empty<GUILayoutOption>());
			SortButton(RecipeSortMode.NameAsc, Loc.T("hbp_sort_name_asc"));
			SortButton(RecipeSortMode.NameDesc, Loc.T("hbp_sort_name_desc"));
			SortButton(RecipeSortMode.Station, Loc.T("hbp_sort_station"));
			SortButton(RecipeSortMode.StationLevel, Loc.T("hbp_sort_level"));
			GUILayout.Space(10f);
			GUILayout.Label(Loc.T("hbp_filter_type"), _headerStyle, Array.Empty<GUILayoutOption>());
			TypeButton(RecipeTypeFilter.All, Loc.T("hbp_filter_all"));
			TypeButton(RecipeTypeFilter.Craftable, Loc.T("hbp_filter_craft"));
			TypeButton(RecipeTypeFilter.UpgradeOnly, Loc.T("hbp_filter_upgrade"));
			GUILayout.Space(10f);
			GUILayout.Label(Loc.T("hbp_filter_station"), _headerStyle, Array.Empty<GUILayoutOption>());
			if (SideButton(_stationKey == null, Loc.T("hbp_filter_all")))
			{
				_stationKey = null;
				RefreshFilter(resetSelection: true);
			}
			IReadOnlyList<StationOption> stationOptions = RecipeCatalog.StationOptions;
			for (int i = 0; i < stationOptions.Count; i++)
			{
				StationOption stationOption = stationOptions[i];
				string label = $"{stationOption.DisplayName} ({stationOption.Count})";
				bool active = _stationKey != null && _stationKey == stationOption.Key;
				if (SideButton(active, label))
				{
					_stationKey = stationOption.Key;
					RefreshFilter(resetSelection: true);
				}
			}
			GUILayout.Space(8f);
			if (GUILayout.Button(Loc.T("hbp_filter_clear"), Array.Empty<GUILayoutOption>()))
			{
				_stationKey = null;
				_typeFilter = RecipeTypeFilter.All;
				_sort = RecipeSortMode.NameAsc;
				_search = string.Empty;
				RefreshFilter(resetSelection: true);
			}
			GUILayout.EndScrollView();
			GUILayout.EndVertical();
		}

		private void DrawList(float width)
		{
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			//IL_0102: Unknown result type (might be due to invalid IL or missing references)
			//IL_0107: Unknown result type (might be due to invalid IL or missing references)
			//IL_0121: Unknown result type (might be due to invalid IL or missing references)
			//IL_0148: Unknown result type (might be due to invalid IL or missing references)
			GUILayout.BeginVertical((GUILayoutOption[])(object)new GUILayoutOption[2]
			{
				GUILayout.Width(width),
				GUILayout.ExpandHeight(true)
			});
			_listScroll = GUILayout.BeginScrollView(_listScroll, GUI.skin.box);
			if (_filtered.Count == 0)
			{
				GUILayout.Label(Loc.T("hbp_empty"), _bodyStyle, Array.Empty<GUILayoutOption>());
			}
			else
			{
				bool flag = _sort == RecipeSortMode.Station;
				bool flag2 = _sort == RecipeSortMode.StationLevel;
				string text = null;
				for (int i = 0; i < _filtered.Count; i++)
				{
					RecipeEntry recipeEntry = _filtered[i];
					if (flag || flag2)
					{
						string text2 = (flag2 ? GroupKeyLevel(recipeEntry) : recipeEntry.StationName);
						if (text2 != text)
						{
							text = text2;
							GUILayout.Space(4f);
							GUILayout.Label(text2, _groupStyle, Array.Empty<GUILayoutOption>());
						}
					}
					string obj = ((recipeEntry.Amount > 1) ? $"{recipeEntry.DisplayName} ({recipeEntry.Amount})" : recipeEntry.DisplayName);
					Color backgroundColor = GUI.backgroundColor;
					if (i == _selected)
					{
						GUI.backgroundColor = new Color(0.75f, 0.65f, 0.35f);
					}
					if (GUILayout.Button(obj, GUI.skin.button, Array.Empty<GUILayoutOption>()))
					{
						_selected = i;
					}
					GUI.backgroundColor = backgroundColor;
				}
			}
			GUILayout.EndScrollView();
			GUILayout.EndVertical();
		}

		private static string GroupKeyLevel(RecipeEntry e)
		{
			string stationName = e.StationName;
			int num = Mathf.Max(1, e.StationLevel);
			return Loc.Tf("hbp_group_station_level", stationName, num);
		}

		private void DrawDetailPane()
		{
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			GUILayout.BeginVertical(GUI.skin.box, (GUILayoutOption[])(object)new GUILayoutOption[2]
			{
				GUILayout.ExpandWidth(true),
				GUILayout.ExpandHeight(true)
			});
			_detailScroll = GUILayout.BeginScrollView(_detailScroll, Array.Empty<GUILayoutOption>());
			DrawDetail();
			GUILayout.EndScrollView();
			GUILayout.EndVertical();
		}

		private void SortButton(RecipeSortMode mode, string label)
		{
			if (SideButton(_sort == mode, label))
			{
				_sort = mode;
				RefreshFilter(resetSelection: false);
			}
		}

		private void TypeButton(RecipeTypeFilter filter, string label)
		{
			if (SideButton(_typeFilter == filter, label))
			{
				_typeFilter = filter;
				RefreshFilter(resetSelection: true);
			}
		}

		private bool SideButton(bool active, string label)
		{
			return GUILayout.Button(label, active ? _sideBtnActive : _sideBtn, Array.Empty<GUILayoutOption>());
		}

		private void DrawDetail()
		{
			if (_selected < 0 || _selected >= _filtered.Count)
			{
				GUILayout.Label(Loc.T("hbp_empty"), _bodyStyle, Array.Empty<GUILayoutOption>());
				return;
			}
			RecipeEntry recipeEntry = _filtered[_selected];
			GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
			if ((Object)(object)recipeEntry.Icon != (Object)null)
			{
				DrawSprite(recipeEntry.Icon, 48f);
			}
			GUILayout.BeginVertical(Array.Empty<GUILayoutOption>());
			GUILayout.Label(recipeEntry.DisplayName, _titleStyle, Array.Empty<GUILayoutOption>());
			if (recipeEntry.Amount > 1)
			{
				GUILayout.Label(Loc.Tf("hbp_amount", recipeEntry.Amount), _headerStyle, Array.Empty<GUILayoutOption>());
			}
			GUILayout.Label(Loc.Tf("hbp_prefab", recipeEntry.PrefabName), _bodyStyle, Array.Empty<GUILayoutOption>());
			GUILayout.EndVertical();
			GUILayout.EndHorizontal();
			GUILayout.Space(8f);
			GUILayout.Label(Loc.T("hbp_station"), _headerStyle, Array.Empty<GUILayoutOption>());
			string text = recipeEntry.StationName;
			if (recipeEntry.StationLevel > 1)
			{
				text = text + " — " + Loc.Tf("hbp_station_level", recipeEntry.StationLevel);
			}
			GUILayout.Label(text, _bodyStyle, Array.Empty<GUILayoutOption>());
			if (recipeEntry.UpgradeOnly)
			{
				GUILayout.Space(4f);
				GUILayout.Label(Loc.T("hbp_upgrade_only"), _headerStyle, Array.Empty<GUILayoutOption>());
			}
			GUILayout.Space(10f);
			GUILayout.Label(Loc.T("hbp_ingredients"), _headerStyle, Array.Empty<GUILayoutOption>());
			if (recipeEntry.Requirements == null || recipeEntry.Requirements.Length == 0)
			{
				GUILayout.Label("—", _bodyStyle, Array.Empty<GUILayoutOption>());
				return;
			}
			for (int i = 0; i < recipeEntry.Requirements.Length; i++)
			{
				RecipeRequirement recipeRequirement = recipeEntry.Requirements[i];
				GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
				if ((Object)(object)recipeRequirement.Icon != (Object)null)
				{
					DrawSprite(recipeRequirement.Icon, 28f);
				}
				string text2 = recipeRequirement.DisplayName + "  " + Loc.Tf("hbp_amount", recipeRequirement.Amount);
				if (recipeRequirement.AmountPerLevel > 0)
				{
					text2 = text2 + "  " + Loc.Tf("hbp_per_level", recipeRequirement.AmountPerLevel);
				}
				GUILayout.Label(text2, _bodyStyle, Array.Empty<GUILayoutOption>());
				GUILayout.EndHorizontal();
			}
		}

		private void RefreshFilter(bool resetSelection)
		{
			string text = null;
			if (!resetSelection && _selected >= 0 && _selected < _filtered.Count)
			{
				text = _filtered[_selected].PrefabName;
			}
			_filtered = RecipeCatalog.Query(_search, _stationKey, _typeFilter, _sort);
			if (text != null)
			{
				_selected = -1;
				for (int i = 0; i < _filtered.Count; i++)
				{
					if (_filtered[i].PrefabName == text)
					{
						_selected = i;
						break;
					}
				}
				if (_selected < 0 && _filtered.Count > 0)
				{
					_selected = 0;
				}
			}
			else
			{
				_selected = ((_filtered.Count <= 0) ? (-1) : 0);
			}
		}

		private void EnsureStyles()
		{
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0042: Unknown result type (might be due to invalid IL or missing references)
			//IL_0066: Unknown result type (might be due to invalid IL or missing references)
			//IL_0080: Unknown result type (might be due to invalid IL or missing references)
			//IL_0085: Unknown result type (might be due to invalid IL or missing references)
			//IL_009b: Expected O, but got Unknown
			//IL_00a6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ab: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ba: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cf: Unknown result type (might be due to invalid IL or missing references)
			//IL_00de: Expected O, but got Unknown
			//IL_00e9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ee: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f6: 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_0112: Unknown result type (might be due to invalid IL or missing references)
			//IL_011c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0128: Expected O, but got Unknown
			//IL_0133: Unknown result type (might be due to invalid IL or missing references)
			//IL_0138: Unknown result type (might be due to invalid IL or missing references)
			//IL_0140: Unknown result type (might be due to invalid IL or missing references)
			//IL_0147: Unknown result type (might be due to invalid IL or missing references)
			//IL_0158: 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)
			//IL_0177: Unknown result type (might be due to invalid IL or missing references)
			//IL_017c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0186: Expected O, but got Unknown
			//IL_0186: Unknown result type (might be due to invalid IL or missing references)
			//IL_0192: Expected O, but got Unknown
			//IL_019d: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01aa: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b1: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c6: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d5: Expected O, but got Unknown
			//IL_01e0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e5: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ec: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f4: Unknown result type (might be due to invalid IL or missing references)
			//IL_0200: Expected O, but got Unknown
			//IL_0207: 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_021d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0223: Unknown result type (might be due to invalid IL or missing references)
			//IL_022d: Unknown result type (might be due to invalid IL or missing references)
			//IL_023e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0244: Unknown result type (might be due to invalid IL or missing references)
			//IL_024e: Unknown result type (might be due to invalid IL or missing references)
			//IL_025f: 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_0274: Expected O, but got Unknown
			if (!_stylesReady)
			{
				_panelTex = MakeTex(new Color(0.18f, 0.14f, 0.1f, 0.98f));
				_activeTex = MakeTex(new Color(0.45f, 0.36f, 0.18f, 1f));
				_groupTex = MakeTex(new Color(0.28f, 0.22f, 0.14f, 1f));
				GUIStyle val = new GUIStyle(GUI.skin.box);
				val.normal.background = _panelTex;
				_boxStyle = val;
				GUIStyle val2 = new GUIStyle(GUI.skin.label)
				{
					fontSize = 22,
					fontStyle = (FontStyle)1
				};
				val2.normal.textColor = new Color(0.95f, 0.88f, 0.65f);
				_titleStyle = val2;
				GUIStyle val3 = new GUIStyle(GUI.skin.label)
				{
					fontSize = 14,
					fontStyle = (FontStyle)1
				};
				val3.normal.textColor = new Color(0.9f, 0.82f, 0.55f);
				val3.wordWrap = true;
				_headerStyle = val3;
				GUIStyle val4 = new GUIStyle(GUI.skin.label)
				{
					fontSize = 13,
					fontStyle = (FontStyle)1
				};
				val4.normal.background = _groupTex;
				val4.normal.textColor = new Color(1f, 0.92f, 0.7f);
				val4.padding = new RectOffset(6, 6, 4, 4);
				val4.wordWrap = true;
				_groupStyle = val4;
				GUIStyle val5 = new GUIStyle(GUI.skin.label)
				{
					fontSize = 13,
					wordWrap = true
				};
				val5.normal.textColor = new Color(0.92f, 0.9f, 0.85f);
				_bodyStyle = val5;
				_sideBtn = new GUIStyle(GUI.skin.button)
				{
					alignment = (TextAnchor)3,
					fontSize = 12,
					wordWrap = true
				};
				GUIStyle val6 = new GUIStyle(_sideBtn);
				val6.normal.background = _activeTex;
				val6.normal.textColor = Color.white;
				val6.hover.background = _activeTex;
				val6.hover.textColor = Color.white;
				val6.active.background = _activeTex;
				val6.active.textColor = Color.white;
				_sideBtnActive = val6;
				_stylesReady = true;
			}
		}

		private static Texture2D MakeTex(Color c)
		{
			//IL_0004: Unknown result type (might be due to invalid IL or missing references)
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: Expected O, but got Unknown
			Texture2D val = new Texture2D(1, 1, (TextureFormat)4, false);
			val.SetPixel(0, 0, c);
			val.Apply();
			return val;
		}

		private static void DrawSprite(Sprite sprite, float size)
		{
			//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_0090: Unknown result type (might be due to invalid IL or missing references)
			//IL_009b: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)sprite == (Object)null) && !((Object)(object)sprite.texture == (Object)null))
			{
				Rect textureRect = sprite.textureRect;
				Rect val = default(Rect);
				((Rect)(ref val))..ctor(((Rect)(ref textureRect)).x / (float)((Texture)sprite.texture).width, ((Rect)(ref textureRect)).y / (float)((Texture)sprite.texture).height, ((Rect)(ref textureRect)).width / (float)((Texture)sprite.texture).width, ((Rect)(ref textureRect)).height / (float)((Texture)sprite.texture).height);
				GUI.DrawTextureWithTexCoords(GUILayoutUtility.GetRect(size, size, (GUILayoutOption[])(object)new GUILayoutOption[2]
				{
					GUILayout.Width(size),
					GUILayout.Height(size)
				}), (Texture)(object)sprite.texture, val);
			}
		}
	}
}
namespace HelpBookPlus.Patches
{
	[HarmonyPatch(typeof(Menu), "Show")]
	internal static class MenuShowPatch
	{
		private static void Postfix(Menu __instance)
		{
			HelpBookMenuButton.UpdateVisibility(__instance);
		}
	}
	[HarmonyPatch(typeof(Menu), "SetButtonsEnabled")]
	internal static class MenuSetButtonsPatch
	{
		private static void Postfix(Menu __instance)
		{
			HelpBookMenuButton.UpdateVisibility(__instance);
		}
	}
	[HarmonyPatch(typeof(Menu), "OnDestroy")]
	internal static class MenuOnDestroyPatch
	{
		private static void Postfix()
		{
			HelpBookMenuButton.Reset();
		}
	}
	[HarmonyPatch]
	internal static class MouseCapturePatch
	{
		[HarmonyPrefix]
		[HarmonyPatch(typeof(GameCamera), "UpdateMouseCapture")]
		private static bool UpdateMouseCapturePrefix()
		{
			if (!HelpBookWindow.IsOpen)
			{
				return true;
			}
			Cursor.lockState = (CursorLockMode)0;
			Cursor.visible = true;
			return false;
		}

		[HarmonyPrefix]
		[HarmonyPatch(typeof(GameCamera), "UpdateCamera")]
		private static bool UpdateCameraPrefix()
		{
			return !HelpBookWindow.IsOpen;
		}
	}
	[HarmonyPatch]
	internal static class PlayerInputBlockPatch
	{
		[HarmonyPrefix]
		[HarmonyPatch(typeof(Player), "TakeInput")]
		private static bool PlayerTakeInputPrefix(ref bool __result)
		{
			if (!HelpBookWindow.IsOpen)
			{
				return true;
			}
			__result = false;
			return false;
		}

		[HarmonyPrefix]
		[HarmonyPatch(typeof(PlayerController), "TakeInput")]
		private static bool ControllerTakeInputPrefix(ref bool __result)
		{
			if (!HelpBookWindow.IsOpen)
			{
				return true;
			}
			__result = false;
			return false;
		}

		[HarmonyPostfix]
		[HarmonyPatch(typeof(PlayerController), "InInventoryEtc")]
		private static void InInventoryEtcPostfix(ref bool __result)
		{
			if (HelpBookWindow.IsOpen)
			{
				__result = true;
			}
		}
	}
}
namespace HelpBookPlus.Localization
{
	internal static class Loc
	{
		private static readonly Dictionary<string, Dictionary<string, string>> Tables = new Dictionary<string, Dictionary<string, string>>(StringComparer.OrdinalIgnoreCase);

		private static string _activeCode = "en";

		private static string LangDir => Path.Combine(Paths.ConfigPath, "HelpBookPlus", "lang");

		internal static void Init()
		{
			EnsureLangFolder();
			LoadEmbedded("en");
			LoadEmbedded("pt");
			LoadDiskOverrides();
			ApplyLanguagePreference();
			Plugin.Log.LogInfo((object)("Localization ready (active=" + _activeCode + ", files in " + LangDir + ")"));
		}

		internal static string T(string key)
		{
			if (string.IsNullOrEmpty(key))
			{
				return key;
			}
			if (Tables.TryGetValue(_activeCode, out var value) && value.TryGetValue(key, out var value2))
			{
				return value2;
			}
			if (Tables.TryGetValue("en", out var value3) && value3.TryGetValue(key, out value2))
			{
				return value2;
			}
			return key;
		}

		internal static string Tf(string key, params object[] args)
		{
			try
			{
				return string.Format(T(key), args);
			}
			catch (FormatException)
			{
				return T(key);
			}
		}

		private static void EnsureLangFolder()
		{
			Directory.CreateDirectory(LangDir);
			WriteEmbedded("en");
			WriteEmbedded("pt");
		}

		private static void WriteEmbedded(string code)
		{
			string path = Path.Combine(LangDir, code + ".json");
			string text = ReadEmbedded(code);
			if (!string.IsNullOrEmpty(text))
			{
				File.WriteAllText(path, text, Encoding.UTF8);
			}
		}

		private static void LoadEmbedded(string code)
		{
			string text = ReadEmbedded(code);
			if (!string.IsNullOrEmpty(text))
			{
				Tables[code] = ParseFlatJson(text);
			}
		}

		private static void LoadDiskOverrides()
		{
			if (!Directory.Exists(LangDir))
			{
				return;
			}
			string[] files = Directory.GetFiles(LangDir, "*.json");
			foreach (string text in files)
			{
				string fileNameWithoutExtension = Path.GetFileNameWithoutExtension(text);
				try
				{
					Dictionary<string, string> dictionary = ParseFlatJson(File.ReadAllText(text, Encoding.UTF8));
					if (dictionary.Count == 0)
					{
						continue;
					}
					if (!Tables.TryGetValue(fileNameWithoutExtension, out var value))
					{
						Tables[fileNameWithoutExtension] = dictionary;
						continue;
					}
					foreach (KeyValuePair<string, string> item in dictionary)
					{
						value[item.Key] = item.Value;
					}
				}
				catch (Exception ex)
				{
					Plugin.Log.LogWarning((object)("Failed to load lang file " + text + ": " + ex.Message));
				}
			}
		}

		private static string ReadEmbedded(string code)
		{
			string text = "HelpBookPlus.Languages." + code + ".json";
			using Stream stream = Assembly.GetExecutingAssembly().GetManifestResourceStream(text);
			if (stream == null)
			{
				Plugin.Log.LogWarning((object)("Missing embedded language resource: " + text));
				return null;
			}
			using StreamReader streamReader = new StreamReader(stream, Encoding.UTF8);
			return streamReader.ReadToEnd();
		}

		internal static void ApplyLanguagePreference()
		{
			string a = ModConfig.Language?.Value ?? "Auto";
			if (string.Equals(a, "Portuguese", StringComparison.OrdinalIgnoreCase) || string.Equals(a, "pt", StringComparison.OrdinalIgnoreCase) || string.Equals(a, "pt-BR", StringComparison.OrdinalIgnoreCase))
			{
				_activeCode = (Tables.ContainsKey("pt") ? "pt" : "en");
				return;
			}
			if (string.Equals(a, "English", StringComparison.OrdinalIgnoreCase) || string.Equals(a, "en", StringComparison.OrdinalIgnoreCase))
			{
				_activeCode = "en";
				return;
			}
			try
			{
				string text = ((Localization.instance != null) ? Localization.instance.GetSelectedLanguage() : null);
				if (!string.IsNullOrEmpty(text) && (text.IndexOf("Portuguese", StringComparison.OrdinalIgnoreCase) >= 0 || text.StartsWith("pt", StringComparison.OrdinalIgnoreCase) || text.IndexOf("Brazil", StringComparison.OrdinalIgnoreCase) >= 0))
				{
					_activeCode = (Tables.ContainsKey("pt") ? "pt" : "en");
					return;
				}
			}
			catch
			{
			}
			_activeCode = "en";
		}

		internal static Dictionary<string, string> ParseFlatJson(string json)
		{
			Dictionary<string, string> dictionary = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
			if (string.IsNullOrWhiteSpace(json))
			{
				return dictionary;
			}
			int i = 0;
			SkipWs(json, ref i);
			if (i >= json.Length || json[i] != '{')
			{
				return dictionary;
			}
			i++;
			while (i < json.Length)
			{
				SkipWs(json, ref i);
				if (i < json.Length && json[i] == '}')
				{
					break;
				}
				if (i < json.Length && json[i] == ',')
				{
					i++;
					continue;
				}
				if (!TryReadString(json, ref i, out var value))
				{
					break;
				}
				SkipWs(json, ref i);
				if (i >= json.Length || json[i] != ':')
				{
					break;
				}
				i++;
				SkipWs(json, ref i);
				if (!TryReadString(json, ref i, out var value2))
				{
					break;
				}
				dictionary[value] = value2;
			}
			return dictionary;
		}

		private static void SkipWs(string s, ref int i)
		{
			while (i < s.Length && char.IsWhiteSpace(s[i]))
			{
				i++;
			}
		}

		private static bool TryReadString(string s, ref int i, out string value)
		{
			value = null;
			SkipWs(s, ref i);
			if (i >= s.Length || s[i] != '"')
			{
				return false;
			}
			i++;
			StringBuilder stringBuilder = new StringBuilder();
			while (i < s.Length)
			{
				char c = s[i++];
				switch (c)
				{
				case '"':
					value = stringBuilder.ToString();
					return true;
				case '\\':
					if (i < s.Length)
					{
						char c2 = s[i++];
						StringBuilder stringBuilder2 = stringBuilder;
						stringBuilder2.Append(c2 switch
						{
							'n' => '\n', 
							'r' => '\r', 
							't' => '\t', 
							'"' => '"', 
							'\\' => '\\', 
							_ => c2, 
						});
						continue;
					}
					break;
				}
				stringBuilder.Append(c);
			}
			return false;
		}
	}
}
namespace HelpBookPlus.Input
{
	internal sealed class BookInputListener : MonoBehaviour
	{
		private void Update()
		{
			//IL_004b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0058: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			if (!ModConfig.Enabled.Value)
			{
				return;
			}
			if (HelpBookWindow.IsOpen)
			{
				if (Input.GetKeyDown((KeyCode)27))
				{
					HelpBookWindow.Close();
				}
				else if ((int)ModConfig.OpenKey.Value != 0 && Input.GetKeyDown(ModConfig.OpenKey.Value))
				{
					HelpBookWindow.Close();
				}
			}
			else if ((int)ModConfig.OpenKey.Value != 0 && Input.GetKeyDown(ModConfig.OpenKey.Value) && !ShouldIgnoreKey())
			{
				HelpBookWindow.Open();
			}
		}

		private static bool ShouldIgnoreKey()
		{
			if (Console.IsVisible())
			{
				return true;
			}
			try
			{
				if ((Object)(object)Chat.instance != (Object)null && Chat.instance.HasFocus())
				{
					return true;
				}
			}
			catch
			{
			}
			if (TextInput.IsVisible())
			{
				return true;
			}
			if ((Object)(object)Player.m_localPlayer == (Object)null)
			{
				return true;
			}
			return false;
		}
	}
}
namespace HelpBookPlus.Data
{
	internal static class RecipeCatalog
	{
		private static readonly List<RecipeEntry> All = new List<RecipeEntry>();

		private static readonly List<StationOption> Stations = new List<StationOption>();

		private static int _lastRecipeCount = -1;

		internal static IReadOnlyList<RecipeEntry> Entries => All;

		internal static IReadOnlyList<StationOption> StationOptions => Stations;

		internal static void EnsureBuilt(bool force = false)
		{
			ObjectDB instance = ObjectDB.instance;
			if (!((Object)(object)instance == (Object)null) && instance.m_recipes != null)
			{
				int count = instance.m_recipes.Count;
				if (force || count != _lastRecipeCount || All.Count <= 0)
				{
					Rebuild(instance);
				}
			}
		}

		internal static void Invalidate()
		{
			_lastRecipeCount = -1;
			All.Clear();
			Stations.Clear();
		}

		internal static List<RecipeEntry> Query(string search, string stationKey, RecipeTypeFilter typeFilter, RecipeSortMode sort)
		{
			EnsureBuilt();
			List<RecipeEntry> list = new List<RecipeEntry>();
			if (All.Count == 0)
			{
				return list;
			}
			string text = (string.IsNullOrWhiteSpace(search) ? null : search.Trim());
			bool flag = stationKey != null;
			for (int i = 0; i < All.Count; i++)
			{
				RecipeEntry recipeEntry = All[i];
				if ((!flag || string.Equals(recipeEntry.StationKey ?? string.Empty, stationKey, StringComparison.Ordinal)) && (typeFilter != RecipeTypeFilter.Craftable || !recipeEntry.UpgradeOnly) && (typeFilter != RecipeTypeFilter.UpgradeOnly || recipeEntry.UpgradeOnly) && (text == null || recipeEntry.SearchBlob.IndexOf(text, StringComparison.OrdinalIgnoreCase) >= 0))
				{
					list.Add(recipeEntry);
				}
			}
			switch (sort)
			{
			case RecipeSortMode.NameDesc:
				list.Sort((RecipeEntry a, RecipeEntry b) => string.Compare(b.DisplayName, a.DisplayName, StringComparison.OrdinalIgnoreCase));
				break;
			case RecipeSortMode.Station:
				list.Sort(delegate(RecipeEntry a, RecipeEntry b)
				{
					int num = string.Compare(a.StationName, b.StationName, StringComparison.OrdinalIgnoreCase);
					return (num == 0) ? string.Compare(a.DisplayName, b.DisplayName, StringComparison.OrdinalIgnoreCase) : num;
				});
				break;
			case RecipeSortMode.StationLevel:
				list.Sort(delegate(RecipeEntry a, RecipeEntry b)
				{
					int num = a.StationLevel.CompareTo(b.StationLevel);
					if (num != 0)
					{
						return num;
					}
					num = string.Compare(a.StationName, b.StationName, StringComparison.OrdinalIgnoreCase);
					return (num == 0) ? string.Compare(a.DisplayName, b.DisplayName, StringComparison.OrdinalIgnoreCase) : num;
				});
				break;
			default:
				list.Sort((RecipeEntry a, RecipeEntry b) => string.Compare(a.DisplayName, b.DisplayName, StringComparison.OrdinalIgnoreCase));
				break;
			}
			return list;
		}

		private static void Rebuild(ObjectDB db)
		{
			All.Clear();
			Stations.Clear();
			Dictionary<string, StationOption> dictionary = new Dictionary<string, StationOption>(StringComparer.Ordinal);
			List<Recipe> recipes = db.m_recipes;
			for (int i = 0; i < recipes.Count; i++)
			{
				Recipe val = recipes[i];
				if ((Object)(object)val == (Object)null || !val.m_enabled || (Object)(object)val.m_item == (Object)null)
				{
					continue;
				}
				ItemDrop item = val.m_item;
				SharedData val2 = item.m_itemData?.m_shared;
				if (val2 == null)
				{
					continue;
				}
				string name = ((Object)item).name;
				string text = GameLocalize(val2.m_name);
				if (string.IsNullOrEmpty(text))
				{
					text = name;
				}
				string text2 = string.Empty;
				string text3 = Loc.T("hbp_station_none");
				if ((Object)(object)val.m_craftingStation != (Object)null)
				{
					text2 = ((Object)val.m_craftingStation).name ?? string.Empty;
					string name2 = val.m_craftingStation.m_name;
					text3 = (string.IsNullOrEmpty(name2) ? text2 : GameLocalize(name2));
				}
				if (!dictionary.TryGetValue(text2, out var value))
				{
					value = (dictionary[text2] = new StationOption
					{
						Key = text2,
						DisplayName = text3,
						Count = 0
					});
				}
				value.Count++;
				List<RecipeRequirement> list = new List<RecipeRequirement>();
				if (val.m_resources != null)
				{
					for (int j = 0; j < val.m_resources.Length; j++)
					{
						Requirement val3 = val.m_resources[j];
						if (val3 != null && !((Object)(object)val3.m_resItem == (Object)null))
						{
							SharedData val4 = val3.m_resItem.m_itemData?.m_shared;
							string text4 = ((val4 != null) ? GameLocalize(val4.m_name) : ((Object)val3.m_resItem).name);
							list.Add(new RecipeRequirement
							{
								PrefabName = ((Object)val3.m_resItem).name,
								DisplayName = (string.IsNullOrEmpty(text4) ? ((Object)val3.m_resItem).name : text4),
								Amount = val3.m_amount,
								AmountPerLevel = val3.m_amountPerLevel,
								Icon = FirstIcon(val4)
							});
						}
					}
				}
				RecipeEntry recipeEntry = new RecipeEntry
				{
					PrefabName = name,
					DisplayName = text,
					Amount = Mathf.Max(1, val.m_amount),
					StationKey = text2,
					StationName = text3,
					StationLevel = val.m_minStationLevel,
					UpgradeOnly = val.m_noCraftOnlyUpgrade,
					Icon = FirstIcon(val2),
					Requirements = list.ToArray()
				};
				recipeEntry.SearchBlob = BuildSearchBlob(recipeEntry);
				All.Add(recipeEntry);
			}
			Stations.AddRange(dictionary.Values);
			Stations.Sort(delegate(StationOption a, StationOption b)
			{
				bool flag = string.IsNullOrEmpty(a.Key);
				bool flag2 = string.IsNullOrEmpty(b.Key);
				return (flag != flag2) ? ((!flag) ? 1 : (-1)) : string.Compare(a.DisplayName, b.DisplayName, StringComparison.OrdinalIgnoreCase);
			});
			All.Sort((RecipeEntry a, RecipeEntry b) => string.Compare(a.DisplayName, b.DisplayName, StringComparison.OrdinalIgnoreCase));
			_lastRecipeCount = recipes.Count;
			Plugin.Log.LogInfo((object)$"Recipe catalog rebuilt: {All.Count} entries, {Stations.Count} stations.");
		}

		private static string BuildSearchBlob(RecipeEntry e)
		{
			StringBuilder stringBuilder = new StringBuilder();
			stringBuilder.Append(e.DisplayName).Append(' ').Append(e.PrefabName)
				.Append(' ')
				.Append(e.StationName);
			if (e.Requirements != null)
			{
				for (int i = 0; i < e.Requirements.Length; i++)
				{
					RecipeRequirement recipeRequirement = e.Requirements[i];
					stringBuilder.Append(' ').Append(recipeRequirement.DisplayName).Append(' ')
						.Append(recipeRequirement.PrefabName);
				}
			}
			return stringBuilder.ToString();
		}

		private static string GameLocalize(string token)
		{
			if (string.IsNullOrEmpty(token))
			{
				return string.Empty;
			}
			try
			{
				if (Localization.instance != null)
				{
					return Localization.instance.Localize(token);
				}
			}
			catch
			{
			}
			return token;
		}

		private static Sprite FirstIcon(SharedData shared)
		{
			if (shared?.m_icons == null || shared.m_icons.Length == 0)
			{
				return null;
			}
			return shared.m_icons[0];
		}
	}
	internal sealed class RecipeRequirement
	{
		internal string PrefabName;

		internal string DisplayName;

		internal int Amount;

		internal int AmountPerLevel;

		internal Sprite Icon;
	}
	internal sealed class RecipeEntry
	{
		internal string PrefabName;

		internal string DisplayName;

		internal string SearchBlob;

		internal int Amount;

		internal string StationKey;

		internal string StationName;

		internal int StationLevel;

		internal bool UpgradeOnly;

		internal Sprite Icon;

		internal RecipeRequirement[] Requirements;
	}
	internal enum RecipeSortMode
	{
		NameAsc,
		NameDesc,
		Station,
		StationLevel
	}
	internal enum RecipeTypeFilter
	{
		All,
		Craftable,
		UpgradeOnly
	}
	internal sealed class StationOption
	{
		internal string Key;

		internal string DisplayName;

		internal int Count;
	}
}
namespace HelpBookPlus.ConsoleCmds
{
	[HarmonyPatch]
	internal static class HelpBookCommand
	{
		[Serializable]
		[CompilerGenerated]
		private sealed class <>c
		{
			public static readonly <>c <>9 = new <>c();

			public static ConsoleEventFailable <>9__2_0;

			internal object <Register>b__2_0(ConsoleEventArgs _)
			{
				HelpBookWindow.Toggle();
				return true;
			}
		}

		private static bool _registered;

		[HarmonyPostfix]
		[HarmonyPatch(typeof(Terminal), "InitTerminal")]
		private static void InitTerminalPostfix()
		{
			if (!_registered)
			{
				_registered = true;
				Register("helpbookplus", "Toggle HelpBookPlus recipe book");
				Register("hbp", "Alias for helpbookplus");
				Plugin.Log.LogInfo((object)"Console commands registered: helpbookplus, hbp");
			}
		}

		private static void Register(string name, string description)
		{
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Expected O, but got Unknown
			object obj = <>c.<>9__2_0;
			if (obj == null)
			{
				ConsoleEventFailable val = delegate
				{
					HelpBookWindow.Toggle();
					return true;
				};
				<>c.<>9__2_0 = val;
				obj = (object)val;
			}
			new ConsoleCommand(name, description, (ConsoleEventFailable)obj, false, false, false, false, true, false, (ConsoleOptionsFetcher)null, false, false, false);
		}
	}
}
namespace System.Runtime.CompilerServices
{
	[AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)]
	internal sealed class IgnoresAccessChecksToAttribute : Attribute
	{
		public IgnoresAccessChecksToAttribute(string assemblyName)
		{
		}
	}
}