Please disclose if any significant portion of your mod was created using AI tools by adding the 'AI Generated' category. Failing to do so may result in the mod being removed from Thunderstore.
Decompiled source of HelpBookPlus v1.0.5
plugins\HelpBookPlus.dll
Decompiled a week agousing 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) { } } }