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 CraftingSearch v1.0.1
CraftingSearch.dll
Decompiled 3 hours agousing System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Globalization; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using BepInEx; using BepInEx.Logging; using HarmonyLib; using Microsoft.CodeAnalysis; using TMPro; using UnityEngine; using UnityEngine.Events; using UnityEngine.UI; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: AssemblyVersion("0.0.0.0")] [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 CraftingSearch { [BepInPlugin("com.michal.valheim.craftingsearch", "Crafting Search", "1.0.1")] public class Plugin : BaseUnityPlugin { [HarmonyPatch(typeof(InventoryGui), "Awake")] private static class InventoryGui_Awake_Patch { private static void Postfix(InventoryGui __instance) { try { _controls = RecipeListControls.Create(__instance, delegate(string query) { _query = query ?? ""; RefreshRecipes(); }, delegate { Player localPlayer = Player.m_localPlayer; if (!((Object)(object)localPlayer == (Object)null)) { SortSettings.Set(localPlayer, SortSettings.Next(SortSettings.Current(localPlayer))); RefreshRecipes(); } }); } catch (Exception arg) { Log.LogError((object)$"Nie udalo sie dodac wyszukiwarki przepisow: {arg}"); } } } [HarmonyPatch(typeof(InventoryGui), "UpdateRecipeList")] private static class InventoryGui_UpdateRecipeList_Patch { private static void Postfix(InventoryGui __instance) { try { SortMode mode = SortSettings.Current(Player.m_localPlayer); _controls?.SetSortLabel(SortSettings.Label(mode)); RecipeList.Apply(__instance, mode, _query); } catch (Exception arg) { Log.LogError((object)$"Blad przy filtrowaniu/sortowaniu przepisow: {arg}"); } } } [HarmonyPatch(typeof(InventoryGui), "Hide")] private static class InventoryGui_Hide_Patch { private static void Postfix() { _query = ""; _controls?.Clear(); } } [HarmonyPatch(typeof(Chat), "HasFocus")] private static class Chat_HasFocus_Patch { private static void Postfix(ref bool __result) { if (!__result && _controls != null && _controls.IsTyping) { __result = true; } } } public const string PluginGUID = "com.michal.valheim.craftingsearch"; public const string PluginName = "Crafting Search"; public const string PluginVersion = "1.0.1"; internal static ManualLogSource Log; private static RecipeListControls _controls; private static string _query = ""; private static readonly MethodInfo UpdateCraftingPanelMethod = AccessTools.Method(typeof(InventoryGui), "UpdateCraftingPanel", (Type[])null, (Type[])null); private void Awake() { //IL_0016: Unknown result type (might be due to invalid IL or missing references) Log = ((BaseUnityPlugin)this).Logger; Game.isModded = true; new Harmony("com.michal.valheim.craftingsearch").PatchAll(typeof(Plugin).Assembly); } private static void RefreshRecipes() { InventoryGui instance = InventoryGui.instance; if ((Object)(object)instance != (Object)null && InventoryGui.IsVisible()) { UpdateCraftingPanelMethod.Invoke(instance, new object[1] { false }); } } } internal enum SortMode { Original, NameAscending, NameDescending, Type, Weight } internal static class SortSettings { private const string GameKey = "sortcraft"; private const string DescendingKey = "craftingsearch_desc"; private static readonly SortMode[] Cycle = new SortMode[5] { SortMode.Original, SortMode.NameAscending, SortMode.NameDescending, SortMode.Type, SortMode.Weight }; public static SortMode Current(Player player) { //IL_0025: 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_0039: Expected I4, but got Unknown string value = default(string); if ((Object)(object)player == (Object)null || !player.TryGetUniqueKeyValue("sortcraft", ref value) || !Enum.TryParse<SortMethod>(value, ignoreCase: true, out SortMethod result)) { return SortMode.Original; } switch (result - 1) { case 0: { string text = default(string); if (!player.TryGetUniqueKeyValue("craftingsearch_desc", ref text)) { return SortMode.NameAscending; } return SortMode.NameDescending; } case 1: return SortMode.Type; case 2: return SortMode.Weight; default: return SortMode.Original; } } public static SortMode Next(SortMode mode) { return Cycle[(Array.IndexOf(Cycle, mode) + 1) % Cycle.Length]; } public static void Set(Player player, SortMode mode) { player.RemoveUniqueKeyValue("sortcraft"); player.RemoveUniqueKeyValue("craftingsearch_desc"); string text = mode switch { SortMode.NameAscending => "Name", SortMode.NameDescending => "Name", SortMode.Type => "Type", SortMode.Weight => "Weight", _ => null, }; if (text != null) { player.AddUniqueKeyValue("sortcraft", text); } if (mode == SortMode.NameDescending) { player.AddUniqueKeyValue("craftingsearch_desc", "1"); } } public static string Label(SortMode mode) { return mode switch { SortMode.NameAscending => "Sort: A-Z", SortMode.NameDescending => "Sort: Z-A", SortMode.Type => "Sort: Type", SortMode.Weight => "Sort: Weight", _ => "Sort: Default", }; } } internal static class RecipeList { private static readonly FieldInfo AvailableField = AccessTools.Field(typeof(InventoryGui), "m_availableRecipes"); private static readonly FieldInfo BaseSizeField = AccessTools.Field(typeof(InventoryGui), "m_recipeListBaseSize"); private static readonly Type PairType = AccessTools.Inner(typeof(InventoryGui), "RecipeDataPair"); private static readonly PropertyInfo RecipeProperty = AccessTools.Property(PairType, "Recipe"); private static readonly PropertyInfo ItemDataProperty = AccessTools.Property(PairType, "ItemData"); private static readonly PropertyInfo ElementProperty = AccessTools.Property(PairType, "InterfaceElement"); private static readonly PropertyInfo CanCraftProperty = AccessTools.Property(PairType, "CanCraft"); public static void Apply(InventoryGui gui, SortMode mode, string query) { if (AvailableField.GetValue(gui) is IList list) { bool flag = Filter(list, query); if (mode == SortMode.NameDescending) { SortByNameDescending(list); flag = true; } if (flag) { Relayout(gui, list); } } } private static bool Filter(IList list, string query) { //IL_0055: Unknown result type (might be due to invalid IL or missing references) //IL_005f: Expected O, but got Unknown if (string.IsNullOrWhiteSpace(query)) { return false; } string value = query.Trim(); CompareInfo compareInfo = CultureInfo.InvariantCulture.CompareInfo; bool result = false; for (int num = list.Count - 1; num >= 0; num--) { string source = LocalizedName(list[num]); if (compareInfo.IndexOf(source, value, CompareOptions.IgnoreCase | CompareOptions.IgnoreNonSpace) < 0) { Object.Destroy((Object)(GameObject)ElementProperty.GetValue(list[num])); list.RemoveAt(num); result = true; } } return result; } private static void SortByNameDescending(IList list) { List<object> list2 = new List<object>(list.Count); foreach (object item in list) { list2.Add(item); } list2.Sort(delegate(object a, object b) { int num2 = ((bool)CanCraftProperty.GetValue(b)).CompareTo((bool)CanCraftProperty.GetValue(a)); if (num2 == 0) { num2 = Recipe(a).m_listSortWeight.CompareTo(Recipe(b).m_listSortWeight); } if (num2 == 0) { num2 = string.Compare(LocalizedName(b), LocalizedName(a), StringComparison.CurrentCulture); } if (num2 == 0) { num2 = Quality(b).CompareTo(Quality(a)); } return num2; }); for (int num = 0; num < list2.Count; num++) { list[num] = list2[num]; } } private static void Relayout(InventoryGui gui, IList list) { //IL_0015: 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_0033: Unknown result type (might be due to invalid IL or missing references) for (int i = 0; i < list.Count; i++) { ((RectTransform)((GameObject)ElementProperty.GetValue(list[i])).transform).anchoredPosition = new Vector2(0f, (float)i * (0f - gui.m_recipeListSpace)); } float num = (float)BaseSizeField.GetValue(gui); gui.m_recipeListRoot.SetSizeWithCurrentAnchors((Axis)1, Mathf.Max(num, (float)list.Count * gui.m_recipeListSpace)); } private static Recipe Recipe(object pair) { //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Expected O, but got Unknown return (Recipe)RecipeProperty.GetValue(pair); } private static int Quality(object pair) { object? value = ItemDataProperty.GetValue(pair); return ((ItemData)(((value is ItemData) ? value : null)?)).m_quality ?? 0; } private static string LocalizedName(object pair) { string name = Recipe(pair).m_item.m_itemData.m_shared.m_name; if (Localization.instance == null) { return name; } return Localization.instance.Localize(name); } } internal sealed class RecipeListControls { private const float RowHeight = 28f; private const float RowGap = 4f; private const float SortButtonWidth = 120f; private const int MaxQueryLength = 40; private readonly TMP_InputField _input; private readonly TMP_Text _sortLabel; public bool IsTyping { get { if ((Object)(object)_input != (Object)null) { return _input.isFocused; } return false; } } private RecipeListControls(TMP_InputField input, TMP_Text sortLabel) { _input = input; _sortLabel = sortLabel; } public static RecipeListControls Create(InventoryGui gui, Action<string> onQueryChanged, Action onSortClicked) { //IL_0078: 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_0097: Unknown result type (might be due to invalid IL or missing references) //IL_00a1: 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_00c2: 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_00d9: 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_00f5: Unknown result type (might be due to invalid IL or missing references) //IL_013b: Unknown result type (might be due to invalid IL or missing references) //IL_014a: Expected O, but got Unknown Transform parent = ((Transform)gui.m_recipeListRoot).parent; RectTransform val = (RectTransform)(object)((parent is RectTransform) ? parent : null); RectTransform val2 = (RectTransform)(((Object)(object)val != (Object)null) ? /*isinst with value type is only supported in some contexts*/: null); if ((Object)(object)val == (Object)null || (Object)(object)val2 == (Object)null) { Plugin.Log.LogWarning((object)"Nie znaleziono prostokata listy przepisow - wyszukiwarka nie zostanie dodana."); return null; } LogLayout(gui, val); RectTransform component = new GameObject("CraftingSearchRow", new Type[1] { typeof(RectTransform) }).GetComponent<RectTransform>(); ((Transform)component).SetParent((Transform)(object)val2, false); component.anchorMin = new Vector2(val.anchorMin.x, val.anchorMax.y); component.anchorMax = val.anchorMax; component.pivot = new Vector2(0.5f, 1f); component.offsetMin = new Vector2(val.offsetMin.x, val.offsetMax.y - 28f); component.offsetMax = val.offsetMax; ShrinkTop(val, 32f); if ((Object)(object)gui.m_recipeListScroll != (Object)null && (Object)(object)((Component)gui.m_recipeListScroll).transform.parent == (Object)(object)val2) { ShrinkTop((RectTransform)((Component)gui.m_recipeListScroll).transform, 32f); } TMP_FontAsset font = (((Object)(object)gui.m_recipeName != (Object)null) ? gui.m_recipeName.font : null); TMP_InputField obj = CreateInput(component, font); ((UnityEvent<string>)(object)obj.onValueChanged).AddListener((UnityAction<string>)delegate(string text) { onQueryChanged(text); }); TMP_Text sortLabel = CreateSortButton(gui, onSortClicked); return new RecipeListControls(obj, sortLabel); } public void SetSortLabel(string text) { if ((Object)(object)_sortLabel != (Object)null && _sortLabel.text != text) { _sortLabel.text = text; } } public void Clear() { if (!((Object)(object)_input == (Object)null)) { _input.SetTextWithoutNotify(""); _input.DeactivateInputField(false); } } private static void ShrinkTop(RectTransform rect, float amount) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Unknown result type (might be due to invalid IL or missing references) rect.offsetMax = new Vector2(rect.offsetMax.x, rect.offsetMax.y - amount); } private static TMP_InputField CreateInput(RectTransform row, TMP_FontAsset font) { //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Expected O, but got Unknown //IL_002e: 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_0044: Unknown result type (might be due to invalid IL or missing references) //IL_004f: Unknown result type (might be due to invalid IL or missing references) //IL_00c3: 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_00f2: Unknown result type (might be due to invalid IL or missing references) //IL_0109: Unknown result type (might be due to invalid IL or missing references) //IL_0115: Unknown result type (might be due to invalid IL or missing references) //IL_012b: 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_0167: Unknown result type (might be due to invalid IL or missing references) //IL_01a3: Unknown result type (might be due to invalid IL or missing references) //IL_01f9: Unknown result type (might be due to invalid IL or missing references) //IL_0219: Unknown result type (might be due to invalid IL or missing references) GameObject val = new GameObject("RecipeSearch", new Type[1] { typeof(RectTransform) }); RectTransform component = val.GetComponent<RectTransform>(); ((Transform)component).SetParent((Transform)(object)row, false); component.anchorMin = Vector2.zero; component.anchorMax = Vector2.one; component.offsetMin = Vector2.zero; component.offsetMax = Vector2.zero; Image val2 = val.AddComponent<Image>(); Sprite val3 = ((IEnumerable<Sprite>)Resources.FindObjectsOfTypeAll<Sprite>()).FirstOrDefault((Func<Sprite, bool>)((Sprite s) => ((Object)s).name == "text_field")); if ((Object)(object)val3 != (Object)null) { val2.sprite = val3; val2.type = (Type)1; ((Graphic)val2).color = Color.white; } else { ((Graphic)val2).color = new Color(0f, 0f, 0f, 0.6f); } RectTransform component2 = new GameObject("TextArea", new Type[2] { typeof(RectTransform), typeof(RectMask2D) }).GetComponent<RectTransform>(); ((Transform)component2).SetParent((Transform)(object)component, false); component2.anchorMin = Vector2.zero; component2.anchorMax = Vector2.one; component2.offsetMin = new Vector2(8f, 2f); component2.offsetMax = new Vector2(-8f, -2f); TextMeshProUGUI val4 = CreateText(component2, "Placeholder", font, new Color(0.8529f, 0.725f, 0.5331f, 0.5f)); ((TMP_Text)val4).text = "Search recipes..."; ((TMP_Text)val4).fontStyle = (FontStyles)2; TextMeshProUGUI textComponent = CreateText(component2, "Text", font, new Color(0.8529f, 0.725f, 0.5331f, 1f)); TMP_InputField val5 = val.AddComponent<TMP_InputField>(); val5.textViewport = component2; val5.textComponent = (TMP_Text)(object)textComponent; val5.placeholder = (Graphic)(object)val4; val5.characterLimit = 40; val5.lineType = (LineType)0; val5.caretColor = new Color(1f, 0.631f, 0.235f, 1f); val5.selectionColor = new Color(1f, 0.631f, 0.235f, 0.35f); if ((Object)(object)font != (Object)null) { val5.fontAsset = font; } val5.pointSize = 16f; return val5; } private static TextMeshProUGUI CreateText(RectTransform parent, string name, TMP_FontAsset font, Color color) { //IL_0014: 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_0032: 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_0048: Unknown result type (might be due to invalid IL or missing references) //IL_0079: Unknown result type (might be due to invalid IL or missing references) RectTransform component = new GameObject(name, new Type[1] { typeof(RectTransform) }).GetComponent<RectTransform>(); ((Transform)component).SetParent((Transform)(object)parent, false); component.anchorMin = Vector2.zero; component.anchorMax = Vector2.one; component.offsetMin = Vector2.zero; component.offsetMax = Vector2.zero; TextMeshProUGUI val = ((Component)component).gameObject.AddComponent<TextMeshProUGUI>(); if ((Object)(object)font != (Object)null) { ((TMP_Text)val).font = font; } ((TMP_Text)val).fontSize = 16f; ((Graphic)val).color = color; ((TMP_Text)val).alignment = (TextAlignmentOptions)513; ((TMP_Text)val).textWrappingMode = (TextWrappingModes)0; ((TMP_Text)val).overflowMode = (TextOverflowModes)1; return val; } private static TMP_Text CreateSortButton(InventoryGui gui, Action onSortClicked) { //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Expected O, but got Unknown //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Expected O, but got Unknown //IL_007a: Unknown result type (might be due to invalid IL or missing references) //IL_0084: Unknown result type (might be due to invalid IL or missing references) //IL_0095: Unknown result type (might be due to invalid IL or missing references) //IL_009f: Unknown result type (might be due to invalid IL or missing references) //IL_00b0: Unknown result type (might be due to invalid IL or missing references) //IL_00ba: Unknown result type (might be due to invalid IL or missing references) //IL_00cb: 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_00d9: Unknown result type (might be due to invalid IL or missing references) //IL_00ef: Unknown result type (might be due to invalid IL or missing references) //IL_00f9: Expected O, but got Unknown //IL_00f4: 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_0106: Unknown result type (might be due to invalid IL or missing references) //IL_010b: Unknown result type (might be due to invalid IL or missing references) //IL_011c: Unknown result type (might be due to invalid IL or missing references) //IL_0126: 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_0157: Expected O, but got Unknown //IL_016d: Unknown result type (might be due to invalid IL or missing references) //IL_0174: Expected O, but got Unknown RectTransform val = (RectTransform)((Component)gui.m_tabUpgrade).transform; RectTransform val2 = (RectTransform)((Transform)val).parent; GameObject val3 = Object.Instantiate<GameObject>(((Component)gui.m_stackAllButton).gameObject, (Transform)(object)val2); ((Object)val3).name = "CraftingSortButton"; Localize[] componentsInChildren = val3.GetComponentsInChildren<Localize>(true); for (int i = 0; i < componentsInChildren.Length; i++) { Object.DestroyImmediate((Object)(object)componentsInChildren[i]); } RectTransform component = val3.GetComponent<RectTransform>(); component.anchorMin = new Vector2(0f, val.anchorMin.y); component.anchorMax = new Vector2(0f, val.anchorMax.y); component.pivot = new Vector2(1f, val.pivot.y); Rect rect = val.rect; component.sizeDelta = new Vector2(120f, ((Rect)(ref rect)).height); float x = ((Transform)val2).InverseTransformPoint(RightEdge((RectTransform)((Component)gui.m_craftButton).transform)).x; rect = val2.rect; float xMin = ((Rect)(ref rect)).xMin; component.anchoredPosition = new Vector2(x - xMin, val.anchoredPosition.y); Button component2 = val3.GetComponent<Button>(); ((UnityEventBase)component2.onClick).RemoveAllListeners(); ((UnityEvent)component2.onClick).AddListener((UnityAction)delegate { onSortClicked(); }); foreach (Transform item in val3.transform) { Transform val4 = item; if (((Object)val4).name.StartsWith("gamepad_hint", StringComparison.Ordinal)) { ((Component)val4).gameObject.SetActive(false); } } return val3.GetComponentInChildren<TMP_Text>(); } private static Vector3 RightEdge(RectTransform rect) { //IL_0010: 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_0026: Unknown result type (might be due to invalid IL or missing references) Vector3[] array = (Vector3[])(object)new Vector3[4]; rect.GetWorldCorners(array); return (array[2] + array[3]) * 0.5f; } private static void LogLayout(InventoryGui gui, RectTransform list) { //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_0046: Unknown result type (might be due to invalid IL or missing references) //IL_0054: 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_0067: 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) ManualLogSource log = Plugin.Log; object[] obj = new object[7] { ((Object)list).name, ((Object)((Transform)list).parent).name, list.anchorMin, list.anchorMax, list.offsetMin, list.offsetMax, null }; Rect rect = list.rect; obj[6] = ((Rect)(ref rect)).size; log.LogInfo((object)(string.Format("Lista przepisow: '{0}' w '{1}', anchor {2}-{3}, offset {4}/{5}, rozmiar {6}; ", obj) + "scroll: '" + (((Object)(object)gui.m_recipeListScroll != (Object)null) ? ((Object)((Component)gui.m_recipeListScroll).transform.parent).name : "-") + "'")); } } }