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 RamCraftFilterModLabels v0.3.21
RamCraftFilterModLabels.dll
Decompiled a week agousing System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Reflection; using System.Runtime.CompilerServices; using System.Text; using System.Text.RegularExpressions; using BepInEx; using BepInEx.Configuration; using HarmonyLib; using Jotunn.Utils; using TMPro; using UnityEngine; using UnityEngine.Events; using UnityEngine.UI; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: AssemblyVersion("0.0.0.0")] namespace JustinRampage.ModOrigin; [BepInPlugin("justinrampage.modorigin", "RamCraftFilterModLabels", "0.3.21")] [BepInDependency(/*Could not decode attribute arguments.*/)] public sealed class ModOriginPlugin : BaseUnityPlugin { [Serializable] [CompilerGenerated] private sealed class <>c { public static readonly <>c <>9 = new <>c(); public static UnityAction <>9__50_0; public static UnityAction <>9__50_1; internal void <CreateControl>b__50_0() { OpenPopup(showSources: true); } internal void <CreateControl>b__50_1() { OpenPopup(showSources: false); } } public const string PluginGuid = "justinrampage.modorigin"; private Harmony harmony; private static ConfigEntry<bool> previewNew; private static Player discoveryOwner; private static string persistenceFile; private static readonly HashSet<string> NewlyDiscoveredNames = new HashSet<string>(StringComparer.Ordinal); private static readonly HashSet<string> PreviewDismissedNames = new HashSet<string>(StringComparer.Ordinal); private static readonly HashSet<string> PreviewTargetNames = new HashSet<string>(StringComparer.Ordinal); private static string activeViewedRecipeKey; private static RecipeRowNewMarker activeViewedRecipeRow; private static readonly HashSet<string> KeepAtTopUntilMenuClose = new HashSet<string>(StringComparer.Ordinal); internal static ModOriginPlugin Instance; internal static string Selection = "All"; internal static string TypeSelection = "All"; internal static readonly List<string> AvailableSources = new List<string>(); internal static readonly List<string> AvailableTypes = new List<string>(); internal static bool UiReady; private static readonly HashSet<string> VanillaItemNames = new HashSet<string>(StringComparer.Ordinal); private static GameObject sourceControl; private static GameObject typeControl; private static GameObject overlayRoot; private static RectTransform adjustedViewport; private static Vector2 originalOffsetMax; private static TextMeshProUGUI sourceLabel; private static TextMeshProUGUI typeLabel; private static InventoryGui gui; private static int padFilterFocus = -1; private static bool padPopupOpen; private static int padOptionIndex; private static readonly List<string> padOptionChoices = new List<string>(); private static readonly List<Image> padOptionBackgrounds = new List<Image>(); private static MethodInfo zPadDown; private static MethodInfo zPadActive; private static MethodInfo zPadReset; private static bool padInputResolved; private static bool padWarningLogged; private static bool benchStartFilterPending; private static bool suppressAutomaticRecipeViewing; private static Button guardedStyleButton; private static bool styleWasInteractable; private static bool localizationSearched; private static MethodInfo localizationLocalize; private static FieldInfo localizationInstanceField; private static PropertyInfo localizationInstanceProperty; private const string TmpNewPrefix = "<color=#39FF14><b>*</b></color> "; private const string LegacyNewPrefix = "<color=#39FF14><b>*</b></color> "; private const string PriorSmallStarPrefix = "<color=#A3CE3C><size=85%><b>*</b></size></color> "; private const string PriorStarPrefix = "<color=#A3CE3C><b>*</b></color> "; private const string PriorTmpNewPrefix = "<color=#A3CE3C><size=75%><b>NEW</b></size></color> "; private const string PriorLegacyNewPrefix = "<color=#A3CE3C><b>NEW</b></color> "; private void Awake() { //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Expected O, but got Unknown Instance = this; ModQuery.Enable(); previewNew = ((BaseUnityPlugin)this).Config.Bind<bool>("Testing", "PreviewNewMarkers", false, "Temporary visual test: show a green * on the first three available crafting recipes. Does not unlock recipes or change character progression. Disable after testing."); harmony = new Harmony("justinrampage.modorigin"); harmony.PatchAll(typeof(ModOriginPlugin).Assembly); ((BaseUnityPlugin)this).Logger.LogInfo((object)"RamCraftFilterModLabels 0.3.21 loaded: TMP font initialization fix; 0.3.20 features preserved."); } private void OnDestroy() { ResetUi(); if (harmony != null) { harmony.UnpatchSelf(); } Instance = null; } internal static void CaptureVanillaItems(ObjectDB source) { if (VanillaItemNames.Count != 0 || (Object)(object)source == (Object)null || source.m_items == null || source.m_items.Count < 100) { return; } foreach (GameObject item in source.m_items) { if ((Object)(object)item != (Object)null && !string.IsNullOrEmpty(((Object)item).name)) { string text = ((Object)item).name; if (text.EndsWith("(Clone)", StringComparison.Ordinal)) { text = text.Substring(0, text.Length - 7); } VanillaItemNames.Add(text); } } if ((Object)(object)Instance != (Object)null) { ((BaseUnityPlugin)Instance).Logger.LogInfo((object)("Captured " + VanillaItemNames.Count + " original item prefab names for Valheim attribution.")); } } public static string SourceForItem(ItemData item) { if (item == null || (Object)(object)item.m_dropPrefab == (Object)null) { return "Unknown"; } return SourceForPrefab(((Object)item.m_dropPrefab).name); } public static string SourceForPrefab(string name) { if (string.IsNullOrEmpty(name)) { return "Unknown"; } if (name.EndsWith("(Clone)", StringComparison.Ordinal)) { name = name.Substring(0, name.Length - 7); } try { IModPrefab prefab = ModQuery.GetPrefab(name); if (prefab != null && prefab.SourceMod != null && !string.IsNullOrEmpty(prefab.SourceMod.Name)) { string name2 = prefab.SourceMod.Name; if (name2.Equals("Valheim", StringComparison.OrdinalIgnoreCase) || name2.Equals("IronGate", StringComparison.OrdinalIgnoreCase) || name2.Equals("Iron Gate", StringComparison.OrdinalIgnoreCase)) { return "Valheim"; } return name2; } } catch (Exception ex) { if ((Object)(object)Instance != (Object)null) { ((BaseUnityPlugin)Instance).Logger.LogDebug((object)("Source lookup: " + ex.Message)); } } if (VanillaItemNames.Contains(name)) { return "Valheim"; } return "Unknown"; } private static string SourceForRecipe(Recipe recipe) { if ((Object)(object)recipe == (Object)null || (Object)(object)recipe.m_item == (Object)null) { return "Unknown"; } return SourceForPrefab(((Object)recipe.m_item).name); } private static string FilterLabel(string choice, bool isSource) { if (!(choice == "All")) { return choice; } if (!isSource) { return "Type (All)"; } return "Source (All)"; } private static bool UiBelongsTo(InventoryGui current) { if (UiReady && (Object)(object)current != (Object)null && (Object)(object)gui == (Object)(object)current && (Object)(object)typeControl != (Object)null && (Object)(object)sourceControl != (Object)null && (Object)(object)overlayRoot != (Object)null) { return (Object)(object)adjustedViewport != (Object)null; } return false; } private static void ReleaseUiFromOldSession(InventoryGui current) { if (UiReady && !UiBelongsTo(current)) { EndCraftingMenuSession(); ResetUi(); if ((Object)(object)Instance != (Object)null) { ((BaseUnityPlugin)Instance).Logger.LogInfo((object)"Crafting UI session changed; rebuilding filters for current character."); } } } internal static void EnsureUi(InventoryGui current) { //IL_0148: Unknown result type (might be due to invalid IL or missing references) //IL_014d: Unknown result type (might be due to invalid IL or missing references) //IL_0154: Unknown result type (might be due to invalid IL or missing references) //IL_015f: 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_0209: Unknown result type (might be due to invalid IL or missing references) //IL_0213: Expected O, but got Unknown //IL_0239: Unknown result type (might be due to invalid IL or missing references) //IL_023e: Unknown result type (might be due to invalid IL or missing references) //IL_023f: Unknown result type (might be due to invalid IL or missing references) //IL_0249: 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_0254: Unknown result type (might be due to invalid IL or missing references) //IL_0255: Unknown result type (might be due to invalid IL or missing references) //IL_025f: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)current == (Object)null) { return; } ReleaseUiFromOldSession(current); if (UiReady) { return; } try { RectTransform value = Traverse.Create((object)current).Field("m_recipeListRoot").GetValue<RectTransform>(); object value2 = Traverse.Create((object)current).Field("m_tabCraft").GetValue(); Component val = (Component)((value2 is Component) ? value2 : null); if ((Object)(object)value == (Object)null || (Object)(object)val == (Object)null || (Object)(object)((Transform)value).parent == (Object)null || (Object)(object)val.transform.parent == (Object)null) { throw new InvalidOperationException("Crafting UI anchors not found"); } Transform parent = ((Transform)value).parent; RectTransform val2 = (RectTransform)(object)((parent is RectTransform) ? parent : null); Transform parent2 = val.transform.parent; RectTransform val3 = (RectTransform)(object)((parent2 is RectTransform) ? parent2 : null); Transform transform = val.transform; RectTransform val4 = (RectTransform)(object)((transform is RectTransform) ? transform : null); if ((Object)(object)val2 == (Object)null || (Object)(object)val3 == (Object)null || (Object)(object)val4 == (Object)null || (Object)(object)val2 == (Object)(object)val3) { throw new InvalidOperationException("Crafting panel structure not supported"); } TMP_Text componentInChildren = ((Component)current).GetComponentInChildren<TMP_Text>(true); if ((Object)(object)componentInChildren == (Object)null || (Object)(object)componentInChildren.font == (Object)null) { throw new InvalidOperationException("Existing Valheim TMP font not found"); } Canvas componentInParent = ((Component)val3).GetComponentInParent<Canvas>(); if ((Object)(object)componentInParent == (Object)null || (Object)(object)componentInParent.rootCanvas == (Object)null) { throw new InvalidOperationException("Root Canvas missing; popup cannot be shown safely"); } gui = current; adjustedViewport = val2; originalOffsetMax = val2.offsetMax; val2.offsetMax = new Vector2(val2.offsetMax.x, val2.offsetMax.y - 29f); typeControl = CreateControl(val3, val2, componentInChildren, FilterLabel(TypeSelection, isSource: false), 0f, isSource: false); sourceControl = CreateControl(val3, val2, componentInChildren, FilterLabel(Selection, isSource: true), 82f, isSource: true); typeLabel = typeControl.GetComponentInChildren<TextMeshProUGUI>(true); sourceLabel = sourceControl.GetComponentInChildren<TextMeshProUGUI>(true); overlayRoot = new GameObject("RamCraftFilterModLabelsOptionsCanvas", new Type[3] { typeof(RectTransform), typeof(Canvas), typeof(GraphicRaycaster) }); overlayRoot.transform.SetParent(((Component)componentInParent.rootCanvas).transform, false); RectTransform val5 = (RectTransform)overlayRoot.transform; val5.anchorMin = Vector2.zero; val5.anchorMax = Vector2.one; val5.offsetMin = Vector2.zero; val5.offsetMax = Vector2.zero; Canvas component = overlayRoot.GetComponent<Canvas>(); component.overrideSorting = true; component.sortingOrder = 15000; overlayRoot.SetActive(false); UiReady = true; if ((Object)(object)Instance != (Object)null) { ((BaseUnityPlugin)Instance).Logger.LogInfo((object)"RamCraftFilterModLabels controls ready; root Canvas dropdown enabled."); } } catch (Exception ex) { ResetUi(); if ((Object)(object)Instance != (Object)null) { ((BaseUnityPlugin)Instance).Logger.LogWarning((object)("Crafting filters unavailable; original recipe list preserved: " + ex)); } } } private static GameObject CreateControl(RectTransform parent, RectTransform viewport, TMP_Text fontSample, string title, float xOffset, bool isSource) { //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_0043: Expected O, but got Unknown //IL_0056: Unknown result type (might be due to invalid IL or missing references) //IL_005b: Unknown result type (might be due to invalid IL or missing references) //IL_005c: Unknown result type (might be due to invalid IL or missing references) //IL_0066: Unknown result type (might be due to invalid IL or missing references) //IL_0067: Unknown result type (might be due to invalid IL or missing references) //IL_0071: 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_007c: 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_00a2: Unknown result type (might be due to invalid IL or missing references) //IL_00a7: Unknown result type (might be due to invalid IL or missing references) //IL_00ac: Unknown result type (might be due to invalid IL or missing references) //IL_00ad: Unknown result type (might be due to invalid IL or missing references) //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) //IL_00c5: Unknown result type (might be due to invalid IL or missing references) //IL_00cc: Unknown result type (might be due to invalid IL or missing references) //IL_00d1: Unknown result type (might be due to invalid IL or missing references) //IL_00e0: Unknown result type (might be due to invalid IL or missing references) //IL_0104: Unknown result type (might be due to invalid IL or missing references) //IL_0162: 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_016d: Expected O, but got Unknown //IL_0131: Unknown result type (might be due to invalid IL or missing references) //IL_0136: Unknown result type (might be due to invalid IL or missing references) //IL_013c: Expected O, but got Unknown GameObject val = new GameObject(isSource ? "RamSourceFilter" : "RamItemTypeFilter", new Type[3] { typeof(RectTransform), typeof(Image), typeof(Button) }); val.transform.SetParent((Transform)(object)parent, false); RectTransform val2 = (RectTransform)val.transform; val2.anchorMin = Vector2.zero; val2.anchorMax = Vector2.zero; val2.pivot = Vector2.zero; val2.sizeDelta = new Vector2(81f, 24f); Vector3[] array = (Vector3[])(object)new Vector3[4]; viewport.GetWorldCorners(array); Vector3 val3 = ((Transform)parent).InverseTransformPoint(array[1]); float x = val3.x; Rect rect = parent.rect; float num = x - ((Rect)(ref rect)).xMin + xOffset; float y = val3.y; rect = parent.rect; val2.anchoredPosition = new Vector2(num, y - ((Rect)(ref rect)).yMin + 2f); ((Graphic)val.GetComponent<Image>()).color = new Color(0.12f, 0.1f, 0.08f, 0.96f); if (isSource) { ButtonClickedEvent onClick = val.GetComponent<Button>().onClick; object obj = <>c.<>9__50_0; if (obj == null) { UnityAction val4 = delegate { OpenPopup(showSources: true); }; <>c.<>9__50_0 = val4; obj = (object)val4; } ((UnityEvent)onClick).AddListener((UnityAction)obj); } else { ButtonClickedEvent onClick2 = val.GetComponent<Button>().onClick; object obj2 = <>c.<>9__50_1; if (obj2 == null) { UnityAction val5 = delegate { OpenPopup(showSources: false); }; <>c.<>9__50_1 = val5; obj2 = (object)val5; } ((UnityEvent)onClick2).AddListener((UnityAction)obj2); } CreateLabel(val.transform, fontSample, title); return val; } private static TextMeshProUGUI CreateLabel(Transform parent, TMP_Text fontSample, string value) { //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Expected O, but got Unknown //IL_0038: 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_003e: 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_0049: Unknown result type (might be due to invalid IL or missing references) //IL_0053: Unknown result type (might be due to invalid IL or missing references) //IL_005e: 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_00c6: Unknown result type (might be due to invalid IL or missing references) GameObject val = new GameObject("Text", new Type[1] { typeof(RectTransform) }); val.SetActive(false); val.transform.SetParent(parent, false); RectTransform val2 = (RectTransform)val.transform; val2.anchorMin = Vector2.zero; val2.anchorMax = Vector2.one; val2.offsetMin = new Vector2(3f, 0f); val2.offsetMax = new Vector2(-2f, 0f); TextMeshProUGUI obj = val.AddComponent<TextMeshProUGUI>(); ((TMP_Text)obj).font = fontSample.font; ((TMP_Text)obj).fontSize = 13f; ((TMP_Text)obj).enableAutoSizing = true; ((TMP_Text)obj).fontSizeMin = 10f; ((TMP_Text)obj).fontSizeMax = 13f; ((Graphic)obj).color = new Color(0.94f, 0.77f, 0.41f); ((TMP_Text)obj).alignment = (TextAlignmentOptions)4097; ((TMP_Text)obj).overflowMode = (TextOverflowModes)1; ((Graphic)obj).raycastTarget = false; ((TMP_Text)obj).text = value; val.SetActive(true); return obj; } private static void ClosePopup() { //IL_004a: Unknown result type (might be due to invalid IL or missing references) padPopupOpen = false; padOptionChoices.Clear(); padOptionBackgrounds.Clear(); if (!((Object)(object)overlayRoot != (Object)null)) { return; } overlayRoot.SetActive(false); foreach (Transform item in overlayRoot.transform) { Object.Destroy((Object)(object)((Component)item).gameObject); } } private static void OpenPopup(bool showSources) { //IL_0091: Unknown result type (might be due to invalid IL or missing references) //IL_0097: Expected O, but got Unknown //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_0108: 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_0113: 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_011e: Unknown result type (might be due to invalid IL or missing references) //IL_011f: 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_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_013e: Unknown result type (might be due to invalid IL or missing references) //IL_0158: Unknown result type (might be due to invalid IL or missing references) //IL_0173: Unknown result type (might be due to invalid IL or missing references) //IL_017d: Expected O, but got Unknown //IL_01a2: Unknown result type (might be due to invalid IL or missing references) //IL_01a9: Expected O, but got Unknown //IL_01c7: Unknown result type (might be due to invalid IL or missing references) //IL_01ce: Expected O, but got Unknown //IL_01d0: Unknown result type (might be due to invalid IL or missing references) //IL_01dc: Unknown result type (might be due to invalid IL or missing references) //IL_01f2: Unknown result type (might be due to invalid IL or missing references) //IL_0215: Unknown result type (might be due to invalid IL or missing references) //IL_021a: Unknown result type (might be due to invalid IL or missing references) //IL_0240: 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_0291: Unknown result type (might be due to invalid IL or missing references) //IL_029e: Unknown result type (might be due to invalid IL or missing references) //IL_02b5: Unknown result type (might be due to invalid IL or missing references) //IL_02ba: Unknown result type (might be due to invalid IL or missing references) //IL_02bf: Unknown result type (might be due to invalid IL or missing references) //IL_02c2: Unknown result type (might be due to invalid IL or missing references) //IL_02d5: Unknown result type (might be due to invalid IL or missing references) //IL_02dd: Unknown result type (might be due to invalid IL or missing references) //IL_02e2: Unknown result type (might be due to invalid IL or missing references) //IL_02f7: Unknown result type (might be due to invalid IL or missing references) //IL_02fc: Unknown result type (might be due to invalid IL or missing references) //IL_0307: Unknown result type (might be due to invalid IL or missing references) //IL_0322: Unknown result type (might be due to invalid IL or missing references) //IL_032a: Unknown result type (might be due to invalid IL or missing references) //IL_032f: Unknown result type (might be due to invalid IL or missing references) //IL_0339: Unknown result type (might be due to invalid IL or missing references) //IL_03c1: Unknown result type (might be due to invalid IL or missing references) //IL_03c8: Expected O, but got Unknown //IL_03e3: Unknown result type (might be due to invalid IL or missing references) //IL_03e8: Unknown result type (might be due to invalid IL or missing references) //IL_03f3: Unknown result type (might be due to invalid IL or missing references) //IL_03fd: Unknown result type (might be due to invalid IL or missing references) //IL_0408: Unknown result type (might be due to invalid IL or missing references) //IL_0412: Unknown result type (might be due to invalid IL or missing references) //IL_041d: Unknown result type (might be due to invalid IL or missing references) //IL_0427: Unknown result type (might be due to invalid IL or missing references) //IL_0432: Unknown result type (might be due to invalid IL or missing references) //IL_044a: Unknown result type (might be due to invalid IL or missing references) //IL_049f: Unknown result type (might be due to invalid IL or missing references) //IL_0484: Unknown result type (might be due to invalid IL or missing references) //IL_04fd: Unknown result type (might be due to invalid IL or missing references) //IL_0507: Expected O, but got Unknown //IL_04dd: Unknown result type (might be due to invalid IL or missing references) //IL_04e7: Expected O, but got Unknown if (!UiReady || (Object)(object)overlayRoot == (Object)null) { return; } if (overlayRoot.activeSelf) { ClosePopup(); return; } GameObject val = typeControl; List<string> list = new List<string>(showSources ? AvailableSources : AvailableTypes); if (!list.Contains("All")) { list.Insert(0, "All"); } if ((Object)(object)val == (Object)null || (Object)(object)(showSources ? sourceControl : typeControl) == (Object)null) { return; } overlayRoot.SetActive(true); RectTransform val2 = (RectTransform)overlayRoot.transform; Canvas component = ((Component)overlayRoot.transform.parent).GetComponent<Canvas>(); if ((Object)(object)component == (Object)null) { ClosePopup(); return; } GameObject val3 = new GameObject("OutsideClick", new Type[3] { typeof(RectTransform), typeof(Image), typeof(Button) }); val3.transform.SetParent(overlayRoot.transform, false); RectTransform val4 = (RectTransform)val3.transform; val4.anchorMin = Vector2.zero; val4.anchorMax = Vector2.one; val4.offsetMin = Vector2.zero; val4.offsetMax = Vector2.zero; ((Graphic)val3.GetComponent<Image>()).color = new Color(0f, 0f, 0f, 0f); ((UnityEvent)val3.GetComponent<Button>().onClick).AddListener(new UnityAction(ClosePopup)); GameObject val5 = new GameObject("Options", new Type[2] { typeof(RectTransform), typeof(Image) }); val5.transform.SetParent(overlayRoot.transform, false); RectTransform val6 = (RectTransform)val5.transform; val6.anchorMin = Vector2.zero; val6.anchorMax = Vector2.zero; val6.pivot = new Vector2(0f, 1f); float num; Rect rect; if (!((Object)(object)adjustedViewport != (Object)null)) { num = 164f; } else { rect = adjustedViewport.rect; num = ((Rect)(ref rect)).width; } float num2 = num; val6.sizeDelta = new Vector2(Mathf.Max(120f, num2), (float)list.Count * 26f); ((Graphic)val5.GetComponent<Image>()).color = new Color(0.09f, 0.08f, 0.07f, 0.99f); padOptionChoices.Clear(); padOptionBackgrounds.Clear(); Vector3[] array = (Vector3[])(object)new Vector3[4]; ((RectTransform)val.transform).GetWorldCorners(array); Camera val7 = (((int)component.renderMode == 0) ? null : component.worldCamera); Vector2 val8 = RectTransformUtility.WorldToScreenPoint(val7, array[0]); Vector2 val9 = default(Vector2); if (!RectTransformUtility.ScreenPointToLocalPointInRectangle(val2, val8, val7, ref val9)) { ClosePopup(); return; } float x = val9.x; rect = val2.rect; float num3 = x - ((Rect)(ref rect)).xMin; rect = val2.rect; float num4 = Mathf.Clamp(num3, 0f, Mathf.Max(0f, ((Rect)(ref rect)).width - val6.sizeDelta.x)); float y = val9.y; rect = val2.rect; val6.anchoredPosition = new Vector2(num4, y - ((Rect)(ref rect)).yMin); TMP_Text fontSample = (TMP_Text)(object)(showSources ? sourceLabel : typeLabel); string value = (showSources ? Selection : TypeSelection); for (int i = 0; i < list.Count; i++) { string chosen = list[i]; GameObject val10 = new GameObject("Option-" + chosen, new Type[3] { typeof(RectTransform), typeof(Image), typeof(Button) }); val10.transform.SetParent(val5.transform, false); RectTransform val11 = (RectTransform)val10.transform; val11.anchorMin = new Vector2(0f, 1f); val11.anchorMax = new Vector2(1f, 1f); val11.pivot = new Vector2(0.5f, 1f); val11.sizeDelta = new Vector2(0f, 26f); val11.anchoredPosition = new Vector2(0f, -26f * (float)i); Image component2 = val10.GetComponent<Image>(); ((Graphic)component2).color = (chosen.Equals(value, StringComparison.OrdinalIgnoreCase) ? new Color(0.28f, 0.21f, 0.1f, 1f) : new Color(0.15f, 0.13f, 0.11f, 1f)); padOptionChoices.Add(chosen); padOptionBackgrounds.Add(component2); if (showSources) { ((UnityEvent)val10.GetComponent<Button>().onClick).AddListener((UnityAction)delegate { ChooseSource(chosen); }); } else { ((UnityEvent)val10.GetComponent<Button>().onClick).AddListener((UnityAction)delegate { ChooseType(chosen); }); } CreateLabel(val10.transform, fontSample, (chosen == "All") ? (showSources ? "Source (All)" : "Type (All)") : chosen); } val5.transform.SetAsLastSibling(); if (padPopupOpen) { PaintPadOptions(); } } private static void ChooseSource(string choice) { Selection = choice; if ((Object)(object)sourceLabel != (Object)null) { ((TMP_Text)sourceLabel).text = FilterLabel(Selection, isSource: true); } ClosePopup(); RefreshCrafting(); ReturnGamepadRecipeToTopAfterFilterChange(); } private static void ChooseType(string choice) { TypeSelection = choice; if ((Object)(object)typeLabel != (Object)null) { ((TMP_Text)typeLabel).text = FilterLabel(TypeSelection, isSource: false); } ClosePopup(); RefreshCrafting(); ReturnGamepadRecipeToTopAfterFilterChange(); } internal static void ResetFilterSelections() { benchStartFilterPending = false; LeavePadFilterFocus(); TypeSelection = "All"; Selection = "All"; if ((Object)(object)typeLabel != (Object)null) { ((TMP_Text)typeLabel).text = FilterLabel(TypeSelection, isSource: false); } if ((Object)(object)sourceLabel != (Object)null) { ((TMP_Text)sourceLabel).text = FilterLabel(Selection, isSource: true); } ClosePopup(); } private static void RefreshCrafting() { if ((Object)(object)gui == (Object)null) { return; } MethodInfo methodInfo = AccessTools.Method(typeof(InventoryGui), "UpdateCraftingPanel", new Type[1] { typeof(bool) }, (Type[])null); if (methodInfo == null) { if ((Object)(object)Instance != (Object)null) { ((BaseUnityPlugin)Instance).Logger.LogWarning((object)"UpdateCraftingPanel(bool) not found."); } return; } try { methodInfo.Invoke(gui, new object[1] { false }); } catch (Exception ex) { if ((Object)(object)Instance != (Object)null) { ((BaseUnityPlugin)Instance).Logger.LogWarning((object)("Crafting refresh failed: " + ex)); } } } private static void ReturnGamepadRecipeToTopAfterFilterChange() { if (padFilterFocus < 0 || (Object)(object)gui == (Object)null || !UiReady || !GamepadIsActive()) { return; } try { IList gameRecipePairs = GetGameRecipePairs(gui); if (gameRecipePairs != null && gameRecipePairs.Count != 0) { MethodInfo methodInfo = AccessTools.Method(typeof(InventoryGui), "SetRecipe", new Type[2] { typeof(int), typeof(bool) }, (Type[])null); if (methodInfo != null) { methodInfo.Invoke(gui, new object[2] { 0, false }); } ScrollRect val = (((Object)(object)adjustedViewport == (Object)null) ? null : ((Component)adjustedViewport).GetComponentInParent<ScrollRect>()); if ((Object)(object)val != (Object)null) { val.StopMovement(); val.verticalNormalizedPosition = 1f; } } } catch (Exception ex) { if ((Object)(object)Instance != (Object)null) { ((BaseUnityPlugin)Instance).Logger.LogWarning((object)("Gamepad recipe return-to-top skipped: " + ex.Message)); } } } private static HashSet<string> CategoriesForRecipe(Recipe recipe, string source) { HashSet<string> hashSet = new HashSet<string>(StringComparer.Ordinal); if ((Object)(object)recipe == (Object)null || (Object)(object)recipe.m_item == (Object)null || recipe.m_item.m_itemData == null || recipe.m_item.m_itemData.m_shared == null) { hashSet.Add("Other"); return hashSet; } string text = ((object)Unsafe.As<ItemType, ItemType>(ref recipe.m_item.m_itemData.m_shared.m_itemType)/*cast due to .constrained prefix*/).ToString(); string name = ((Object)recipe.m_item).name; string text2 = null; bool flag = source.IndexOf("Backpack", StringComparison.OrdinalIgnoreCase) >= 0; if (!flag) { switch (text) { case "Shoulder": case "Utility": case "Tool": text2 = DisplayName(recipe).ToLowerInvariant(); flag = text2.EndsWith(" backpack", StringComparison.Ordinal) || text2.EndsWith(" pack", StringComparison.Ordinal) || text2.EndsWith(" knapsack", StringComparison.Ordinal) || text2.EndsWith(" wisppack", StringComparison.Ordinal) || text2.EndsWith(" satchel", StringComparison.Ordinal) || text2 == "backpack" || text2 == "knapsack"; break; } } if (flag) { hashSet.Add("Backpacks"); return hashSet; } if (text2 == null) { text2 = DisplayName(recipe).ToLowerInvariant(); } string text3 = name.Replace("_", "").Replace("-", "").ToLowerInvariant(); string text4 = text2.Replace(" ", "").Replace("-", "").Replace("_", ""); if (Regex.IsMatch(text2, "^cast\\s*[:\\-]\\s*\\S", RegexOptions.IgnoreCase) || Regex.IsMatch(name, "^cast[_-]", RegexOptions.IgnoreCase)) { hashSet.Add("Casts"); return hashSet; } bool num = Regex.IsMatch(text2, "\\b(?:potions?|tonics?|elixirs?)\\b", RegexOptions.IgnoreCase); bool flag2 = text3.StartsWith("potion", StringComparison.Ordinal) || text3.StartsWith("tonic", StringComparison.Ordinal) || text3.StartsWith("elixir", StringComparison.Ordinal); if (num || flag2) { hashSet.Add("Potions"); return hashSet; } bool num2 = Regex.IsMatch(text2, "\\b(?:meads?|barley\\s+wine|wine\\s+base)\\b", RegexOptions.IgnoreCase); bool flag3 = text3.StartsWith("mead", StringComparison.Ordinal) || text3.StartsWith("barleywine", StringComparison.Ordinal) || text3.StartsWith("winebase", StringComparison.Ordinal); if (num2 || flag3) { hashSet.Add("Meads"); return hashSet; } bool num3 = Regex.IsMatch(text2, "\\b(?:rings?|necklaces?|pendants?|bracelets?|amulets?|earrings?|brooches?)\\b", RegexOptions.IgnoreCase); bool flag4 = text3.StartsWith("jcring", StringComparison.Ordinal) || text3.StartsWith("jcnecklace", StringComparison.Ordinal) || text3.StartsWith("jcpendant", StringComparison.Ordinal) || text3.StartsWith("jcbracelet", StringComparison.Ordinal) || text3.StartsWith("jcamulet", StringComparison.Ordinal) || text3.StartsWith("jcearring", StringComparison.Ordinal) || Regex.IsMatch(name, "(?:^|[_-])(?:rings?|necklaces?|pendants?|bracelets?|amulets?|earrings?|brooches?)(?:$|[_-])", RegexOptions.IgnoreCase); if (num3 || flag4) { hashSet.Add("Jewelry"); return hashSet; } bool flag5 = Regex.IsMatch(text2, "\\b(?:gems?|gemstones?)\\b", RegexOptions.IgnoreCase) || Regex.IsMatch(text2, "^(?:(?:simple|advanced|perfect|uncut|raw|shattered|merged|boss)\\s+)?(?:onyx|sapphire|sulfur|spinel|ruby|emerald|humite|diamond|topaz)(?:\\s+(?:gemstones?|gems?|shards?|formations?))?$", RegexOptions.IgnoreCase) || Regex.IsMatch(text2, "^(?:onyx|sapphire|sulfur|spinel|ruby|emerald|humite|diamond|topaz)(?:\\s+(?:onyx|sapphire|sulfur|spinel|ruby|emerald|humite|diamond|topaz))?\\s+(?:shards?|formations?)$", RegexOptions.IgnoreCase); bool flag6 = text3.StartsWith("jcsocket", StringComparison.Ordinal) || text3.StartsWith("jcgemstone", StringComparison.Ordinal) || text3.StartsWith("jcuncut", StringComparison.Ordinal) || text3.StartsWith("jcraw", StringComparison.Ordinal) || text3.StartsWith("jcshattered", StringComparison.Ordinal) || Regex.IsMatch(name, "^jc_(?:.*(?:socket|gemstone|shard|uncut|merged_gemstone).*)$", RegexOptions.IgnoreCase); switch (text) { default: if (!(text == "Trophie")) { break; } goto case "Material"; case "Material": case "Utility": case "Consumable": if (flag5 || flag6) { hashSet.Add("Gems"); return hashSet; } break; } if (text3.Contains("bloodthirster") || text4.Contains("bloodthirster")) { hashSet.Add("Weapons"); return hashSet; } if (text.Equals("Saddle", StringComparison.OrdinalIgnoreCase) || text3.Contains("saddle") || text4.Contains("saddle")) { hashSet.Add("Saddles"); return hashSet; } if (text.Equals("Trinket", StringComparison.OrdinalIgnoreCase) || text3.Contains("trinket") || text4.Contains("trinket")) { hashSet.Add("Trinkets"); return hashSet; } int num4; switch (text) { default: num4 = ((text == "Ammo") ? 1 : 0); break; case "OneHandedWeapon": case "TwoHandedWeapon": case "TwoHandedWeaponLeft": case "Bow": num4 = 1; break; } bool flag7 = (byte)num4 != 0; bool flag8 = text4 == "bell" || text4 == "bellfragment" || text3 == "bell" || text3 == "bellfragment" || Regex.IsMatch(text2, "\\bkeys?\\b", RegexOptions.IgnoreCase) || text4.Contains("sealbreaker"); bool flag9 = text3.StartsWith("key", StringComparison.Ordinal) || text3.EndsWith("key", StringComparison.Ordinal) || text3.Contains("keyfragment") || text3.Contains("sealbreaker") || Regex.IsMatch(name, "(?:^|[_-])key(?:[_-]|$)", RegexOptions.IgnoreCase); if (text.Equals("Key", StringComparison.OrdinalIgnoreCase) || (!flag7 && (flag8 || flag9))) { hashSet.Add("Keys"); return hashSet; } bool num5 = Regex.IsMatch(text2, "\\bmiss(?:ile|le)s?\\b", RegexOptions.IgnoreCase); bool flag10 = text3.EndsWith("missile", StringComparison.Ordinal) || text3.EndsWith("missiles", StringComparison.Ordinal) || text3.EndsWith("missle", StringComparison.Ordinal) || text3.EndsWith("missles", StringComparison.Ordinal); bool flag11 = Regex.IsMatch(text2, "\\b(?:launcher|staff|wand)\\b", RegexOptions.IgnoreCase) || text3.Contains("launcher") || text3.Contains("staff") || text3.Contains("wand"); if ((num5 || flag10) && !flag11) { hashSet.Add("Ammo"); return hashSet; } if (Regex.IsMatch(text2, "\\bbaits?\\b", RegexOptions.IgnoreCase) || text3.Contains("fishingbait") || text3.StartsWith("bait", StringComparison.Ordinal) || text3.EndsWith("bait", StringComparison.Ordinal)) { hashSet.Add("Baits"); return hashSet; } if (text == "Ammo") { hashSet.Add("Ammo"); return hashSet; } if (text.Equals("Quiver", StringComparison.OrdinalIgnoreCase) || text3.Contains("quiver") || text4.Contains("quiver")) { hashSet.Add("Archery"); return hashSet; } if (text == "Bow" || text.Equals("Crossbow", StringComparison.OrdinalIgnoreCase) || text3.Contains("crossbow") || text4.Contains("crossbow") || (text3.StartsWith("bow", StringComparison.Ordinal) && !text3.Contains("bowstring")) || text2.EndsWith(" bow", StringComparison.Ordinal) || text2.EndsWith(" longbow", StringComparison.Ordinal)) { hashSet.Add("Archery"); hashSet.Add("Weapons"); return hashSet; } if (text3.Contains("snowshovel") || text4.Contains("snowshovel") || text3.Contains("butcherknife") || text4.Contains("butcherknife") || text3.Contains("fishingrod") || text4.Contains("fishingrod") || text3.Contains("fishingpole") || text4.Contains("fishingpole") || text3.Contains("scythe") || text4.Contains("scythe")) { hashSet.Add("Tools"); return hashSet; } bool flag12 = name.IndexOf("pickaxe", StringComparison.OrdinalIgnoreCase) >= 0; if (!flag12 && (text == "OneHandedWeapon" || text == "Tool")) { if (text2 == null) { text2 = DisplayName(recipe).ToLowerInvariant(); } flag12 = text2.Contains("pickaxe"); } if (flag12) { hashSet.Add("Tools"); return hashSet; } string text5 = (((Object)(object)recipe.m_craftingStation != (Object)null) ? ((Object)recipe.m_craftingStation).name : "").Replace("_", "").Replace("-", "").Replace(" ", "") .ToLowerInvariant(); bool num6 = text5.Contains("foodprep") || text5.Contains("foodpreparation"); bool flag13 = Regex.IsMatch(text2, "\\b(?:uncooked|unbaked|dough|picnic|feast|pies?|platter|soups?|stews?|jerky|roasted|cooked|breads?|raw fish|stuffed mushroom|salad|porridge|omelette|omelet)\\b", RegexOptions.IgnoreCase); bool flag14 = text == "Material" || text == "Consumable" || text == "Fish"; if (num6 || (flag13 && flag14)) { hashSet.Add("Foods"); return hashSet; } switch (text) { case "Shoulder": hashSet.Add("Back"); break; case "Helmet": hashSet.Add("Helmets"); break; case "Chest": hashSet.Add("Chest"); break; case "Legs": hashSet.Add("Legs"); break; case "Shield": hashSet.Add("Shields"); break; case "OneHandedWeapon": hashSet.Add("Weapons"); if (text2 == null) { text2 = DisplayName(recipe).ToLowerInvariant(); } if (text2.EndsWith(" axe", StringComparison.Ordinal) || text2.EndsWith(" hatchet", StringComparison.Ordinal) || (name.StartsWith("Axe", StringComparison.OrdinalIgnoreCase) && name.IndexOf("Battle", StringComparison.OrdinalIgnoreCase) < 0)) { hashSet.Add("Tools"); } break; case "TwoHandedWeapon": case "TwoHandedWeaponLeft": case "Bow": hashSet.Add("Weapons"); break; case "Tool": case "Torch": hashSet.Add("Tools"); break; case "Ammo": hashSet.Add("Ammo"); break; case "Material": hashSet.Add("Materials"); break; case "Consumable": case "Fish": hashSet.Add("Foods"); break; case "Utility": hashSet.Add("Utility"); break; case "Trophie": hashSet.Add("Trophies"); break; default: hashSet.Add("Other"); break; } return hashSet; } internal static bool IsStationCrafting() { Player localPlayer = Player.m_localPlayer; if ((Object)(object)localPlayer != (Object)null) { return (Object)(object)localPlayer.GetCurrentCraftingStation() != (Object)null; } return false; } internal static void UpdateRecipes(ref List<Recipe> recipes) { if (!IsStationCrafting() || !UiReady || recipes == null) { return; } EnsureDiscoveryOwner(Player.m_localPlayer); SortedSet<string> sortedSet = new SortedSet<string>(StringComparer.OrdinalIgnoreCase); string[] array = new string[24] { "Back", "Backpacks", "Helmets", "Chest", "Legs", "Shields", "Archery", "Weapons", "Tools", "Ammo", "Baits", "Casts", "Foods", "Meads", "Potions", "Gems", "Jewelry", "Materials", "Keys", "Saddles", "Trinkets", "Utility", "Trophies", "Other" }; HashSet<string> hashSet = new HashSet<string>(StringComparer.Ordinal); Dictionary<Recipe, string> dictionary = new Dictionary<Recipe, string>(); Dictionary<Recipe, HashSet<string>> dictionary2 = new Dictionary<Recipe, HashSet<string>>(); foreach (Recipe recipe in recipes) { if ((Object)(object)recipe == (Object)null) { continue; } string text = SourceForRecipe(recipe); sortedSet.Add(text); HashSet<string> hashSet2 = CategoriesForRecipe(recipe, text); foreach (string item2 in hashSet2) { hashSet.Add(item2); } dictionary[recipe] = text; dictionary2[recipe] = hashSet2; } AvailableSources.Clear(); AvailableSources.Add("All"); if (sortedSet.Contains("Valheim")) { AvailableSources.Add("Valheim"); } foreach (string item3 in sortedSet) { if (!item3.Equals("Valheim", StringComparison.OrdinalIgnoreCase) && !item3.Equals("Unknown", StringComparison.OrdinalIgnoreCase) && !item3.Equals("All", StringComparison.OrdinalIgnoreCase)) { AvailableSources.Add(item3); } } if (sortedSet.Contains("Unknown")) { AvailableSources.Add("Unknown"); } AvailableTypes.Clear(); AvailableTypes.Add("All"); string[] array2 = array; foreach (string item in array2) { if (hashSet.Contains(item)) { AvailableTypes.Add(item); } } List<Recipe> list = new List<Recipe>(recipes.Count); if (Selection == "All" && TypeSelection == "All") { list.AddRange(recipes); } else { foreach (Recipe recipe2 in recipes) { if (!((Object)(object)recipe2 == (Object)null) && (!(Selection != "All") || dictionary[recipe2].Equals(Selection, StringComparison.OrdinalIgnoreCase)) && (!(TypeSelection != "All") || dictionary2[recipe2].Contains(TypeSelection))) { list.Add(recipe2); } } } if (Selection != "All" || TypeSelection != "All") { recipes = list; } } private static void EnsureDiscoveryOwner(Player player) { if ((Object)(object)player == (Object)null || (Object)(object)Player.m_localPlayer != (Object)(object)player || ((Object)(object)discoveryOwner == (Object)(object)player && !string.IsNullOrEmpty(persistenceFile))) { return; } if ((Object)(object)discoveryOwner != (Object)(object)player) { discoveryOwner = player; NewlyDiscoveredNames.Clear(); PreviewDismissedNames.Clear(); PreviewTargetNames.Clear(); activeViewedRecipeKey = null; activeViewedRecipeRow = null; KeepAtTopUntilMenuClose.Clear(); } persistenceFile = null; try { string playerName = player.GetPlayerName(); if (string.IsNullOrEmpty(playerName)) { return; } string text = Convert.ToBase64String(Encoding.UTF8.GetBytes(playerName.Trim().ToLowerInvariant())).TrimEnd('=').Replace('+', '-') .Replace('/', '_'); string text2 = Path.Combine(Paths.ConfigPath, "RamCraftFilterModLabels"); Directory.CreateDirectory(text2); persistenceFile = Path.Combine(text2, "new-" + text + ".txt"); if (!File.Exists(persistenceFile)) { return; } string[] array = File.ReadAllLines(persistenceFile); foreach (string text3 in array) { if (!string.IsNullOrEmpty(text3)) { NewlyDiscoveredNames.Add(text3); } } } catch (Exception ex) { persistenceFile = null; if ((Object)(object)Instance != (Object)null) { ((BaseUnityPlugin)Instance).Logger.LogWarning((object)("Local NEW tracking unavailable: " + ex.Message)); } } } private static void SaveNewMarkers() { if (string.IsNullOrEmpty(persistenceFile)) { return; } try { string text = persistenceFile + ".tmp"; File.WriteAllLines(text, NewlyDiscoveredNames); File.Copy(text, persistenceFile, overwrite: true); File.Delete(text); } catch (Exception ex) { if ((Object)(object)Instance != (Object)null) { ((BaseUnityPlugin)Instance).Logger.LogWarning((object)("Could not save local NEW markers: " + ex.Message)); } } } internal static HashSet<string> SnapshotKnownRecipes(Player player) { if ((Object)(object)player == (Object)null || (Object)(object)Player.m_localPlayer != (Object)(object)player) { return null; } EnsureDiscoveryOwner(player); try { HashSet<string> value = Traverse.Create((object)player).Field("m_knownRecipes").GetValue<HashSet<string>>(); if (value == null) { return null; } return new HashSet<string>(value, StringComparer.Ordinal); } catch (Exception ex) { if ((Object)(object)Instance != (Object)null) { ((BaseUnityPlugin)Instance).Logger.LogDebug((object)("NEW snapshot unavailable: " + ex.Message)); } return null; } } internal static void TrackRecipeDiscovery(Player player, HashSet<string> prior) { if (prior == null || (Object)(object)player == (Object)null || (Object)(object)discoveryOwner != (Object)(object)player) { return; } try { HashSet<string> value = Traverse.Create((object)player).Field("m_knownRecipes").GetValue<HashSet<string>>(); if (value == null) { return; } int num = 0; foreach (string item in value) { if (!prior.Contains(item) && NewlyDiscoveredNames.Add(item)) { num++; } } if (num != 0) { SaveNewMarkers(); if ((Object)(object)Instance != (Object)null) { ((BaseUnityPlugin)Instance).Logger.LogDebug((object)("RamCraftFilterModLabels noticed " + num + " newly discovered recipe(s).")); } } } catch (Exception ex) { if ((Object)(object)Instance != (Object)null) { ((BaseUnityPlugin)Instance).Logger.LogDebug((object)("NEW discovery unavailable: " + ex.Message)); } } } private static string RecipeKnowledgeKey(Recipe recipe) { if ((Object)(object)recipe == (Object)null || (Object)(object)recipe.m_item == (Object)null || recipe.m_item.m_itemData == null || recipe.m_item.m_itemData.m_shared == null) { return null; } return recipe.m_item.m_itemData.m_shared.m_name; } private static string CleanDisplayName(string input) { if (string.IsNullOrEmpty(input)) { return ""; } return Regex.Replace(input, "<[^>]*>", "").Trim(); } private static string DisplayName(Recipe recipe) { string text = RecipeKnowledgeKey(recipe); if (string.IsNullOrEmpty(text)) { return ""; } try { if (!localizationSearched) { Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies(); for (int i = 0; i < assemblies.Length; i++) { Type type = assemblies[i].GetType("Localization", throwOnError: false); if (!(type == null)) { MethodInfo method = type.GetMethod("Localize", BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic, null, new Type[1] { typeof(string) }, null); if (!(method == null)) { localizationLocalize = method; localizationInstanceField = type.GetField("instance", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); localizationInstanceProperty = type.GetProperty("instance", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic) ?? type.GetProperty("Instance", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); break; } } } localizationSearched = true; } if (localizationLocalize != null) { object obj = null; if (!localizationLocalize.IsStatic) { if (localizationInstanceField != null) { obj = localizationInstanceField.GetValue(null); } else if (localizationInstanceProperty != null) { obj = localizationInstanceProperty.GetValue(null, null); } if (obj == null) { return CleanDisplayName(text); } } string text2 = localizationLocalize.Invoke(obj, new object[1] { text }) as string; if (!string.IsNullOrEmpty(text2)) { return CleanDisplayName(text2); } } } catch (Exception) { } return CleanDisplayName(text); } private static TMP_Text FindNameText(Transform row) { if ((Object)(object)row == (Object)null) { return null; } TMP_Text[] componentsInChildren = ((Component)row).GetComponentsInChildren<TMP_Text>(true); foreach (TMP_Text val in componentsInChildren) { if ((Object)(object)val != (Object)null && ((Object)((Component)val).gameObject).name.Equals("name", StringComparison.OrdinalIgnoreCase)) { return val; } } return null; } private static Text FindLegacyNameText(Transform row) { if ((Object)(object)row == (Object)null) { return null; } Text[] componentsInChildren = ((Component)row).GetComponentsInChildren<Text>(true); foreach (Text val in componentsInChildren) { if ((Object)(object)val != (Object)null && ((Object)((Component)val).gameObject).name.Equals("name", StringComparison.OrdinalIgnoreCase)) { return val; } } return null; } internal static string WithoutOurNewPrefix(string text) { if (string.IsNullOrEmpty(text)) { return text; } if (text.StartsWith("<color=#39FF14><b>*</b></color> ", StringComparison.Ordinal)) { return text.Substring("<color=#39FF14><b>*</b></color> ".Length); } if (text.StartsWith("<color=#39FF14><b>*</b></color> ", StringComparison.Ordinal)) { return text.Substring("<color=#39FF14><b>*</b></color> ".Length); } if (text.StartsWith("<color=#A3CE3C><size=85%><b>*</b></size></color> ", StringComparison.Ordinal)) { return text.Substring("<color=#A3CE3C><size=85%><b>*</b></size></color> ".Length); } if (text.StartsWith("<color=#A3CE3C><b>*</b></color> ", StringComparison.Ordinal)) { return text.Substring("<color=#A3CE3C><b>*</b></color> ".Length); } if (text.StartsWith("<color=#A3CE3C><size=75%><b>NEW</b></size></color> ", StringComparison.Ordinal)) { return text.Substring("<color=#A3CE3C><size=75%><b>NEW</b></size></color> ".Length); } if (text.StartsWith("<color=#A3CE3C><b>NEW</b></color> ", StringComparison.Ordinal)) { return text.Substring("<color=#A3CE3C><b>NEW</b></color> ".Length); } return text; } internal static string WithNewPrefix(string text, bool useTmp) { return (useTmp ? "<color=#39FF14><b>*</b></color> " : "<color=#39FF14><b>*</b></color> ") + WithoutOurNewPrefix(text); } internal static void BeganViewingRecipe(string key, bool wasStarred, RecipeRowNewMarker row) { if (string.IsNullOrEmpty(key)) { return; } if (!string.IsNullOrEmpty(activeViewedRecipeKey) && activeViewedRecipeKey != key) { DismissNew(activeViewedRecipeKey); if ((Object)(object)activeViewedRecipeRow != (Object)null) { activeViewedRecipeRow.RemoveStarFromText(); } activeViewedRecipeKey = null; activeViewedRecipeRow = null; } if (wasStarred) { activeViewedRecipeKey = key; activeViewedRecipeRow = row; } } internal static bool LeftViewedRecipe(string key) { if (string.IsNullOrEmpty(key) || activeViewedRecipeKey != key) { return false; } activeViewedRecipeKey = null; activeViewedRecipeRow = null; return DismissNew(key); } private static bool DismissNew(string key) { if (string.IsNullOrEmpty(key)) { return false; } bool num = NewlyDiscoveredNames.Remove(key); if (num) { SaveNewMarkers(); } bool flag = PreviewTargetNames.Contains(key) && !PreviewDismissedNames.Contains(key); PreviewDismissedNames.Add(key); if (num || flag) { KeepAtTopUntilMenuClose.Add(key); } return num || flag; } internal static void EndCraftingMenuSession() { activeViewedRecipeKey = null; activeViewedRecipeRow = null; KeepAtTopUntilMenuClose.Clear(); } private static IList GetGameRecipePairs(InventoryGui current) { FieldInfo fieldInfo = AccessTools.Field(typeof(InventoryGui), "m_availableRecipes"); if (!(fieldInfo == null)) { return fieldInfo.GetValue(current) as IList; } return null; } private static PropertyInfo FindPairProperty(object pair, string propertyName) { return pair?.GetType().GetProperty(propertyName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); } private static Recipe GetPairedRecipe(object pair) { PropertyInfo propertyInfo = FindPairProperty(pair, "Recipe") ?? FindPairProperty(pair, "Key"); if (!(propertyInfo == null)) { object? value = propertyInfo.GetValue(pair, null); return (Recipe)((value is Recipe) ? value : null); } return null; } private static GameObject GetPairedRow(object pair) { PropertyInfo propertyInfo = FindPairProperty(pair, "InterfaceElement"); if (!(propertyInfo == null)) { object? value = propertyInfo.GetValue(pair, null); return (GameObject)((value is GameObject) ? value : null); } return null; } internal static void SortActualRecipeRows(InventoryGui current) { //IL_017a: 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_018f: Unknown result type (might be due to invalid IL or missing references) if (!IsStationCrafting() || (Object)(object)current == (Object)null || !UiReady) { return; } try { IList gameRecipePairs = GetGameRecipePairs(current); if (gameRecipePairs == null || gameRecipePairs.Count < 2) { return; } List<object> list = new List<object>(); List<object> list2 = new List<object>(); for (int i = 0; i < gameRecipePairs.Count; i++) { object obj = gameRecipePairs[i]; Recipe pairedRecipe = GetPairedRecipe(obj); GameObject pairedRow = GetPairedRow(obj); if ((Object)(object)pairedRecipe == (Object)null || (Object)(object)pairedRow == (Object)null || (Object)(object)pairedRow.GetComponent<RectTransform>() == (Object)null) { if ((Object)(object)Instance != (Object)null) { ((BaseUnityPlugin)Instance).Logger.LogWarning((object)"NEW-first: recipe pair layout differs; leaving vanilla order unchanged."); } return; } string text = RecipeKnowledgeKey(pairedRecipe); if (!string.IsNullOrEmpty(text) && (NewlyDiscoveredNames.Contains(text) || KeepAtTopUntilMenuClose.Contains(text))) { list.Add(obj); } else { list2.Add(obj); } } if (list.Count != 0 && list2.Count != 0) { list.AddRange(list2); float num = Traverse.Create((object)current).Field("m_recipeListSpace").GetValue<float>(); if (num <= 0f) { num = 30f; } for (int j = 0; j < list.Count; j++) { gameRecipePairs[j] = list[j]; } for (int k = 0; k < list.Count; k++) { RectTransform component = GetPairedRow(list[k]).GetComponent<RectTransform>(); Vector2 anchoredPosition = component.anchoredPosition; anchoredPosition.y = (float)(-k) * num; component.anchoredPosition = anchoredPosition; ((Transform)component).SetSiblingIndex(k); } } } catch (Exception ex) { if ((Object)(object)Instance != (Object)null) { ((BaseUnityPlugin)Instance).Logger.LogWarning((object)("NEW-first sort skipped: " + ex)); } } } internal static void OnGameRecipeSelected(InventoryGui current, int index) { if (suppressAutomaticRecipeViewing || (Object)(object)current == (Object)null || index < 0) { return; } try { IList gameRecipePairs = GetGameRecipePairs(current); if (gameRecipePairs != null && index < gameRecipePairs.Count) { object pair = gameRecipePairs[index]; Recipe pairedRecipe = GetPairedRecipe(pair); if (!((Object)(object)pairedRecipe == (Object)null)) { string text = RecipeKnowledgeKey(pairedRecipe); GameObject pairedRow = GetPairedRow(pair); RecipeRowNewMarker row = (((Object)(object)pairedRow == (Object)null) ? null : pairedRow.GetComponent<RecipeRowNewMarker>()); bool wasStarred = !string.IsNullOrEmpty(text) && (NewlyDiscoveredNames.Contains(text) || (previewNew != null && previewNew.Value && PreviewTargetNames.Contains(text) && !PreviewDismissedNames.Contains(text))); BeganViewingRecipe(text, wasStarred, row); } } } catch (Exception ex) { if ((Object)(object)Instance != (Object)null) { ((BaseUnityPlugin)Instance).Logger.LogWarning((object)("Recipe selection tracking skipped: " + ex)); } } } internal static void DecorateRecipeRows(InventoryGui current, List<Recipe> recipes) { //IL_00d2: Unknown result type (might be due to invalid IL or missing references) //IL_00d9: Expected O, but got Unknown if ((Object)(object)current == (Object)null || recipes == null) { return; } EnsureDiscoveryOwner(Player.m_localPlayer); try { RectTransform value = Traverse.Create((object)current).Field("m_recipeListRoot").GetValue<RectTransform>(); if ((Object)(object)value == (Object)null) { return; } Dictionary<string, List<Recipe>> dictionary = new Dictionary<string, List<Recipe>>(StringComparer.OrdinalIgnoreCase); foreach (Recipe recipe in recipes) { string text = DisplayName(recipe); if (!string.IsNullOrEmpty(text)) { if (!dictionary.TryGetValue(text, out var value2)) { value2 = new List<Recipe>(); dictionary.Add(text, value2); } value2.Add(recipe); } } bool flag = previewNew != null && previewNew.Value; foreach (Transform item in (Transform)value) { Transform val = item; TMP_Text val2 = FindNameText(val); Text val3 = (((Object)(object)val2 == (Object)null) ? FindLegacyNameText(val) : null); if ((Object)(object)val2 == (Object)null && (Object)(object)val3 == (Object)null) { continue; } string text2 = (((Object)(object)val2 != (Object)null) ? val2.text : val3.text); string text3 = WithoutOurNewPrefix(text2); if (string.IsNullOrEmpty(text3)) { continue; } if (!dictionary.TryGetValue(CleanDisplayName(text3), out var value3) || value3.Count != 1) { if (text3 != text2) { if ((Object)(object)val2 != (Object)null) { val2.text = text3; } else { val3.text = text3; } } continue; } string text4 = RecipeKnowledgeKey(value3[0]); bool flag2 = !string.IsNullOrEmpty(text4) && NewlyDiscoveredNames.Contains(text4); if (flag && !string.IsNullOrEmpty(text4) && PreviewTargetNames.Count < 3) { PreviewTargetNames.Add(text4); } bool flag3 = flag && !string.IsNullOrEmpty(text4) && PreviewTargetNames.Contains(text4) && !PreviewDismissedNames.Contains(text4); RecipeRowNewMarker recipeRowNewMarker = ((Component)val).GetComponent<RecipeRowNewMarker>(); if ((Object)(object)recipeRowNewMarker == (Object)null) { recipeRowNewMarker = ((Component)val).gameObject.AddComponent<RecipeRowNewMarker>(); } recipeRowNewMarker.Show(val2, val3, text4, flag2 || flag3, text3); } } catch (Exception ex) { if ((Object)(object)Instance != (Object)null) { ((BaseUnityPlugin)Instance).Logger.LogWarning((object)("Recipe NEW markers skipped: " + ex.Message)); } } } private static void ResolvePadInput() { if (padInputResolved) { return; } padInputResolved = true; Type type = AccessTools.TypeByName("ZInput"); if (!(type == null)) { zPadDown = AccessTools.Method(type, "GetButtonDown", new Type[1] { typeof(string) }, (Type[])null); zPadActive = AccessTools.Method(type, "IsGamepadActive", Type.EmptyTypes, (Type[])null); zPadReset = AccessTools.Method(type, "ResetButtonStatus", new Type[1] { typeof(string) }, (Type[])null); if ((zPadDown == null || zPadActive == null || zPadReset == null) && (Object)(object)Instance != (Object)null && !padWarningLogged) { padWarningLogged = true; ((BaseUnityPlugin)Instance).Logger.LogWarning((object)"Gamepad filter controls unavailable: missing ZInput method; normal crafting is untouched."); } } } private static bool GamepadIsActive() { ResolvePadInput(); try { return zPadActive != null && (bool)zPadActive.Invoke(null, null); } catch { return false; } } private static bool PadDown(string button) { if (zPadDown == null) { return false; } try { return (bool)zPadDown.Invoke(null, new object[1] { button }); } catch { return false; } } private static bool PadVerticalUp() { if (!PadDown("JoyDPadUp") && !PadDown("JoyRStickUp")) { return PadDown("JoyLStickUp"); } return true; } private static bool PadVerticalDown() { if (!PadDown("JoyDPadDown") && !PadDown("JoyRStickDown")) { return PadDown("JoyLStickDown"); } return true; } private static bool CraftingGroupActive(InventoryGui current) { try { if (!(Traverse.Create((object)current).Field("m_uiGroups").GetValue() is Array { Length: >3 } array) || array.GetValue(3) == null) { return false; } object value = array.GetValue(3); PropertyInfo propertyInfo = AccessTools.Property(value.GetType(), "IsActive"); return propertyInfo != null && (bool)propertyInfo.GetValue(value, null); } catch { return false; } } private static bool OnCraftTab(InventoryGui current) { try { MethodInfo methodInfo = AccessTools.Method(typeof(InventoryGui), "InCraftTab", Type.EmptyTypes, (Type[])null); if (methodInfo == null) { return false; } return (bool)methodInfo.Invoke(current, null); } catch { return false; } } private static void RestoreStyleButton() { if ((Object)(object)guardedStyleButton != (Object)null) { ((Selectable)guardedStyleButton).interactable = styleWasInteractable; } guardedStyleButton = null; } private static void GuardStyleButton(InventoryGui current) { if (padFilterFocus < 0 || !((Object)(object)current != (Object)null) || !((Object)(object)current == (Object)(object)gui) || !UiReady || !GamepadIsActive()) { RestoreStyleButton(); return; } Button val = null; try { val = Traverse.Create((object)current).Field("m_variantButton").GetValue<Button>(); } catch { } if ((Object)(object)guardedStyleButton != (Object)(object)val) { RestoreStyleButton(); } if (!((Object)(object)val == (Object)null)) { if ((Object)(object)guardedStyleButton == (Object)null) { guardedStyleButton = val; styleWasInteractable = ((Selectable)val).interactable; } ((Selectable)val).interactable = false; } } private static void ResetGamepadRecipePosition(InventoryGui current) { try { IList gameRecipePairs = GetGameRecipePairs(current); if (gameRecipePairs != null && gameRecipePairs.Count > 0) { MethodInfo methodInfo = AccessTools.Method(typeof(InventoryGui), "SetRecipe", new Type[2] { typeof(int), typeof(bool) }, (Type[])null); if (methodInfo != null) { suppressAutomaticRecipeViewing = true; try { methodInfo.Invoke(current, new object[2] { 0, false }); } finally { suppressAutomaticRecipeViewing = false; } } } ScrollRect val = (((Object)(object)adjustedViewport == (Object)null) ? null : ((Component)adjustedViewport).GetComponentInParent<ScrollRect>()); if ((Object)(object)val != (Object)null) { val.StopMovement(); val.verticalNormalizedPosition = 1f; } } catch (Exception ex) { if ((Object)(object)Instance != (Object)null) { ((BaseUnityPlugin)Instance).Logger.LogWarning((object)("New station controller positioning skipped: " + ex.Message)); } } finally { suppressAutomaticRecipeViewing = false; } } internal static void OnCraftingWindowShown(InventoryGui current) { if (!((Object)(object)current == (Object)null)) { ReleaseUiFromOldSession(current); if (IsStationCrafting() && GamepadIsActive()) { benchStartFilterPending = true; BeginBenchFilterFocus(current); } } } private static void BeginBenchFilterFocus(InventoryGui current) { if (benchStartFilterPending && !((Object)(object)current == (Object)null) && UiReady && GamepadIsActive() && CraftingGroupActive(current) && OnCraftTab(current)) { benchStartFilterPending = false; ResetGamepadRecipePosition(current); activeViewedRecipeKey = null; activeViewedRecipeRow = null; padPopupOpen = false; padFilterFocus = 0; PaintPadFocus(); } } private static void PaintPadFocus() { //IL_0058: 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_00bb: Unknown result type (might be due to invalid IL or missing references) //IL_00a0: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)typeControl != (Object)null) { Image component = typeControl.GetComponent<Image>(); if ((Object)(object)component != (Object)null) { ((Graphic)component).color = ((padFilterFocus == 0) ? new Color(0.34f, 0.26f, 0.13f, 0.98f) : new Color(0.12f, 0.1f, 0.08f, 0.96f)); } } if ((Object)(object)sourceControl != (Object)null) { Image component2 = sourceControl.GetComponent<Image>(); if ((Object)(object)component2 != (Object)null) { ((Graphic)component2).color = ((padFilterFocus == 1) ? new Color(0.34f, 0.26f, 0.13f, 0.98f) : new Color(0.12f, 0.1f, 0.08f, 0.96f)); } } GuardStyleButton(gui); } private static void PaintPadOptions() { //IL_0051: 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) for (int i = 0; i < padOptionBackgrounds.Count; i++) { Image val = padOptionBackgrounds[i]; if ((Object)(object)val != (Object)null) { ((Graphic)val).color = ((i == padOptionIndex) ? new Color(0.52f, 0.36f, 0.13f, 1f) : new Color(0.15f, 0.13f, 0.11f, 1f)); } } } private static void LeavePadFilterFocus() { padFilterFocus = -1; padPopupOpen = false; padOptionIndex = 0; PaintPadFocus(); ClosePopup(); } internal static void ConsumeFilterCancelBeforeInventoryUpdate(InventoryGui current) { if (benchStartFilterPending) { BeginBenchFilterFocus(current); } if (padFilterFocus < 0) { return; } if ((Object)(object)current == (Object)null || !UiReady || !IsStationCrafting() || !InventoryGui.IsVisible() || !GamepadIsActive() || !CraftingGroupActive(current) || !OnCraftTab(current)) { LeavePadFilterFocus(); return; } GuardStyleButton(current); if (!PadDown("JoyButtonB")) { return; } LeavePadFilterFocus(); try { if (zPadReset != null) { zPadReset.Invoke(null, new object[1] { "JoyButtonB" }); } } catch { } } internal static bool HandleRecipeGamepadInput(InventoryGui current) { if (benchStartFilterPending) { BeginBenchFilterFocus(current); } if ((Object)(object)current == (Object)null || !UiReady || !IsStationCrafting() || !InventoryGui.IsVisible() || !GamepadIsActive() || !CraftingGroupActive(current) || !OnCraftTab(current)) { if (padFilterFocus >= 0) { LeavePadFilterFocus(); } return true; } if (padFilterFocus < 0) { if (!PadVerticalUp()) { return true; } try { MethodInfo methodInfo = AccessTools.Method(typeof(InventoryGui), "GetSelectedRecipeIndex", new Type[1] { typeof(bool) }, (Type[])null); if (methodInfo == null || (int)methodInfo.Invoke(current, new object[1] { false }) != 0) { return true; } } catch { return true; } padFilterFocus = 0; PaintPadFocus(); return false; } if (padPopupOpen) { if (PadVerticalUp() && padOptionChoices.Count > 0) { padOptionIndex = (padOptionIndex + padOptionChoices.Count - 1) % padOptionChoices.Count; PaintPadOptions(); } else if (PadVerticalDown() && padOptionChoices.Count > 0) { padOptionIndex = (padOptionIndex + 1) % padOptionChoices.Count; PaintPadOptions(); } else if (PadDown("JoyButtonA") && padOptionChoices.Count > 0) { string choice = padOptionChoices[padOptionIndex]; if (padFilterFocus == 0) { ChooseType(choice); } else { ChooseSource(choice); } PaintPadFocus(); } return false; } if (PadDown("JoyDPadLeft") || PadDown("JoyRStickLeft") || PadDown("JoyLStickLeft")) { padFilterFocus = 0; PaintPadFocus(); } else if (PadDown("JoyDPadRight") || PadDown("JoyRStickRight") || PadDown("JoyLStickRight")) { padFilterFocus = 1; PaintPadFocus(); } else if (PadVerticalDown()) { LeavePadFilterFocus(); } else if (PadDown("JoyButtonA")) { List<string> list = new List<string>((padFilterFocus == 0) ? AvailableTypes : AvailableSources); if (!list.Contains("All")) { list.Insert(0, "All"); } string selected = ((padFilterFocus == 0) ? TypeSelection : Selection); padOptionIndex = Mathf.Max(0, list.FindIndex((string c) => c.Equals(selected, StringComparison.OrdinalIgnoreCase))); padPopupOpen = true; OpenPopup(padFilterFocus == 1); if ((Object)(object)overlayRoot == (Object)null || !overlayRoot.activeSelf) { padPopupOpen = false; } PaintPadOptions(); } return false; } internal static void ResetUi() { //IL_0028: Unknown result type (might be due to invalid IL or missing references) benchStartFilterPending = false; RestoreStyleButton(); ResetFilterSelections(); UiReady = false; if ((Object)(object)adjustedViewport != (Object)null) { adjustedViewport.offsetMax = originalOffsetMax; } adjustedViewport = null; if ((Object)(object)sourceControl != (Object)null) { Object.Destroy((Object)(object)sourceControl); } if ((Object)(object)typeControl != (Object)null) { Object.Destroy((Object)(object)typeControl); } if ((Object)(object)overlayRoot != (Object)null) { Object.Destroy((Object)(object)overlayRoot); } sourceControl = null; typeControl = null; overlayRoot = null; sourceLabel = null; typeLabel = null; gui = null; } } internal sealed class RecipeRowNewMarker : MonoBehaviour { private TMP_Text tmpName; private Text legacyName; private string unmarkedText; internal void Show(TMP_Text titleTmp, Text titleLegacy, string key, bool isNew, string originalText) { tmpName = titleTmp; legacyName = titleLegacy; unmarkedText = originalText; string text = (isNew ? ModOriginPlugin.WithNewPrefix(originalText, (Object)(object)titleTmp != (Object)null) : originalText); if ((Object)(object)tmpName != (Object)null && tmpName.text != text) { tmpName.text = text; } else if ((Object)(object)legacyName != (Object)null && legacyName.text != text) { legacyName.text = text; } } internal void RemoveStarFromText() { if ((Object)(object)tmpName != (Object)null && !string.IsNullOrEmpty(unmarkedText)) { tmpName.text = unmarkedText; } else if ((Object)(object)legacyName != (Object)null && !string.IsNullOrEmpty(unmarkedText)) { legacyName.text = unmarkedText; } } } [HarmonyPatch(typeof(ObjectDB), "CopyOtherDB")] [HarmonyPriority(800)] internal static class VanillaCatalogPatch { private static void Prefix(ObjectDB other) { ModOriginPlugin.CaptureVanillaItems(other); } } [HarmonyPatch] internal static class ItemTooltipPatch { private static IEnumerable<MethodBase> TargetMethods() { MethodInfo[] methods = typeof(ItemData).GetMethods(BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); foreach (MethodInfo methodInfo in methods) { if (methodInfo.Name != "GetTooltip" || methodInfo.ReturnType != typeof(string)) { continue; } ParameterInfo[] parameters = methodInfo.GetParameters(); for (int j = 0; j < parameters.Length; j++) { if (parameters[j].ParameterType == typeof(ItemData)) { yield return methodInfo; break; } } } } private static void Postfix(object[] __args, ref string __result) { if (__args == null || string.IsNullOrEmpty(__result) || __result.Contains("Source Mod:") || __result.Contains("Source:")) { return; } ItemData val = null; foreach (object obj in __args) { val = (ItemData)((obj is ItemData) ? obj : null); if (val != null) { break; } } if (val != null) { string text = ModOriginPlugin.SourceForItem(val); __result = __result + "\n<color=#A3CE3C>Source:</color> " + text; } } } [HarmonyPatch(typeof(InventoryGui), "Update")] [HarmonyPriority(800)] internal static class FilterGamepadCancelPatch { private static void Prefix(InventoryGui __instance) { ModOriginPlugin.ConsumeFilterCancelBeforeInventoryUpdate(__instance); } } [HarmonyPatch(typeof(InventoryGui), "Show", new Type[] { typeof(Container), typeof(int) })] internal static class NewStationGamepadFocusPatch { private static void Postfix(InventoryGui __instance) { ModOriginPlugin.OnCraftingWindowShown(__instance); } } [HarmonyPatch(typeof(InventoryGui), "UpdateRecipeGamepadInput")] internal static class FilterGamepadNavigationPatch { private static bool Prefix(InventoryGui __instance) { return ModOriginPlugin.HandleRecipeGamepadInput(__instance); } } [HarmonyPatch(typeof(InventoryGui), "UpdateRecipeList")] internal static class RecipeListPatch { private static void Prefix(InventoryGui __instance, ref List<Recipe> recipes) { if (!ModOriginPlugin.IsStationCrafting()) { if (ModOriginPlugin.UiReady) { ModOriginPlugin.ResetUi(); } } else { ModOriginPlugin.EnsureUi(__instance); ModOriginPlugin.UpdateRecipes(ref recipes); } } private static void Postfix(InventoryGui __instance, List<Recipe> recipes) { ModOriginPlugin.SortActualRecipeRows(__instance); ModOriginPlugin.DecorateRecipeRows(__instance, recipes); } } [HarmonyPatch(typeof(InventoryGui), "SetRecipe", new Type[] { typeof(int), typeof(bool) })] internal static class GameRecipeSelectionPatch { private static void Postfix(InventoryGui __instance, int __0) { ModOriginPlugin.OnGameRecipeSelected(__instance, __0); } } [HarmonyPatch(typeof(InventoryGui), "Hide")] internal static class InventoryHidePatch { private static void Postfix() { ModOriginPlugin.EndCraftingMenuSession(); ModOriginPlugin.ResetFilterSelections(); } } [HarmonyPatch(typeof(Player), "UpdateKnownRecipesList")] internal static class KnownRecipesChangedPatch { private static void Prefix(Player __instance, out HashSet<string> __state) { __state = ModOriginPlugin.SnapshotKnownRecipes(__instance); } private static void Postfix(Player __instance, HashSet<string> __state) { ModOriginPlugin.TrackRecipeDiscovery(__instance, __state); } }