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 TabSecret v0.1.0
TabSecret.dll
Decompiled a day ago
The result has been truncated due to the large size, download it to view full contents!
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