using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Linq.Expressions; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Versioning; using System.Text.RegularExpressions; using BepInEx; using BepInEx.Bootstrap; using BepInEx.Configuration; using HarmonyLib; using UnityEngine; using UnityEngine.UI; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: AssemblyTitle("PinRecipe")] [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("")] [assembly: AssemblyProduct("PinRecipe")] [assembly: AssemblyCopyright("Copyright © 2025")] [assembly: AssemblyTrademark("")] [assembly: ComVisible(false)] [assembly: Guid("b7fff297-caca-412c-8cb0-52556a76bd3f")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")] [assembly: AssemblyVersion("1.0.0.0")] namespace ValheimRecipePinner; public class ContainerScanner { public static List AllContainers = new List(); private static readonly HashSet _containerSet = new HashSet(); internal static readonly object ContainerLock = new object(); public Dictionary ContainerCache = new Dictionary(); private static readonly HashSet _processedIDs = new HashSet(); private readonly List _snapshotBuffer = new List(); private Vector3 _lastScanPos; private int _lastItemCount; private float _scanTimer; private float _moveScanCooldown; private const float MovementThresholdSqr = 4f; private const float MinMoveScanCooldown = 1f; public void InitializeContainers() { if (!RecipePinnerPlugin.EnableChestScanning.Value) { return; } DebugLogger.Log("Init containers"); lock (ContainerLock) { if (AllContainers.Count != 0) { return; } Container[] array = Object.FindObjectsByType((FindObjectsSortMode)0); foreach (Container val in array) { if ((Object)(object)val != (Object)null && _containerSet.Add(val)) { AllContainers.Add(val); if ((Object)(object)((Component)val).GetComponent() == (Object)null) { ((Component)val).gameObject.AddComponent().MyContainer = val; } } } DebugLogger.Log($"Tracking {AllContainers.Count} containers"); } } public void UpdateScanning() { //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)Player.m_localPlayer == (Object)null) { return; } _scanTimer += Time.deltaTime; _moveScanCooldown += Time.deltaTime; bool flag = Vector3.SqrMagnitude(((Component)Player.m_localPlayer).transform.position - _lastScanPos) > 4f && _moveScanCooldown >= 1f; int num = 0; foreach (ItemData allItem in ((Humanoid)Player.m_localPlayer).GetInventory().GetAllItems()) { num += allItem.m_stack; } bool flag2 = num != _lastItemCount; bool flag3 = false; if ((Object)(object)InventoryGui.instance != (Object)null) { flag3 = (Object)(object)ReflectionHelper.GetCurrentContainer(InventoryGui.instance) != (Object)null; } float num2 = (flag3 ? 0.5f : RecipePinnerPlugin.ChestScanInterval.Value); bool flag4 = _scanTimer >= num2; if (flag || flag2 || flag4) { DebugLogger.Verbose($"Scanning containers - Moved: {flag}, InvChanged: {flag2}, Interval: {flag4}"); _scanTimer = 0f; if (flag) { _moveScanCooldown = 0f; } _lastItemCount = num; UpdateContainerCache(); } } private void UpdateContainerCache() { //IL_002d: 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_01ed: Unknown result type (might be due to invalid IL or missing references) //IL_01ee: Unknown result type (might be due to invalid IL or missing references) //IL_00f1: Unknown result type (might be due to invalid IL or missing references) //IL_00f6: Unknown result type (might be due to invalid IL or missing references) //IL_00f7: Unknown result type (might be due to invalid IL or missing references) ContainerCache.Clear(); if ((Object)(object)Player.m_localPlayer == (Object)null) { DebugLogger.Verbose("Cannot scan - player is null"); return; } Vector3 position = ((Component)Player.m_localPlayer).transform.position; float value = RecipePinnerPlugin.ChestScanRange.Value; float num = value * value; _snapshotBuffer.Clear(); lock (ContainerLock) { _snapshotBuffer.AddRange(AllContainers); } _processedIDs.Clear(); int num2 = 0; int num3 = 0; int num4 = 0; foreach (Container item in _snapshotBuffer) { if ((Object)(object)item == (Object)null || (Object)(object)((Component)item).transform == (Object)null) { num3++; continue; } int instanceID = ((Object)item).GetInstanceID(); if (!_processedIDs.Add(instanceID)) { num3++; continue; } if (Vector3.SqrMagnitude(((Component)item).transform.position - position) > num) { num3++; continue; } bool flag = true; if (ReflectionHelper.CheckContainerAccess != null) { flag = ReflectionHelper.CheckContainerAccess(item, Player.m_localPlayer.GetPlayerID()); } if (!flag) { num4++; continue; } Inventory inventory = item.GetInventory(); if (inventory == null) { continue; } foreach (ItemData allItem in inventory.GetAllItems()) { string name = allItem.m_shared.m_name; if (ContainerCache.TryGetValue(name, out var value2)) { ContainerCache[name] = value2 + allItem.m_stack; } else { ContainerCache[name] = allItem.m_stack; } } num2++; } _lastScanPos = position; DebugLogger.Verbose($"Container scan complete - Scanned: {num2}, Skipped: {num3}, AccessDenied: {num4}, UniqueItems: {ContainerCache.Count}"); } [HarmonyPatch(typeof(Container), "Awake")] [HarmonyPostfix] public static void TrackContainerAwake(Container __instance) { if ((Object)(object)__instance == (Object)null || RecipePinnerPlugin.EnableChestScanning == null || !RecipePinnerPlugin.EnableChestScanning.Value) { return; } lock (ContainerLock) { if (_containerSet.Add(__instance)) { AllContainers.Add(__instance); (((Component)__instance).gameObject.GetComponent() ?? ((Component)__instance).gameObject.AddComponent()).MyContainer = __instance; DebugLogger.Verbose($"New container tracked: {((Object)__instance).name} (Total: {AllContainers.Count})"); } } } public static void RemoveFromSet(Container c) { _containerSet.Remove(c); } } public class ContainerTracker : MonoBehaviour { public Container MyContainer; private void OnDestroy() { if (ContainerScanner.AllContainers != null && (Object)(object)MyContainer != (Object)null && RecipePinnerPlugin.EnableChestScanning != null && RecipePinnerPlugin.EnableChestScanning.Value) { lock (ContainerScanner.ContainerLock) { ContainerScanner.AllContainers.Remove(MyContainer); ContainerScanner.RemoveFromSet(MyContainer); DebugLogger.Verbose($"Container removed: {((Object)MyContainer).name} (Remaining: {ContainerScanner.AllContainers.Count})"); } } } } public class DataPersistence { public void SavePins() { try { string savePath = GetSavePath(); if (string.IsNullOrEmpty(savePath)) { DebugLogger.Warning("Cannot save - save path is invalid"); return; } RecipeManager recipeMgr = RecipePinnerPlugin.Instance.RecipeMgr; List list = new List(); foreach (KeyValuePair pinnedRecipe in recipeMgr.PinnedRecipes) { list.Add($"{pinnedRecipe.Key}:{pinnedRecipe.Value}"); } File.WriteAllLines(savePath, list); DebugLogger.Log($"Saved {list.Count} pinned recipes to: {savePath}"); } catch (Exception ex) { DebugLogger.Error("Failed to save pins", ex); } } public void LoadPins() { string savePath = GetSavePath(); if (string.IsNullOrEmpty(savePath)) { DebugLogger.Warning("Cannot load - save path is invalid"); return; } RecipeManager recipeMgr = RecipePinnerPlugin.Instance.RecipeMgr; if (!File.Exists(savePath)) { DebugLogger.Log("No save file found at: " + savePath); return; } try { recipeMgr.PinnedRecipes.Clear(); string[] array = File.ReadAllLines(savePath); int num = 0; int num2 = 0; string[] array2 = array; foreach (string text in array2) { if (string.IsNullOrWhiteSpace(text)) { continue; } int num3 = text.LastIndexOf(':'); if (num3 > 0 && num3 < text.Length - 1) { string key = text.Substring(0, num3).Trim(); if (int.TryParse(text.Substring(num3 + 1).Trim(), out var result)) { recipeMgr.PinnedRecipes[key] = result; num++; } else { DebugLogger.Warning("Invalid count value in save file: " + text); num2++; } } else if (!recipeMgr.PinnedRecipes.ContainsKey(text)) { recipeMgr.PinnedRecipes[text] = 1; num++; } } if (recipeMgr.PinnedRecipes.Count > RecipePinnerPlugin.MaximumPins.Value) { int count = recipeMgr.PinnedRecipes.Count; Dictionary dictionary = new Dictionary(); int num4 = 0; foreach (KeyValuePair pinnedRecipe in recipeMgr.PinnedRecipes) { if (num4 < RecipePinnerPlugin.MaximumPins.Value) { dictionary[pinnedRecipe.Key] = pinnedRecipe.Value; num4++; continue; } break; } recipeMgr.PinnedRecipes = dictionary; DebugLogger.Warning($"Exceeded max pins limit - trimmed from {count} to {recipeMgr.PinnedRecipes.Count}"); } DebugLogger.Log($"Loaded {num} recipes from: {savePath} (Errors: {num2})"); } catch (Exception ex) { DebugLogger.Error("Failed to load pins", ex); } } private string GetSavePath() { if ((Object)(object)Player.m_localPlayer == (Object)null) { DebugLogger.Verbose("Cannot get save path - local player is null"); return null; } string playerName = Player.m_localPlayer.GetPlayerName(); if (string.IsNullOrWhiteSpace(playerName)) { DebugLogger.Warning("Cannot get save path - player name is empty"); return null; } string text = Path.Combine(Paths.ConfigPath, "RecipePinner_Data"); if (!Directory.Exists(text)) { try { Directory.CreateDirectory(text); DebugLogger.Log("Created save directory: " + text); } catch (Exception ex) { DebugLogger.Error("Failed to create save directory: " + text, ex); return null; } } string text2 = playerName; char[] invalidFileNameChars = Path.GetInvalidFileNameChars(); foreach (char oldChar in invalidFileNameChars) { text2 = text2.Replace(oldChar, '_'); } string text3 = Path.Combine(text, text2 + ".txt"); DebugLogger.Verbose("Save path: " + text3); return text3; } } public static class DebugLogger { private const string Prefix = "[RecipePinner]"; public static void Log(string message) { if (IsDebugEnabled()) { Debug.Log((object)("[RecipePinner] " + message)); } } public static void Warning(string message) { Debug.LogWarning((object)("[RecipePinner] " + message)); } public static void Error(string message) { Debug.LogError((object)("[RecipePinner] " + message)); } public static void Error(string message, Exception ex) { Debug.LogError((object)("[RecipePinner] " + message + "\nException: " + ex.Message + "\nStackTrace: " + ex.StackTrace)); } public static void Verbose(string message) { if (IsDebugEnabled()) { Debug.Log((object)("[RecipePinner] [VERBOSE] " + message)); } } private static bool IsDebugEnabled() { if ((Object)(object)RecipePinnerPlugin.Instance != (Object)null && RecipePinnerPlugin.EnableDebugLogging != null) { return RecipePinnerPlugin.EnableDebugLogging.Value; } return false; } } public class LocalizationManager { private readonly RecipePinnerPlugin _plugin; private readonly Dictionary _localizedText = new Dictionary(); private static readonly Dictionary _defaultEnglish = new Dictionary { { "pinned", "Recipe Pinned!" }, { "unpinned", "Pin Removed" }, { "list_full", "List Full!" }, { "added_more", "Added More: {0}x" }, { "decreased", "Decreased: {0}x" }, { "cleared", "Pinned Recipes Cleared" }, { "max_level", "Max Level Reached" }, { "no_upgrade_cost", "No upgrade cost found" }, { "gathering_title", "GATHERING LIST" }, { "gathering_opened", "Gathering List Opened" }, { "gathering_closed", "Gathering List Closed" }, { "gathering_empty", "No Recipes Pinned" }, { "gathering_hint", "Open/Close: {0}" } }; public LocalizationManager(RecipePinnerPlugin plugin) { _plugin = plugin; DebugLogger.Log("LocalizationManager init"); } public void LoadTranslations() { _localizedText.Clear(); string text = RecipePinnerPlugin.LanguageOverride.Value.Trim(); if (string.IsNullOrEmpty(text) || text.ToLower() == "auto") { text = ((Localization.instance == null) ? "English" : Localization.instance.GetSelectedLanguage()); DebugLogger.Log("Auto-detected language: " + text); } else { DebugLogger.Log("Using forced language: " + text); } string text2 = Path.Combine(Path.GetDirectoryName(((BaseUnityPlugin)_plugin).Info.Location), "RecipePinner_languages", text + ".json"); if (!File.Exists(text2)) { DebugLogger.Log("Language file not found: " + text2 + " - Using default English"); return; } try { string text3 = File.ReadAllText(text2); int num = 0; string[] array = text3.Split(new char[1] { '\n' }); for (int i = 0; i < array.Length; i++) { string text4 = array[i].Trim(); if (string.IsNullOrEmpty(text4) || text4 == "{" || text4 == "}" || !text4.Contains(":")) { continue; } string[] array2 = text4.Split(new char[1] { ':' }, 2); if (array2.Length == 2) { string text5 = array2[0].Trim(',', '"', ' ', '\t', '\r'); string value = array2[1].Trim(',', '"', ' ', '\t', '\r'); if (!string.IsNullOrEmpty(text5) && !string.IsNullOrEmpty(value)) { _localizedText[text5] = value; num++; } } } DebugLogger.Log($"Loaded {num} translations from: {text}.json"); } catch (Exception ex) { DebugLogger.Error("Failed to load language file: " + text2, ex); } } public string GetText(string key) { if (_localizedText.TryGetValue(key, out var value)) { DebugLogger.Verbose("Translation found for '" + key + "': " + value); return value; } if (_defaultEnglish.TryGetValue(key, out var value2)) { DebugLogger.Verbose("Using default English for '" + key + "': " + value2); return value2; } DebugLogger.Warning("No translation found for key: " + key); return key; } } public class PinnedRecipeData { public Recipe RecipeRef; public string RawName; public string CachedHeader; public Sprite Icon; public int StackCount; public List Resources = new List(); public bool IsDirty = true; } public class PinnedResData { public string ItemName; public string CachedName; public Sprite Icon; public int RequiredAmount; public int LastKnownAmount; public int LastKnownInvAmount; public string CachedAmountString; } public class RecipeManager { public Dictionary PinnedRecipes = new Dictionary(); public List CachedPins = new List(); private readonly Dictionary _fakeRecipeCache = new Dictionary(); private static readonly Regex CleanNameRegex = new Regex("<.*?>", RegexOptions.Compiled); private static readonly Regex AmountSuffixRegex = new Regex("\\s*[xX]?\\s*\\d+$", RegexOptions.Compiled); private static readonly Regex UpgradeStarRegex = new Regex("\\s*★(\\d+)$", RegexOptions.Compiled); private static readonly Dictionary _cachedRecipeFields = new Dictionary(); private static readonly Dictionary _cachedRecipeProps = new Dictionary(); private static readonly Dictionary _cachedItemFields = new Dictionary(); private static readonly Dictionary _cachedItemProps = new Dictionary(); public void Cleanup() { DebugLogger.Log("RecipeManager cleanup"); int count = _fakeRecipeCache.Count; foreach (Recipe value in _fakeRecipeCache.Values) { if ((Object)(object)value != (Object)null) { Object.Destroy((Object)(object)value); } } _fakeRecipeCache.Clear(); DebugLogger.Log($"Cleaned {count} fake recipes"); _cachedRecipeFields.Clear(); _cachedRecipeProps.Clear(); _cachedItemFields.Clear(); _cachedItemProps.Clear(); } public void RefreshRecipeCache() { DebugLogger.Verbose("Refreshing cache"); CachedPins.Clear(); if ((Object)(object)ObjectDB.instance == (Object)null) { DebugLogger.Warning("ObjectDB null, can't refresh"); return; } int num = 0; int num2 = 0; foreach (KeyValuePair pinnedRecipe in PinnedRecipes) { string key = pinnedRecipe.Key; int value = pinnedRecipe.Value; Recipe recipeByName = GetRecipeByName(key); if ((Object)(object)recipeByName != (Object)null) { PinnedRecipeData pinnedRecipeData = new PinnedRecipeData { IsDirty = true, RecipeRef = recipeByName, StackCount = value }; if ((Object)(object)recipeByName.m_item != (Object)null) { pinnedRecipeData.Icon = recipeByName.m_item.m_itemData.GetIcon(); pinnedRecipeData.RawName = recipeByName.m_item.m_itemData.m_shared.m_name; } else { ZNetScene instance = ZNetScene.instance; GameObject val = ((instance != null) ? instance.GetPrefab(((Object)recipeByName).name) : null); if ((Object)(object)val != (Object)null) { Piece component = val.GetComponent(); if ((Object)(object)component != (Object)null) { pinnedRecipeData.Icon = component.m_icon; pinnedRecipeData.RawName = component.m_name; } } } if (string.IsNullOrEmpty(pinnedRecipeData.RawName)) { pinnedRecipeData.RawName = ((Object)recipeByName).name; } string text = pinnedRecipeData.RawName; if (Localization.instance != null) { Match match = UpgradeStarRegex.Match(key); text = ((!match.Success) ? Localization.instance.Localize(pinnedRecipeData.RawName) : (Localization.instance.Localize(pinnedRecipeData.RawName) + match.Value)); } text = text.Replace("\r", "").Replace("\n", ""); if (recipeByName.m_amount > 1) { text += $" (x{recipeByName.m_amount})"; } if (value > 1) { text = $"{value}x {text}"; } pinnedRecipeData.CachedHeader = text; Requirement[] resources = recipeByName.m_resources; foreach (Requirement val2 in resources) { if (val2 != null && !((Object)(object)val2.m_resItem == (Object)null) && val2.m_amount > 0) { PinnedResData pinnedResData = new PinnedResData { ItemName = val2.m_resItem.m_itemData.m_shared.m_name, Icon = val2.m_resItem.m_itemData.GetIcon(), RequiredAmount = val2.m_amount * value, LastKnownAmount = -1, LastKnownInvAmount = -1 }; string text2 = pinnedResData.ItemName; if (Localization.instance != null) { text2 = Localization.instance.Localize(pinnedResData.ItemName); } text2 = text2.Replace("\r", "").Replace("\n", ""); pinnedResData.CachedName = text2; pinnedRecipeData.Resources.Add(pinnedResData); } } CachedPins.Add(pinnedRecipeData); num++; } else { DebugLogger.Warning("Recipe not found: " + key); num2++; } } DebugLogger.Log($"Cache refreshed: {num} ok, {num2} failed"); if ((Object)(object)Player.m_localPlayer != (Object)null && (Object)(object)RecipePinnerPlugin.Instance != (Object)null) { RecipePinnerPlugin.Instance.UIMgr.UpdateUI(isVisible: true); } } public Recipe GetRecipeByName(string name) { if ((Object)(object)ObjectDB.instance == (Object)null) { return null; } if (_fakeRecipeCache.TryGetValue(name, out var value)) { DebugLogger.Verbose("Found cached fake recipe: " + name); return value; } Match match = UpgradeStarRegex.Match(name); if (match.Success) { string name2 = name.Substring(0, match.Index).Trim(); int targetLevel = int.Parse(match.Groups[1].Value); Recipe recipeByName = GetRecipeByName(name2); if ((Object)(object)recipeByName != (Object)null) { Recipe val = CreateFakeUpgradeRecipe(recipeByName, targetLevel, name); if ((Object)(object)val != (Object)null) { return val; } } } GameObject itemPrefab = ObjectDB.instance.GetItemPrefab(name); ItemDrop val2 = ((itemPrefab != null) ? itemPrefab.GetComponent() : null); if ((Object)(object)val2 != (Object)null) { Recipe recipe = ObjectDB.instance.GetRecipe(val2.m_itemData); if ((Object)(object)recipe != (Object)null) { DebugLogger.Verbose("Found standard recipe: " + name); return recipe; } } Recipe val3 = null; foreach (Recipe recipe2 in ObjectDB.instance.m_recipes) { if (((Object)recipe2).name == name) { val3 = recipe2; break; } } if ((Object)(object)val3 != (Object)null) { DebugLogger.Verbose("Found recipe in ObjectDB: " + name); return val3; } ZNetScene instance = ZNetScene.instance; GameObject val4 = ((instance != null) ? instance.GetPrefab(name) : null); if ((Object)(object)val4 != (Object)null) { Piece component = val4.GetComponent(); if ((Object)(object)component != (Object)null && component.m_resources != null && component.m_resources.Length != 0) { Recipe val5 = ScriptableObject.CreateInstance(); ((Object)val5).hideFlags = (HideFlags)61; ((Object)val5).name = name; val5.m_item = val4.GetComponent(); val5.m_resources = (Requirement[])component.m_resources.Clone(); _fakeRecipeCache[name] = val5; DebugLogger.Verbose("Created fake recipe for piece: " + name); return val5; } } DebugLogger.Warning("Recipe not found anywhere: " + name); return null; } private Recipe CreateFakeUpgradeRecipe(Recipe baseRecipe, int targetLevel, string customName) { //IL_005f: Unknown result type (might be due to invalid IL or missing references) //IL_0064: 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_0080: 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_0096: Expected O, but got Unknown if ((Object)(object)baseRecipe == (Object)null) { return null; } Recipe val = ScriptableObject.CreateInstance(); ((Object)val).hideFlags = (HideFlags)61; ((Object)val).name = customName; val.m_item = baseRecipe.m_item; val.m_amount = 1; int num = Mathf.Max(1, targetLevel - 1); List list = new List(); Requirement[] resources = baseRecipe.m_resources; foreach (Requirement val2 in resources) { if (val2.m_amountPerLevel > 0) { Requirement item = new Requirement { m_resItem = val2.m_resItem, m_amount = val2.m_amountPerLevel * num, m_amountPerLevel = 0, m_recover = val2.m_recover }; list.Add(item); } } if (list.Count == 0) { Object.Destroy((Object)(object)val); return null; } val.m_resources = list.ToArray(); _fakeRecipeCache[customName] = val; DebugLogger.Verbose("Created fake upgrade recipe: " + customName); return val; } public void ValidateAndCleanPins() { if ((Object)(object)ObjectDB.instance == (Object)null) { DebugLogger.Warning("Cannot validate pins - ObjectDB.instance is null"); return; } DebugLogger.Log("Validating pins"); List list = new List(); foreach (string key in PinnedRecipes.Keys) { if ((Object)(object)GetRecipeByName(key) == (Object)null) { list.Add(key); } } if (list.Count > 0) { foreach (string item in list) { PinnedRecipes.Remove(item); DebugLogger.Warning("Removed invalid recipe: " + item); } RecipePinnerPlugin.Instance?.DataMgr.SavePins(); DebugLogger.Log($"Removed {list.Count} invalid pins"); } else { DebugLogger.Log("All pins valid"); } } public void TryPinHoveredRecipe(InventoryGui gui) { //IL_005e: Unknown result type (might be due to invalid IL or missing references) //IL_0065: Expected O, but got Unknown DebugLogger.Verbose("Attempting to pin hovered recipe..."); Transform recipeListRoot = ReflectionHelper.GetRecipeListRoot(gui); if (!(ReflectionHelper.GetAvailableRecipes(gui) is IList list) || (Object)(object)recipeListRoot == (Object)null) { DebugLogger.Verbose("Cannot pin - listRoot or availableRecipes is null"); return; } ScrollRect componentInParent = ((Component)recipeListRoot).GetComponentInParent(); bool flag = !((Selectable)gui.m_tabUpgrade).interactable; foreach (Transform item in recipeListRoot) { Transform val = item; if (!((Component)val).gameObject.activeInHierarchy) { continue; } RectTransform val2 = (RectTransform)(object)((val is RectTransform) ? val : null); if ((Object)(object)val2 == (Object)null || !IsVisibleInScroll(val2, componentInParent) || !InputHelper.IsMouseOverRect(val2)) { continue; } string text = ExtractTextFromUI(val); if (string.IsNullOrEmpty(text)) { continue; } string text2 = CleanNameRegex.Replace(text, string.Empty).Trim(); text2 = text2.Replace("\r", "").Replace("\n", ""); string text3 = AmountSuffixRegex.Replace(text2, "").Trim(); DebugLogger.Verbose($"Hovered: '{text3}' (UpgradeTab: {flag})"); foreach (object item2 in list) { Recipe recipeFromObject = GetRecipeFromObject(item2); if (!((Object)(object)recipeFromObject != (Object)null)) { continue; } string rawRecipeName = GetRawRecipeName(recipeFromObject); if (string.IsNullOrEmpty(rawRecipeName)) { continue; } string text4 = rawRecipeName; if (Localization.instance != null) { text4 = Localization.instance.Localize(rawRecipeName); } text4 = text4.Replace("\r", "").Replace("\n", ""); if (!text4.Equals(text3, StringComparison.OrdinalIgnoreCase) && !text4.Equals(text2, StringComparison.OrdinalIgnoreCase)) { continue; } if (flag) { ItemData val3 = GetItemDataFromObject(item2) ?? ReflectionHelper.GetCraftUpgradeItem(gui); if (val3 != null) { int quality = val3.m_quality; int num = quality + 1; int maxQuality = val3.m_shared.m_maxQuality; if (quality >= maxQuality) { string text5 = RecipePinnerPlugin.Instance.LocalizationMgr.GetText("max_level"); Player localPlayer = Player.m_localPlayer; if (localPlayer != null) { ((Character)localPlayer).Message((MessageType)2, text5, 0, (Sprite)null); } return; } string name = ((Object)recipeFromObject.m_item).name; string text6 = $"{name} ★{num}"; DebugLogger.Log("Attempting to pin upgrade: " + text6 + " (Base: " + name + ")"); if ((Object)(object)GetRecipeByName(text6) != (Object)null) { TogglePin(text6); return; } string text7 = RecipePinnerPlugin.Instance.LocalizationMgr.GetText("no_upgrade_cost"); Player localPlayer2 = Player.m_localPlayer; if (localPlayer2 != null) { ((Character)localPlayer2).Message((MessageType)2, text7, 0, (Sprite)null); } } else { DebugLogger.Warning("Matched name but could not get ItemData for upgrade."); } } else { DebugLogger.Log("Matched recipe: " + ((Object)recipeFromObject).name); TogglePin(((Object)recipeFromObject).name); } return; } } } public void TryPinHoveredPiece() { DebugLogger.Verbose("Attempting to pin hovered piece..."); if (!((Object)(object)Hud.instance == (Object)null)) { Piece hoveredPiece = ReflectionHelper.GetHoveredPiece(Hud.instance); if ((Object)(object)hoveredPiece != (Object)null && hoveredPiece.m_resources != null && hoveredPiece.m_resources.Length != 0) { DebugLogger.Log("Pinning piece: " + ((Object)hoveredPiece).name); TogglePin(((Object)hoveredPiece).name); } else { DebugLogger.Verbose("No valid piece to pin (Mouse must be over a recipe icon)"); } } } private void TogglePin(string recipeName) { bool flag = Input.GetKey((KeyCode)304) || Input.GetKey((KeyCode)303); LocalizationManager localizationMgr = RecipePinnerPlugin.Instance.LocalizationMgr; if (PinnedRecipes.TryGetValue(recipeName, out var value)) { if (flag) { value--; if (value <= 0) { PinnedRecipes.Remove(recipeName); Player localPlayer = Player.m_localPlayer; if (localPlayer != null) { ((Character)localPlayer).Message((MessageType)2, localizationMgr.GetText("unpinned"), 0, (Sprite)null); } DebugLogger.Log("Unpinned: " + recipeName); } else { PinnedRecipes[recipeName] = value; string text = string.Format(localizationMgr.GetText("decreased"), value); Player localPlayer2 = Player.m_localPlayer; if (localPlayer2 != null) { ((Character)localPlayer2).Message((MessageType)2, text, 0, (Sprite)null); } DebugLogger.Log($"Decreased pin count: {recipeName} = {value}"); } } else { value++; PinnedRecipes[recipeName] = value; string text2 = string.Format(localizationMgr.GetText("added_more"), value); Player localPlayer3 = Player.m_localPlayer; if (localPlayer3 != null) { ((Character)localPlayer3).Message((MessageType)2, text2, 0, (Sprite)null); } DebugLogger.Log($"Increased pin count: {recipeName} = {value}"); } } else { if (flag) { return; } if (PinnedRecipes.Count < RecipePinnerPlugin.MaximumPins.Value) { PinnedRecipes.Add(recipeName, 1); Player localPlayer4 = Player.m_localPlayer; if (localPlayer4 != null) { ((Character)localPlayer4).Message((MessageType)2, localizationMgr.GetText("pinned"), 0, (Sprite)null); } DebugLogger.Log("Pinned new recipe: " + recipeName); } else { Player localPlayer5 = Player.m_localPlayer; if (localPlayer5 != null) { ((Character)localPlayer5).Message((MessageType)2, localizationMgr.GetText("list_full"), 0, (Sprite)null); } DebugLogger.Warning($"Cannot pin {recipeName} - max pins reached ({RecipePinnerPlugin.MaximumPins.Value})"); } } RefreshRecipeCache(); } private Recipe GetRecipeFromObject(object data) { if (data == null) { return null; } Recipe val = (Recipe)((data is Recipe) ? data : null); if (val != null) { return val; } Type type = data.GetType(); if (_cachedRecipeFields.TryGetValue(type, out var value)) { object? value2 = value.GetValue(data); return (Recipe)((value2 is Recipe) ? value2 : null); } if (_cachedRecipeProps.TryGetValue(type, out var value3)) { object? value4 = value3.GetValue(data, null); return (Recipe)((value4 is Recipe) ? value4 : null); } PropertyInfo property = type.GetProperty("Key"); if (property != null) { object? value5 = property.GetValue(data, null); Recipe val2 = (Recipe)((value5 is Recipe) ? value5 : null); if (val2 != null) { _cachedRecipeProps[type] = property; return val2; } } FieldInfo field = type.GetField("m_recipe", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (field != null) { object? value6 = field.GetValue(data); Recipe val3 = (Recipe)((value6 is Recipe) ? value6 : null); if (val3 != null) { _cachedRecipeFields[type] = field; return val3; } } FieldInfo[] fields = type.GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); foreach (FieldInfo fieldInfo in fields) { if (fieldInfo.FieldType == typeof(Recipe)) { _cachedRecipeFields[type] = fieldInfo; object? value7 = fieldInfo.GetValue(data); return (Recipe)((value7 is Recipe) ? value7 : null); } } PropertyInfo[] properties = type.GetProperties(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); foreach (PropertyInfo propertyInfo in properties) { if (propertyInfo.PropertyType == typeof(Recipe) && propertyInfo.CanRead) { _cachedRecipeProps[type] = propertyInfo; object? value8 = propertyInfo.GetValue(data, null); return (Recipe)((value8 is Recipe) ? value8 : null); } } return null; } private ItemData GetItemDataFromObject(object data) { if (data == null) { return null; } Type type = data.GetType(); if (_cachedItemFields.TryGetValue(type, out var value)) { object? value2 = value.GetValue(data); return (ItemData)((value2 is ItemData) ? value2 : null); } if (_cachedItemProps.TryGetValue(type, out var value3)) { object? value4 = value3.GetValue(data, null); return (ItemData)((value4 is ItemData) ? value4 : null); } PropertyInfo property = type.GetProperty("Value"); if (property != null) { object? value5 = property.GetValue(data, null); ItemData val = (ItemData)((value5 is ItemData) ? value5 : null); if (val != null) { _cachedItemProps[type] = property; return val; } } PropertyInfo property2 = type.GetProperty("Item2"); if (property2 != null) { object? value6 = property2.GetValue(data, null); ItemData val2 = (ItemData)((value6 is ItemData) ? value6 : null); if (val2 != null) { _cachedItemProps[type] = property2; return val2; } } FieldInfo[] fields = type.GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); foreach (FieldInfo fieldInfo in fields) { if (fieldInfo.FieldType == typeof(ItemData)) { _cachedItemFields[type] = fieldInfo; object? value7 = fieldInfo.GetValue(data); return (ItemData)((value7 is ItemData) ? value7 : null); } } PropertyInfo[] properties = type.GetProperties(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); foreach (PropertyInfo propertyInfo in properties) { if (propertyInfo.PropertyType == typeof(ItemData) && propertyInfo.CanRead) { _cachedItemProps[type] = propertyInfo; object? value8 = propertyInfo.GetValue(data, null); return (ItemData)((value8 is ItemData) ? value8 : null); } } return null; } private string ExtractTextFromUI(Transform child) { Text componentInChildren = ((Component)child).GetComponentInChildren(); if ((Object)(object)componentInChildren != (Object)null) { return componentInChildren.text; } Component[] componentsInChildren = ((Component)child).GetComponentsInChildren(true); foreach (Component val in componentsInChildren) { if (!((object)val).GetType().Name.Contains("TextMeshPro") && !((object)val).GetType().Name.Contains("TMP_Text")) { continue; } PropertyInfo property = ((object)val).GetType().GetProperty("text"); if (property != null) { string text = property.GetValue(val, null) as string; if (!string.IsNullOrEmpty(text)) { return text; } } } return null; } private string GetRawRecipeName(Recipe r) { if ((Object)(object)r.m_item != (Object)null && r.m_item.m_itemData != null) { return r.m_item.m_itemData.m_shared.m_name; } ZNetScene instance = ZNetScene.instance; GameObject val = ((instance != null) ? instance.GetPrefab(((Object)r).name) : null); if ((Object)(object)val != (Object)null) { ItemDrop component = val.GetComponent(); if ((Object)(object)component != (Object)null) { return component.m_itemData.m_shared.m_name; } Piece component2 = val.GetComponent(); if ((Object)(object)component2 != (Object)null) { return component2.m_name; } } return null; } private bool IsVisibleInScroll(RectTransform item, ScrollRect scrollRect) { //IL_00a5: 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_00b1: 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_00c0: 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) if ((Object)(object)item == (Object)null || !((Component)item).gameObject.activeInHierarchy) { return false; } if ((Object)(object)scrollRect == (Object)null || (Object)(object)scrollRect.viewport == (Object)null) { return true; } Vector3[] array = (Vector3[])(object)new Vector3[4]; scrollRect.viewport.GetWorldCorners(array); Rect val = default(Rect); ((Rect)(ref val))..ctor(array[0].x, array[0].y, array[2].x - array[0].x, array[2].y - array[0].y); Vector3[] array2 = (Vector3[])(object)new Vector3[4]; item.GetWorldCorners(array2); Vector3 val2 = (array2[0] + array2[2]) / 2f; return ((Rect)(ref val)).Contains(val2); } } [BepInPlugin("com.Kadrio.RecipePinner", "Recipe Pinner", "1.2.4")] public class RecipePinnerPlugin : BaseUnityPlugin { public enum PinLayoutMode { AutoDetect, ForceVertical, ForceHorizontal, ForceBottomRightHorizontal } public class ConfigurationManagerAttributes { public bool? ShowRangeAsPercent; public Action CustomDrawer; public bool? Browsable; public string Category; public object DefaultValue; public bool? HideDefaultButton; public bool? HideSettingName; public string Description; public string DispName; public int? Order; public bool? ReadOnly; public bool? IsAdvanced; public Func ObjToStr; public Func StrToObj; } public static RecipePinnerPlugin Instance; public static ConfigEntry EnableMod; public static ConfigEntry LanguageOverride; public static ConfigEntry LayoutModeConfig; public static ConfigEntry MaximumPins; public static ConfigEntry PinsPerPage; public static ConfigEntry AutoUnpinAfterCrafting; public static ConfigEntry EnableGatheringList; public static ConfigEntry AutoOpenGatheringList; public static ConfigEntry HotkeyPin; public static ConfigEntry HotkeyClearAll; public static ConfigEntry HotkeyToggleVisibility; public static ConfigEntry HotkeyPageSwitch; public static ConfigEntry HotkeyGatheringList; public static ConfigEntry EnableChestScanning; public static ConfigEntry ChestScanRange; public static ConfigEntry ChestScanInterval; public static ConfigEntry UIScale; public static ConfigEntry FontSizeRecipeName; public static ConfigEntry FontSizeMaterials; public static ConfigEntry BackgroundOpacity; public static ConfigEntry ColorHeader; public static ConfigEntry ColorEnoughInInventory; public static ConfigEntry ColorEnoughWithChests; public static ConfigEntry ColorMissing; public static ConfigEntry ColorPaginationActive; public static ConfigEntry PaginationInactiveOpacity; public static ConfigEntry PaginationDotSize; public static ConfigEntry PaginationDotSpacing; public static ConfigEntry EnableCraftReadiness; public static ConfigEntry ColorCraftReady; public static ConfigEntry ColorCraftNotReady; public static ConfigEntry GatheringListFontSizeTitle; public static ConfigEntry GatheringListFontSizeMaterials; public static ConfigEntry VerticalListWidth; public static ConfigEntry VerticalPinSpacing; public static ConfigEntry VerticalPosition; public static ConfigEntry HorizontalColumnWidth; public static ConfigEntry HorizontalPinSpacing; public static ConfigEntry HorizontalPosition; public static ConfigEntry BottomRightColumnWidth; public static ConfigEntry BottomRightPinSpacing; public static ConfigEntry BottomRightPosition; public static ConfigEntry EnableDebugLogging; public static ConfigEntry InventoryGatheringListPosition; public LocalizationManager LocalizationMgr; public RecipeManager RecipeMgr; public ContainerScanner ContainerMgr; public UIManager UIMgr; public DataPersistence DataMgr; internal bool _mluiMapListEnabled; internal bool _mluiNoMapListEnabled; internal bool _mluiInstalled; private bool _startupInitialized; private string _lastLanguage = ""; private string _currentSessionPlayer; private static bool _isUiVisible = true; public bool IsHorizontalMode { get { if (LayoutModeConfig.Value == PinLayoutMode.ForceBottomRightHorizontal) { return true; } if (LayoutModeConfig.Value == PinLayoutMode.ForceHorizontal) { return true; } if (LayoutModeConfig.Value == PinLayoutMode.ForceVertical) { return false; } if (!_mluiInstalled) { return false; } if (Game.m_noMap) { return _mluiNoMapListEnabled; } return _mluiMapListEnabled; } } private void Awake() { //IL_005d: Unknown result type (might be due to invalid IL or missing references) //IL_0062: Unknown result type (might be due to invalid IL or missing references) Instance = this; BindConfigs(); DebugLogger.Log("Plugin init"); LocalizationMgr = new LocalizationManager(this); RecipeMgr = new RecipeManager(); ContainerMgr = new ContainerScanner(); UIMgr = new UIManager(); DataMgr = new DataPersistence(); DebugLogger.Log("Managers ready"); Harmony val = new Harmony("com.Kadrio.RecipePinner"); val.PatchAll(typeof(RecipePinnerPlugin)); val.PatchAll(typeof(ContainerScanner)); DebugLogger.Log("Patches applied"); } private void BindConfigs() { //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Expected O, but got Unknown //IL_008d: Unknown result type (might be due to invalid IL or missing references) //IL_0097: Expected O, but got Unknown //IL_00e4: Unknown result type (might be due to invalid IL or missing references) //IL_00ee: Expected O, but got Unknown //IL_0143: Unknown result type (might be due to invalid IL or missing references) //IL_014d: Expected O, but got Unknown //IL_01a1: Unknown result type (might be due to invalid IL or missing references) //IL_01ab: Expected O, but got Unknown //IL_01f8: Unknown result type (might be due to invalid IL or missing references) //IL_0202: Expected O, but got Unknown //IL_0239: Unknown result type (might be due to invalid IL or missing references) //IL_0243: Expected O, but got Unknown //IL_0290: Unknown result type (might be due to invalid IL or missing references) //IL_029a: Expected O, but got Unknown //IL_02d5: Unknown result type (might be due to invalid IL or missing references) //IL_02df: Expected O, but got Unknown //IL_031a: Unknown result type (might be due to invalid IL or missing references) //IL_0324: Expected O, but got Unknown //IL_035f: Unknown result type (might be due to invalid IL or missing references) //IL_0369: Expected O, but got Unknown //IL_03a4: Unknown result type (might be due to invalid IL or missing references) //IL_03ae: Expected O, but got Unknown //IL_03e6: Unknown result type (might be due to invalid IL or missing references) //IL_03f0: Expected O, but got Unknown //IL_0427: Unknown result type (might be due to invalid IL or missing references) //IL_0431: Expected O, but got Unknown //IL_0490: Unknown result type (might be due to invalid IL or missing references) //IL_049a: Expected O, but got Unknown //IL_04e3: Unknown result type (might be due to invalid IL or missing references) //IL_04ed: Expected O, but got Unknown //IL_0536: Unknown result type (might be due to invalid IL or missing references) //IL_0540: Expected O, but got Unknown //IL_059f: Unknown result type (might be due to invalid IL or missing references) //IL_05a9: Expected O, but got Unknown //IL_05e8: Unknown result type (might be due to invalid IL or missing references) //IL_05f2: Expected O, but got Unknown //IL_0647: Unknown result type (might be due to invalid IL or missing references) //IL_0651: Expected O, but got Unknown //IL_06a6: Unknown result type (might be due to invalid IL or missing references) //IL_06b0: Expected O, but got Unknown //IL_0705: Unknown result type (might be due to invalid IL or missing references) //IL_070f: Expected O, but got Unknown //IL_075c: Unknown result type (might be due to invalid IL or missing references) //IL_0766: Expected O, but got Unknown //IL_07a5: Unknown result type (might be due to invalid IL or missing references) //IL_07cb: Unknown result type (might be due to invalid IL or missing references) //IL_07d5: Expected O, but got Unknown //IL_0814: Unknown result type (might be due to invalid IL or missing references) //IL_083a: Unknown result type (might be due to invalid IL or missing references) //IL_0844: Expected O, but got Unknown //IL_0883: Unknown result type (might be due to invalid IL or missing references) //IL_08a9: Unknown result type (might be due to invalid IL or missing references) //IL_08b3: Expected O, but got Unknown //IL_08f2: Unknown result type (might be due to invalid IL or missing references) //IL_0918: Unknown result type (might be due to invalid IL or missing references) //IL_0922: Expected O, but got Unknown //IL_0961: Unknown result type (might be due to invalid IL or missing references) //IL_0987: Unknown result type (might be due to invalid IL or missing references) //IL_0991: Expected O, but got Unknown //IL_09d0: Unknown result type (might be due to invalid IL or missing references) //IL_09f6: Unknown result type (might be due to invalid IL or missing references) //IL_0a00: Expected O, but got Unknown //IL_0a3f: Unknown result type (might be due to invalid IL or missing references) //IL_0a65: Unknown result type (might be due to invalid IL or missing references) //IL_0a6f: Expected O, but got Unknown //IL_0ace: Unknown result type (might be due to invalid IL or missing references) //IL_0ad8: Expected O, but got Unknown //IL_0b2d: Unknown result type (might be due to invalid IL or missing references) //IL_0b37: Expected O, but got Unknown //IL_0b8b: Unknown result type (might be due to invalid IL or missing references) //IL_0b95: Expected O, but got Unknown //IL_0be6: Unknown result type (might be due to invalid IL or missing references) //IL_0bf0: Expected O, but got Unknown //IL_0c2b: Unknown result type (might be due to invalid IL or missing references) //IL_0c35: Expected O, but got Unknown //IL_0c54: Unknown result type (might be due to invalid IL or missing references) //IL_0c7a: Unknown result type (might be due to invalid IL or missing references) //IL_0c84: Expected O, but got Unknown //IL_0cbf: Unknown result type (might be due to invalid IL or missing references) //IL_0cc9: Expected O, but got Unknown //IL_0d04: Unknown result type (might be due to invalid IL or missing references) //IL_0d0e: Expected O, but got Unknown //IL_0d2d: Unknown result type (might be due to invalid IL or missing references) //IL_0d53: Unknown result type (might be due to invalid IL or missing references) //IL_0d5d: Expected O, but got Unknown //IL_0d98: Unknown result type (might be due to invalid IL or missing references) //IL_0da2: Expected O, but got Unknown //IL_0ddd: Unknown result type (might be due to invalid IL or missing references) //IL_0de7: Expected O, but got Unknown //IL_0e06: Unknown result type (might be due to invalid IL or missing references) //IL_0e2c: Unknown result type (might be due to invalid IL or missing references) //IL_0e36: Expected O, but got Unknown //IL_0e55: Unknown result type (might be due to invalid IL or missing references) //IL_0e7b: Unknown result type (might be due to invalid IL or missing references) //IL_0e85: Expected O, but got Unknown //IL_0ebc: Unknown result type (might be due to invalid IL or missing references) //IL_0ec6: Expected O, but got Unknown EnableMod = ((BaseUnityPlugin)this).Config.Bind("1 - General", "EnableMod", true, new ConfigDescription("Enable or disable the mod completely.", (AcceptableValueBase)null, new object[1] { new ConfigurationManagerAttributes { Order = 99 } })); EnableMod.SettingChanged += delegate { if (!EnableMod.Value) { UIMgr?.DestroyUI(); } }; LanguageOverride = ((BaseUnityPlugin)this).Config.Bind("1 - General", "LanguageOverride", "Auto", new ConfigDescription("Force a specific language (e.g., 'German', 'Turkish').", (AcceptableValueBase)null, new object[1] { new ConfigurationManagerAttributes { Order = 98 } })); LanguageOverride.SettingChanged += delegate { LocalizationMgr?.LoadTranslations(); RecipeMgr?.RefreshRecipeCache(); UIMgr?.DestroyUI(); }; LayoutModeConfig = ((BaseUnityPlugin)this).Config.Bind("1 - General", "LayoutMode", PinLayoutMode.AutoDetect, new ConfigDescription("Choose layout position.", (AcceptableValueBase)null, new object[1] { new ConfigurationManagerAttributes { Order = 97 } })); LayoutModeConfig.SettingChanged += delegate { UIMgr?.DestroyUI(); }; MaximumPins = ((BaseUnityPlugin)this).Config.Bind("1 - General", "MaximumPins", 10, new ConfigDescription("Max pins allowed.", (AcceptableValueBase)(object)new AcceptableValueRange(1, 20), new object[1] { new ConfigurationManagerAttributes { Order = 96 } })); MaximumPins.SettingChanged += delegate { UIMgr?.DestroyUI(); }; PinsPerPage = ((BaseUnityPlugin)this).Config.Bind("1 - General", "PinsPerPage", 5, new ConfigDescription("How many pins to show per page.", (AcceptableValueBase)(object)new AcceptableValueRange(1, 10), new object[1] { new ConfigurationManagerAttributes { Order = 95 } })); PinsPerPage.SettingChanged += delegate { UIMgr?.ResetPage(); UIMgr?.DestroyUI(); }; AutoUnpinAfterCrafting = ((BaseUnityPlugin)this).Config.Bind("1 - General", "AutoUnpinAfterCrafting", true, new ConfigDescription("Unpin after crafting.", (AcceptableValueBase)null, new object[1] { new ConfigurationManagerAttributes { Order = 94 } })); EnableGatheringList = ((BaseUnityPlugin)this).Config.Bind("1 - General", "EnableGatheringList", true, new ConfigDescription("Enable the gathering list feature.", (AcceptableValueBase)null, new object[1] { new ConfigurationManagerAttributes { Order = 93 } })); EnableGatheringList.SettingChanged += delegate { UIMgr?.DestroyUI(); }; AutoOpenGatheringList = ((BaseUnityPlugin)this).Config.Bind("1 - General", "AutoOpenGatheringList", true, new ConfigDescription("Automatically open gathering list when 2+ recipes are pinned.", (AcceptableValueBase)null, new object[1] { new ConfigurationManagerAttributes { Order = 92 } })); HotkeyPin = ((BaseUnityPlugin)this).Config.Bind("2 - Controls", "HotkeyPin", (KeyCode)325, new ConfigDescription("Key to pin recipe.", (AcceptableValueBase)null, new object[1] { new ConfigurationManagerAttributes { Order = 99 } })); HotkeyToggleVisibility = ((BaseUnityPlugin)this).Config.Bind("2 - Controls", "HotkeyToggleVisibility", (KeyCode)288, new ConfigDescription("Key to toggle overlay.", (AcceptableValueBase)null, new object[1] { new ConfigurationManagerAttributes { Order = 98 } })); HotkeyGatheringList = ((BaseUnityPlugin)this).Config.Bind("2 - Controls", "HotkeyGatheringList", (KeyCode)289, new ConfigDescription("Key to toggle gathering list panel.", (AcceptableValueBase)null, new object[1] { new ConfigurationManagerAttributes { Order = 97 } })); HotkeyPageSwitch = ((BaseUnityPlugin)this).Config.Bind("2 - Controls", "HotkeyPageSwitch", (KeyCode)308, new ConfigDescription("Key to cycle through pin pages.", (AcceptableValueBase)null, new object[1] { new ConfigurationManagerAttributes { Order = 96 } })); HotkeyClearAll = ((BaseUnityPlugin)this).Config.Bind("2 - Controls", "HotkeyClearAll", (KeyCode)112, new ConfigDescription("Key to clear all pins.", (AcceptableValueBase)null, new object[1] { new ConfigurationManagerAttributes { Order = 95 } })); EnableChestScanning = ((BaseUnityPlugin)this).Config.Bind("3 - Chest Scanner", "EnableChestScanning", false, new ConfigDescription("Count materials in nearby chests.", (AcceptableValueBase)null, new object[1] { new ConfigurationManagerAttributes { Order = 99 } })); EnableChestScanning.SettingChanged += delegate { RecipeMgr?.RefreshRecipeCache(); }; ChestScanRange = ((BaseUnityPlugin)this).Config.Bind("3 - Chest Scanner", "ChestScanRange", 20f, new ConfigDescription("Scan radius.", (AcceptableValueBase)(object)new AcceptableValueRange(5f, 100f), new object[1] { new ConfigurationManagerAttributes { Order = 98 } })); ChestScanInterval = ((BaseUnityPlugin)this).Config.Bind("3 - Chest Scanner", "ChestScanInterval", 3f, new ConfigDescription("Scan frequency (seconds).", (AcceptableValueBase)(object)new AcceptableValueRange(0.5f, 10f), new object[1] { new ConfigurationManagerAttributes { Order = 97 } })); UIScale = ((BaseUnityPlugin)this).Config.Bind("4 - Appearance", "UIScale", 0.75f, new ConfigDescription("Global UI scale.", (AcceptableValueBase)(object)new AcceptableValueRange(0.3f, 3f), new object[1] { new ConfigurationManagerAttributes { Order = 99 } })); UIScale.SettingChanged += delegate { UIMgr?.DestroyUI(); }; BackgroundOpacity = ((BaseUnityPlugin)this).Config.Bind("4 - Appearance", "BackgroundOpacity", 0.5f, new ConfigDescription("Background opacity.", (AcceptableValueBase)(object)new AcceptableValueRange(0f, 1f), new object[1] { new ConfigurationManagerAttributes { Order = 98 } })); FontSizeRecipeName = ((BaseUnityPlugin)this).Config.Bind("4 - Appearance", "FontSizeRecipeName", 16, new ConfigDescription("Recipe name font size.", (AcceptableValueBase)(object)new AcceptableValueRange(8, 40), new object[1] { new ConfigurationManagerAttributes { Order = 97 } })); FontSizeRecipeName.SettingChanged += delegate { RecipeMgr?.RefreshRecipeCache(); }; FontSizeMaterials = ((BaseUnityPlugin)this).Config.Bind("4 - Appearance", "FontSizeMaterials", 15, new ConfigDescription("Material font size.", (AcceptableValueBase)(object)new AcceptableValueRange(8, 40), new object[1] { new ConfigurationManagerAttributes { Order = 96 } })); FontSizeMaterials.SettingChanged += delegate { RecipeMgr?.RefreshRecipeCache(); }; GatheringListFontSizeTitle = ((BaseUnityPlugin)this).Config.Bind("4 - Appearance", "GatheringListFontSizeTitle", 20, new ConfigDescription("Gathering list title font size.", (AcceptableValueBase)(object)new AcceptableValueRange(8, 40), new object[1] { new ConfigurationManagerAttributes { Order = 95 } })); GatheringListFontSizeTitle.SettingChanged += delegate { UIMgr?.DestroyUI(); }; GatheringListFontSizeMaterials = ((BaseUnityPlugin)this).Config.Bind("4 - Appearance", "GatheringListFontSizeMaterials", 15, new ConfigDescription("Gathering list material font size.", (AcceptableValueBase)(object)new AcceptableValueRange(8, 40), new object[1] { new ConfigurationManagerAttributes { Order = 94 } })); GatheringListFontSizeMaterials.SettingChanged += delegate { UIMgr?.DestroyUI(); }; EnableCraftReadiness = ((BaseUnityPlugin)this).Config.Bind("4 - Appearance", "EnableCraftReadiness", true, new ConfigDescription("Show a colored accent bar indicating craft readiness.", (AcceptableValueBase)null, new object[1] { new ConfigurationManagerAttributes { Order = 93 } })); EnableCraftReadiness.SettingChanged += delegate { RecipeMgr?.RefreshRecipeCache(); }; ColorHeader = ((BaseUnityPlugin)this).Config.Bind("5 - Colors", "ColorHeader", new Color(1f, 0.717f, 0.368f, 1f), new ConfigDescription("Recipe title color.", (AcceptableValueBase)null, new object[1] { new ConfigurationManagerAttributes { Order = 99 } })); ColorHeader.SettingChanged += delegate { RecipeMgr?.RefreshRecipeCache(); }; ColorEnoughInInventory = ((BaseUnityPlugin)this).Config.Bind("5 - Colors", "ColorEnoughInInventory", new Color(0f, 1f, 0f, 1f), new ConfigDescription("Color: Enough in inventory.", (AcceptableValueBase)null, new object[1] { new ConfigurationManagerAttributes { Order = 98 } })); ColorEnoughInInventory.SettingChanged += delegate { RecipeMgr?.RefreshRecipeCache(); }; ColorEnoughWithChests = ((BaseUnityPlugin)this).Config.Bind("5 - Colors", "ColorEnoughWithChests", new Color(1f, 1f, 0f, 1f), new ConfigDescription("Color: Enough with chests.", (AcceptableValueBase)null, new object[1] { new ConfigurationManagerAttributes { Order = 97 } })); ColorEnoughWithChests.SettingChanged += delegate { RecipeMgr?.RefreshRecipeCache(); }; ColorMissing = ((BaseUnityPlugin)this).Config.Bind("5 - Colors", "ColorMissing", new Color(1f, 0.33f, 0.33f, 1f), new ConfigDescription("Color: Missing materials.", (AcceptableValueBase)null, new object[1] { new ConfigurationManagerAttributes { Order = 96 } })); ColorMissing.SettingChanged += delegate { RecipeMgr?.RefreshRecipeCache(); }; ColorCraftReady = ((BaseUnityPlugin)this).Config.Bind("5 - Colors", "ColorCraftReady", new Color(0.2f, 0.9f, 0.3f, 0.85f), new ConfigDescription("Accent bar color when all materials are available.", (AcceptableValueBase)null, new object[1] { new ConfigurationManagerAttributes { Order = 95 } })); ColorCraftReady.SettingChanged += delegate { RecipeMgr?.RefreshRecipeCache(); }; ColorCraftNotReady = ((BaseUnityPlugin)this).Config.Bind("5 - Colors", "ColorCraftNotReady", new Color(0.9f, 0.25f, 0.25f, 0.5f), new ConfigDescription("Accent bar color when materials are missing.", (AcceptableValueBase)null, new object[1] { new ConfigurationManagerAttributes { Order = 94 } })); ColorCraftNotReady.SettingChanged += delegate { RecipeMgr?.RefreshRecipeCache(); }; ColorPaginationActive = ((BaseUnityPlugin)this).Config.Bind("6 - Pagination", "ColorPaginationActive", new Color(1f, 0.717f, 0.368f, 1f), new ConfigDescription("Active page dot color.", (AcceptableValueBase)null, new object[1] { new ConfigurationManagerAttributes { Order = 99 } })); ColorPaginationActive.SettingChanged += delegate { UIMgr?.UpdateUI(isVisible: true); }; PaginationInactiveOpacity = ((BaseUnityPlugin)this).Config.Bind("6 - Pagination", "PaginationInactiveOpacity", 0.3f, new ConfigDescription("Opacity of inactive page dots.", (AcceptableValueBase)(object)new AcceptableValueRange(0.1f, 1f), new object[1] { new ConfigurationManagerAttributes { Order = 98 } })); PaginationInactiveOpacity.SettingChanged += delegate { UIMgr?.UpdateUI(isVisible: true); }; PaginationDotSize = ((BaseUnityPlugin)this).Config.Bind("6 - Pagination", "PaginationDotSize", 10, new ConfigDescription("Size of the pagination squares.", (AcceptableValueBase)(object)new AcceptableValueRange(5, 20), new object[1] { new ConfigurationManagerAttributes { Order = 97 } })); PaginationDotSize.SettingChanged += delegate { UIMgr?.UpdateUI(isVisible: true); }; PaginationDotSpacing = ((BaseUnityPlugin)this).Config.Bind("6 - Pagination", "PaginationDotSpacing", 8, new ConfigDescription("Space between pagination squares.", (AcceptableValueBase)(object)new AcceptableValueRange(0, 20), new object[1] { new ConfigurationManagerAttributes { Order = 96 } })); PaginationDotSpacing.SettingChanged += delegate { UIMgr?.UpdateUI(isVisible: true); }; VerticalListWidth = ((BaseUnityPlugin)this).Config.Bind("7 - Layout (Vertical Mode)", "ListWidth", 265f, new ConfigDescription("List width.", (AcceptableValueBase)null, new object[1] { new ConfigurationManagerAttributes { Order = 99 } })); VerticalPinSpacing = ((BaseUnityPlugin)this).Config.Bind("7 - Layout (Vertical Mode)", "PinSpacing", 10f, new ConfigDescription("Spacing between pins.", (AcceptableValueBase)null, new object[1] { new ConfigurationManagerAttributes { Order = 98 } })); VerticalPosition = ((BaseUnityPlugin)this).Config.Bind("7 - Layout (Vertical Mode)", "Position", new Vector2(-40f, -250f), new ConfigDescription("Position (X, Y).", (AcceptableValueBase)null, new object[1] { new ConfigurationManagerAttributes { Order = 97 } })); HorizontalColumnWidth = ((BaseUnityPlugin)this).Config.Bind("8 - Layout (Horizontal - Map Side)", "ColumnWidth", 265f, new ConfigDescription("Column width.", (AcceptableValueBase)null, new object[1] { new ConfigurationManagerAttributes { Order = 99 } })); HorizontalPinSpacing = ((BaseUnityPlugin)this).Config.Bind("8 - Layout (Horizontal - Map Side)", "PinSpacing", 10f, new ConfigDescription("Spacing between pins.", (AcceptableValueBase)null, new object[1] { new ConfigurationManagerAttributes { Order = 98 } })); HorizontalPosition = ((BaseUnityPlugin)this).Config.Bind("8 - Layout (Horizontal - Map Side)", "Position", new Vector2(-250f, -40f), new ConfigDescription("Position (X, Y).", (AcceptableValueBase)null, new object[1] { new ConfigurationManagerAttributes { Order = 97 } })); BottomRightColumnWidth = ((BaseUnityPlugin)this).Config.Bind("9 - Layout (Horizontal - Bottom Right)", "ColumnWidth", 265f, new ConfigDescription("Column width.", (AcceptableValueBase)null, new object[1] { new ConfigurationManagerAttributes { Order = 99 } })); BottomRightPinSpacing = ((BaseUnityPlugin)this).Config.Bind("9 - Layout (Horizontal - Bottom Right)", "PinSpacing", 10f, new ConfigDescription("Spacing between pins.", (AcceptableValueBase)null, new object[1] { new ConfigurationManagerAttributes { Order = 98 } })); BottomRightPosition = ((BaseUnityPlugin)this).Config.Bind("9 - Layout (Horizontal - Bottom Right)", "Position", new Vector2(-40f, 40f), new ConfigDescription("Position (X, Y).", (AcceptableValueBase)null, new object[1] { new ConfigurationManagerAttributes { Order = 97 } })); InventoryGatheringListPosition = ((BaseUnityPlugin)this).Config.Bind("1 - General", "InventoryGatheringListPosition", new Vector2(-400f, 320f), new ConfigDescription("Gathering list position offset (X, Y) when inventory/chest is open.", (AcceptableValueBase)null, new object[1] { new ConfigurationManagerAttributes { Order = 91 } })); EnableDebugLogging = ((BaseUnityPlugin)this).Config.Bind("10 - Debug", "EnableDebugLogging", false, new ConfigDescription("Enable debug logs.", (AcceptableValueBase)null, new object[1] { new ConfigurationManagerAttributes { Order = 99 } })); DebugLogger.Log("Config loaded"); } private void Start() { DebugLogger.Log("Start()"); LocalizationMgr.LoadTranslations(); ReadMyLittleUIConfig(); ContainerMgr.InitializeContainers(); DebugLogger.Log("Start done"); } private void OnDestroy() { DebugLogger.Log("OnDestroy"); if ((Object)(object)Player.m_localPlayer != (Object)null) { DataMgr.SavePins(); } RecipeMgr.Cleanup(); } private void Update() { //IL_00ee: Unknown result type (might be due to invalid IL or missing references) //IL_013f: Unknown result type (might be due to invalid IL or missing references) //IL_01a7: Unknown result type (might be due to invalid IL or missing references) //IL_02bd: Unknown result type (might be due to invalid IL or missing references) //IL_02ed: Unknown result type (might be due to invalid IL or missing references) if (!EnableMod.Value) { return; } ReflectionHelper.UpdateGuiScale(); if (!_startupInitialized && (Object)(object)Player.m_localPlayer != (Object)null && (Object)(object)ObjectDB.instance != (Object)null && ObjectDB.instance.m_recipes.Count > 0) { DebugLogger.Log("First init"); _lastLanguage = Localization.instance.GetSelectedLanguage(); DataMgr.LoadPins(); RecipeMgr.ValidateAndCleanPins(); RecipeMgr.RefreshRecipeCache(); _startupInitialized = true; DebugLogger.Log($"Init done - {RecipeMgr.PinnedRecipes.Count} pins loaded"); } if (EnableChestScanning.Value && (Object)(object)Player.m_localPlayer != (Object)null && RecipeMgr.CachedPins.Count > 0) { ContainerMgr.UpdateScanning(); } if (Input.GetKeyDown(HotkeyToggleVisibility.Value) && !InputHelper.IsInputBlocked()) { _isUiVisible = !_isUiVisible; DebugLogger.Log($"UI visibility toggled: {_isUiVisible}"); } if ((Object)(object)Player.m_localPlayer != (Object)null) { UpdatePlayerSession(); } if (Input.GetKeyDown(HotkeyPin.Value)) { if ((Object)(object)InventoryGui.instance != (Object)null && InventoryGui.IsVisible()) { RecipeMgr.TryPinHoveredRecipe(InventoryGui.instance); } else if ((Object)(object)Hud.instance != (Object)null && (Object)(object)Player.m_localPlayer != (Object)null && ((Character)Player.m_localPlayer).InPlaceMode()) { RecipeMgr.TryPinHoveredPiece(); } } if (Input.GetKeyDown(HotkeyClearAll.Value) && !InputHelper.IsInputBlocked() && RecipeMgr.PinnedRecipes.Count > 0) { int count = RecipeMgr.PinnedRecipes.Count; RecipeMgr.PinnedRecipes.Clear(); RecipeMgr.RefreshRecipeCache(); UIMgr.CloseGatheringList(); Player localPlayer = Player.m_localPlayer; if (localPlayer != null) { ((Character)localPlayer).Message((MessageType)2, LocalizationMgr.GetText("cleared"), 0, (Sprite)null); } DebugLogger.Log($"Cleared {count} pinned recipes"); } if (Localization.instance != null) { string selectedLanguage = Localization.instance.GetSelectedLanguage(); if (_lastLanguage != selectedLanguage) { DebugLogger.Log("Language changed from " + _lastLanguage + " to " + selectedLanguage); _lastLanguage = selectedLanguage; LocalizationMgr.LoadTranslations(); if ((Object)(object)ObjectDB.instance != (Object)null) { RecipeMgr.RefreshRecipeCache(); } UIMgr?.DestroyUI(); } } if (Input.GetKeyDown(HotkeyPageSwitch.Value) && _isUiVisible && !InputHelper.IsInputBlocked()) { UIMgr?.CyclePage(); } if (Input.GetKeyDown(HotkeyGatheringList.Value) && !InputHelper.IsInputBlocked() && EnableGatheringList.Value) { UIMgr?.ToggleGatheringList(); } } private void UpdatePlayerSession() { if ((Object)(object)Player.m_localPlayer == (Object)null || ((Character)Player.m_localPlayer).IsDead()) { return; } string playerName = Player.m_localPlayer.GetPlayerName(); if (!string.IsNullOrEmpty(playerName)) { if (_currentSessionPlayer != playerName) { DebugLogger.Log("Player session changed from '" + _currentSessionPlayer + "' to '" + playerName + "'"); RecipeMgr.PinnedRecipes.Clear(); RecipeMgr.CachedPins.Clear(); UIMgr.DestroyUI(); _currentSessionPlayer = playerName; DataMgr.LoadPins(); RecipeMgr.RefreshRecipeCache(); } UIMgr.UpdateUI(_isUiVisible); } } private void ReadMyLittleUIConfig() { if (!Chainloader.PluginInfos.ContainsKey("shudnal.MyLittleUI")) { _mluiInstalled = false; DebugLogger.Log("MyLittleUI not detected"); return; } _mluiInstalled = true; _mluiMapListEnabled = true; _mluiNoMapListEnabled = true; string path = Path.Combine(Paths.ConfigPath, "shudnal.MyLittleUI.cfg"); if (!File.Exists(path)) { DebugLogger.Log("MyLittleUI installed but config not found"); return; } try { string[] array = File.ReadAllLines(path); string text = ""; string[] array2 = array; for (int i = 0; i < array2.Length; i++) { string text2 = array2[i].Trim(); if (text2.StartsWith("[") && text2.EndsWith("]")) { text = text2; } else if (text2.StartsWith("Enable")) { bool flag = text2.ToLower().Contains("true"); if (text == "[Status effects - Map - List]") { _mluiMapListEnabled = flag; } else if (text == "[Status effects - Nomap - List]") { _mluiNoMapListEnabled = flag; } } } DebugLogger.Log($"MyLittleUI Config: MapList={_mluiMapListEnabled}, NoMapList={_mluiNoMapListEnabled}"); } catch (Exception ex) { DebugLogger.Error("Error reading MyLittleUI config", ex); } } [HarmonyPatch(typeof(Game), "SavePlayerProfile")] [HarmonyPostfix] public static void AutoSavePinsHook() { if ((Object)(object)Player.m_localPlayer != (Object)null && (Object)(object)Instance != (Object)null) { DebugLogger.Log("Auto-saving pins"); Instance.DataMgr.SavePins(); } } [HarmonyPatch(typeof(InventoryGui), "DoCrafting")] [HarmonyPostfix] public static void AutoUnpinHook(InventoryGui __instance) { if (!EnableMod.Value || !AutoUnpinAfterCrafting.Value || (Object)(object)Instance == (Object)null) { return; } Recipe craftRecipe = ReflectionHelper.GetCraftRecipe(__instance); if (!((Object)(object)craftRecipe != (Object)null)) { return; } string text = null; if (!((Selectable)__instance.m_tabUpgrade).interactable) { ItemData craftUpgradeItem = ReflectionHelper.GetCraftUpgradeItem(__instance); if (craftUpgradeItem != null) { string name = ((Object)craftRecipe.m_item).name; int quality = craftUpgradeItem.m_quality; int num = quality + 1; text = $"{name} ★{num}"; DebugLogger.Log($"Upgrade crafted: Unpinning target {text} (Base Level: {quality})"); } } else { text = ((Object)craftRecipe).name; } if (text != null && Instance.RecipeMgr.PinnedRecipes.TryGetValue(text, out var value)) { value--; DebugLogger.Log($"Auto-unpin: {text}, remaining count: {value}"); if (value <= 0) { Instance.RecipeMgr.PinnedRecipes.Remove(text); DebugLogger.Log("Recipe " + text + " fully unpinned"); } else { Instance.RecipeMgr.PinnedRecipes[text] = value; } Instance.RecipeMgr.RefreshRecipeCache(); if (Instance.RecipeMgr.PinnedRecipes.Count < 2) { Instance.UIMgr.CloseGatheringList(); } } } [HarmonyPatch(typeof(Player), "ConsumeResources")] [HarmonyPostfix] public static void AutoUnpinBuildHook() { if ((Object)(object)Instance == (Object)null || !EnableMod.Value || !AutoUnpinAfterCrafting.Value) { return; } Player localPlayer = Player.m_localPlayer; if ((Object)(object)localPlayer == (Object)null) { return; } PieceTable pieceTable = ReflectionHelper.GetPieceTable(localPlayer); if ((Object)(object)pieceTable == (Object)null) { return; } Piece selectedPiece = pieceTable.GetSelectedPiece(); if ((Object)(object)selectedPiece == (Object)null) { return; } string text = ((Object)selectedPiece).name.Replace("(Clone)", "").Trim(); if (Instance.RecipeMgr.PinnedRecipes.TryGetValue(text, out var value)) { value--; DebugLogger.Log($"Auto-unpin (Build): {text}, remaining count: {value}"); if (value <= 0) { Instance.RecipeMgr.PinnedRecipes.Remove(text); DebugLogger.Log("Build recipe " + text + " fully unpinned"); } else { Instance.RecipeMgr.PinnedRecipes[text] = value; } Instance.RecipeMgr.RefreshRecipeCache(); if (Instance.RecipeMgr.PinnedRecipes.Count < 2) { Instance.UIMgr.CloseGatheringList(); } } } } public static class ReflectionHelper { private static Func _getGuiScale; private static Func _getRecipeListRoot; private static Func _getAvailableRecipes; private static Func _getCurrentContainer; private static Func _getCraftRecipe; private static Func _getCraftUpgradeItem; private static Func _getHoveredPiece; public static Func CheckContainerAccess; private static FieldInfo _f_buildPieces; public static float currentGuiScaleValue; static ReflectionHelper() { currentGuiScaleValue = 1f; InitializeReflection(); } public static void InitializeReflection() { DebugLogger.Log("Reflection init"); int num = 0; int num2 = 0; try { FieldInfo fieldInfo = AccessTools.Field(typeof(GuiScaler), "m_largeGuiScale"); if (fieldInfo != null && fieldInfo.IsStatic) { _getGuiScale = Expression.Lambda>(Expression.Field(null, fieldInfo), Array.Empty()).Compile(); num++; DebugLogger.Verbose("✓ GuiScaler.m_largeGuiScale"); } else { num2++; DebugLogger.Warning("✗ GuiScaler.m_largeGuiScale not found"); } FieldInfo fieldInfo2 = AccessTools.Field(typeof(InventoryGui), "m_recipeListRoot"); if (fieldInfo2 != null) { ParameterExpression parameterExpression = Expression.Parameter(typeof(InventoryGui), "arg"); _getRecipeListRoot = Expression.Lambda>(Expression.Field(parameterExpression, fieldInfo2), new ParameterExpression[1] { parameterExpression }).Compile(); num++; DebugLogger.Verbose("✓ InventoryGui.m_recipeListRoot"); } else { num2++; DebugLogger.Warning("✗ InventoryGui.m_recipeListRoot not found"); } FieldInfo fieldInfo3 = AccessTools.Field(typeof(InventoryGui), "m_availableRecipes"); if (fieldInfo3 != null) { ParameterExpression parameterExpression2 = Expression.Parameter(typeof(InventoryGui), "arg"); _getAvailableRecipes = Expression.Lambda>(Expression.Field(parameterExpression2, fieldInfo3), new ParameterExpression[1] { parameterExpression2 }).Compile(); num++; DebugLogger.Verbose("✓ InventoryGui.m_availableRecipes"); } else { num2++; DebugLogger.Warning("✗ InventoryGui.m_availableRecipes not found"); } FieldInfo fieldInfo4 = AccessTools.Field(typeof(InventoryGui), "m_currentContainer"); if (fieldInfo4 != null) { ParameterExpression parameterExpression3 = Expression.Parameter(typeof(InventoryGui), "arg"); _getCurrentContainer = Expression.Lambda>(Expression.Field(parameterExpression3, fieldInfo4), new ParameterExpression[1] { parameterExpression3 }).Compile(); num++; DebugLogger.Verbose("✓ InventoryGui.m_currentContainer"); } else { num2++; DebugLogger.Warning("✗ InventoryGui.m_currentContainer not found"); } FieldInfo fieldInfo5 = AccessTools.Field(typeof(InventoryGui), "m_craftRecipe"); if (fieldInfo5 != null) { ParameterExpression parameterExpression4 = Expression.Parameter(typeof(InventoryGui), "arg"); _getCraftRecipe = Expression.Lambda>(Expression.Field(parameterExpression4, fieldInfo5), new ParameterExpression[1] { parameterExpression4 }).Compile(); num++; DebugLogger.Verbose("✓ InventoryGui.m_craftRecipe"); } else { num2++; DebugLogger.Warning("✗ InventoryGui.m_craftRecipe not found"); } FieldInfo fieldInfo6 = AccessTools.Field(typeof(InventoryGui), "m_craftUpgradeItem"); if (fieldInfo6 != null) { ParameterExpression parameterExpression5 = Expression.Parameter(typeof(InventoryGui), "arg"); _getCraftUpgradeItem = Expression.Lambda>(Expression.Field(parameterExpression5, fieldInfo6), new ParameterExpression[1] { parameterExpression5 }).Compile(); num++; DebugLogger.Verbose("✓ InventoryGui.m_craftUpgradeItem"); } else { num2++; DebugLogger.Warning("✗ InventoryGui.m_craftUpgradeItem not found"); } FieldInfo fieldInfo7 = AccessTools.Field(typeof(Hud), "m_hoveredPiece"); if (fieldInfo7 != null) { ParameterExpression parameterExpression6 = Expression.Parameter(typeof(Hud), "arg"); _getHoveredPiece = Expression.Lambda>(Expression.Field(parameterExpression6, fieldInfo7), new ParameterExpression[1] { parameterExpression6 }).Compile(); num++; DebugLogger.Verbose("✓ Hud.m_hoveredPiece"); } else { num2++; DebugLogger.Warning("✗ Hud.m_hoveredPiece not found"); } MethodInfo methodInfo = AccessTools.Method(typeof(Container), "CheckAccess", new Type[1] { typeof(long) }, (Type[])null); if (methodInfo != null) { CheckContainerAccess = AccessTools.MethodDelegate>(methodInfo, (object)null, true); num++; DebugLogger.Verbose("✓ Container.CheckAccess"); } else { num2++; DebugLogger.Warning("✗ Container.CheckAccess not found"); } _f_buildPieces = AccessTools.Field(typeof(Player), "m_buildPieces"); if (_f_buildPieces != null) { num++; DebugLogger.Verbose("✓ Player.m_buildPieces"); } else { num2++; DebugLogger.Warning("✗ Player.m_buildPieces not found"); } DebugLogger.Log($"Reflection done: {num} ok, {num2} failed"); if (num2 > 0) { DebugLogger.Warning("Some reflection targets failed"); } } catch (Exception ex) { DebugLogger.Error("Reflection init failed", ex); } } public static void UpdateGuiScale() { if (_getGuiScale != null) { currentGuiScaleValue = _getGuiScale(); } else { currentGuiScaleValue = 1f; } } public static Transform GetRecipeListRoot(InventoryGui gui) { if (_getRecipeListRoot == null) { DebugLogger.Warning("GetRecipeListRoot delegate is null"); return null; } return _getRecipeListRoot(gui); } public static object GetAvailableRecipes(InventoryGui gui) { if (_getAvailableRecipes == null) { DebugLogger.Warning("GetAvailableRecipes delegate is null"); return null; } return _getAvailableRecipes(gui); } public static Container GetCurrentContainer(InventoryGui gui) { if (_getCurrentContainer == null) { DebugLogger.Verbose("GetCurrentContainer delegate is null"); return null; } return _getCurrentContainer(gui); } public static Recipe GetCraftRecipe(InventoryGui gui) { if (_getCraftRecipe == null) { DebugLogger.Warning("GetCraftRecipe delegate is null"); return null; } return _getCraftRecipe(gui); } public static ItemData GetCraftUpgradeItem(InventoryGui gui) { return _getCraftUpgradeItem?.Invoke(gui); } public static Piece GetHoveredPiece(Hud hud) { if (_getHoveredPiece == null) { DebugLogger.Verbose("GetHoveredPiece delegate is null"); return null; } return _getHoveredPiece(hud); } public static PieceTable GetPieceTable(Player player) { if (_f_buildPieces == null || (Object)(object)player == (Object)null) { return null; } object? value = _f_buildPieces.GetValue(player); return (PieceTable)((value is PieceTable) ? value : null); } } public static class InputHelper { public static bool IsInputBlocked() { if (Console.IsVisible()) { return true; } if ((Object)(object)Chat.instance != (Object)null && Chat.instance.HasFocus()) { return true; } if (TextInput.IsVisible()) { DebugLogger.Verbose("Input blocked: TextInput is visible"); return true; } return false; } public static bool IsMouseOverRect(RectTransform rect) { //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)rect == (Object)null) { DebugLogger.Verbose("IsMouseOverRect: rect is null"); return false; } bool num = RectTransformUtility.RectangleContainsScreenPoint(rect, Vector2.op_Implicit(Input.mousePosition)); if (num) { DebugLogger.Verbose("Mouse over rect: " + ((Object)((Component)rect).gameObject).name); } return num; } } public class GatheringItemUI : MonoBehaviour { public Image Icon; public Text AmountText; public void SetActive(bool active) { ((Component)this).gameObject.SetActive(active); } } public class GatheringListUI : MonoBehaviour { [CompilerGenerated] private sealed class d__10 : IEnumerator, IDisposable, IEnumerator { private int <>1__state; private object <>2__current; public GatheringListUI <>4__this; object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public d__10(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <>1__state = -2; } private bool MoveNext() { int num = <>1__state; GatheringListUI gatheringListUI = <>4__this; switch (num) { default: return false; case 0: <>1__state = -1; <>2__current = null; <>1__state = 1; return true; case 1: <>1__state = -1; if ((Object)(object)gatheringListUI.ItemListRoot != (Object)null) { Transform itemListRoot = gatheringListUI.ItemListRoot; LayoutRebuilder.ForceRebuildLayoutImmediate((RectTransform)(object)((itemListRoot is RectTransform) ? itemListRoot : null)); } if ((Object)(object)gatheringListUI.PanelRect != (Object)null) { LayoutRebuilder.ForceRebuildLayoutImmediate(gatheringListUI.PanelRect); } return false; } } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } public RectTransform PanelRect; public Image BgImage; public Text TitleText; public Transform ItemListRoot; public Text HintText; public List ItemSlots = new List(); private Coroutine _layoutCoroutine; public void SetActive(bool active) { ((Component)this).gameObject.SetActive(active); } public void RefreshLayout() { if (((Component)this).gameObject.activeInHierarchy) { if (_layoutCoroutine != null) { ((MonoBehaviour)this).StopCoroutine(_layoutCoroutine); } _layoutCoroutine = ((MonoBehaviour)this).StartCoroutine(FixLayout()); } } private void OnDisable() { _layoutCoroutine = null; } [IteratorStateMachine(typeof(d__10))] private IEnumerator FixLayout() { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new d__10(0) { <>4__this = this }; } } public class GatheringItemData { public string ItemName; public string DisplayName; public Sprite Icon; public int TotalRequired; public int TotalHave; public bool IsComplete; } public static class UIBuilder { private static Color ValheimOrange = new Color(1f, 0.77f, 0.31f, 1f); private static Color DividerColor = new Color(1f, 1f, 1f, 0.1f); private static Sprite _cachedUiSprite; private static bool _spriteSearchDone = false; private static Sprite GetBackgroundSprite() { if ((Object)(object)_cachedUiSprite != (Object)null) { return _cachedUiSprite; } if (_spriteSearchDone) { return null; } Sprite[] array = Resources.FindObjectsOfTypeAll(); Sprite val = null; Sprite[] array2 = array; foreach (Sprite val2 in array2) { if (!((Object)(object)val2 == (Object)null)) { if (((Object)val2).name == "UISprite") { _cachedUiSprite = val2; break; } if ((Object)(object)val == (Object)null && ((Object)val2).name == "Knob") { val = val2; } } } if ((Object)(object)_cachedUiSprite == (Object)null) { _cachedUiSprite = val; } _spriteSearchDone = true; if ((Object)(object)_cachedUiSprite != (Object)null) { DebugLogger.Verbose("Found background sprite: " + ((Object)_cachedUiSprite).name); } else { DebugLogger.Warning("No suitable background sprite found"); } return _cachedUiSprite; } public static PinSlotUI CreatePinSlot(Transform parent, Font font) { //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Expected O, but got Unknown //IL_0063: Unknown result type (might be due to invalid IL or missing references) //IL_0068: 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_00d9: Unknown result type (might be due to invalid IL or missing references) //IL_00de: Unknown result type (might be due to invalid IL or missing references) //IL_00e5: Unknown result type (might be due to invalid IL or missing references) //IL_00f7: Unknown result type (might be due to invalid IL or missing references) //IL_011d: Unknown result type (might be due to invalid IL or missing references) //IL_0127: Unknown result type (might be due to invalid IL or missing references) //IL_0138: Unknown result type (might be due to invalid IL or missing references) //IL_014d: 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_0177: Unknown result type (might be due to invalid IL or missing references) //IL_0181: Unknown result type (might be due to invalid IL or missing references) //IL_01c9: Unknown result type (might be due to invalid IL or missing references) //IL_01d3: Expected O, but got Unknown //IL_01fe: Unknown result type (might be due to invalid IL or missing references) //IL_0203: Unknown result type (might be due to invalid IL or missing references) //IL_020c: Expected O, but got Unknown //IL_028b: Unknown result type (might be due to invalid IL or missing references) //IL_0290: Unknown result type (might be due to invalid IL or missing references) //IL_0297: Unknown result type (might be due to invalid IL or missing references) //IL_02aa: Unknown result type (might be due to invalid IL or missing references) //IL_031d: 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_0329: Unknown result type (might be due to invalid IL or missing references) //IL_033c: Unknown result type (might be due to invalid IL or missing references) //IL_0377: Unknown result type (might be due to invalid IL or missing references) //IL_03bb: Unknown result type (might be due to invalid IL or missing references) //IL_03c0: Unknown result type (might be due to invalid IL or missing references) //IL_03c7: Unknown result type (might be due to invalid IL or missing references) //IL_03d9: Unknown result type (might be due to invalid IL or missing references) //IL_03f7: Unknown result type (might be due to invalid IL or missing references) //IL_03fc: Unknown result type (might be due to invalid IL or missing references) //IL_041c: Unknown result type (might be due to invalid IL or missing references) //IL_046b: Unknown result type (might be due to invalid IL or missing references) //IL_0470: Unknown result type (might be due to invalid IL or missing references) //IL_0479: Expected O, but got Unknown GameObject val = new GameObject("PinSlot", new Type[1] { typeof(RectTransform) }) { layer = 5 }; val.transform.SetParent(parent, false); PinSlotUI pinSlotUI = val.AddComponent(); pinSlotUI.Rect = val.GetComponent(); Image val2 = val.AddComponent(); Sprite val3 = (val2.sprite = GetBackgroundSprite()); if ((Object)(object)val3 != (Object)null && val3.border != Vector4.zero) { val2.type = (Type)1; } else { val2.type = (Type)0; } float num = ((RecipePinnerPlugin.BackgroundOpacity != null) ? RecipePinnerPlugin.BackgroundOpacity.Value : 0.45f); ((Graphic)val2).color = new Color(0f, 0f, 0f, num); ((Graphic)val2).raycastTarget = false; GameObject val4 = new GameObject("AccentBar", new Type[1] { typeof(RectTransform) }) { layer = 5 }; val4.transform.SetParent(val.transform, false); Image val5 = val4.AddComponent(); ((Graphic)val5).raycastTarget = false; ((Graphic)val5).color = new Color(0.9f, 0.25f, 0.25f, 0.5f); RectTransform component = val4.GetComponent(); component.anchorMin = new Vector2(0f, 0f); component.anchorMax = new Vector2(0f, 1f); component.pivot = new Vector2(0f, 0.5f); component.sizeDelta = new Vector2(4f, 0f); component.anchoredPosition = Vector2.zero; val4.AddComponent().ignoreLayout = true; pinSlotUI.AccentBar = val5; VerticalLayoutGroup obj = val.AddComponent(); ((HorizontalOrVerticalLayoutGroup)obj).childControlHeight = true; ((HorizontalOrVerticalLayoutGroup)obj).childControlWidth = true; ((HorizontalOrVerticalLayoutGroup)obj).childForceExpandHeight = false; ((HorizontalOrVerticalLayoutGroup)obj).spacing = 5f; ((LayoutGroup)obj).padding = new RectOffset(14, 8, 8, 8); ContentSizeFitter obj2 = val.AddComponent(); obj2.horizontalFit = (FitMode)0; obj2.verticalFit = (FitMode)2; GameObject val6 = new GameObject("HeaderRow", new Type[1] { typeof(RectTransform) }) { layer = 5 }; val6.transform.SetParent(val.transform, false); HorizontalLayoutGroup obj3 = val6.AddComponent(); ((HorizontalOrVerticalLayoutGroup)obj3).childControlHeight = true; ((HorizontalOrVerticalLayoutGroup)obj3).childControlWidth = true; ((HorizontalOrVerticalLayoutGroup)obj3).childForceExpandHeight = false; ((HorizontalOrVerticalLayoutGroup)obj3).childForceExpandWidth = false; ((HorizontalOrVerticalLayoutGroup)obj3).spacing = 8f; LayoutElement obj4 = val6.AddComponent(); obj4.minHeight = 30f; obj4.flexibleHeight = 0f; obj4.flexibleWidth = 1f; GameObject val7 = new GameObject("Icon", new Type[1] { typeof(RectTransform) }) { layer = 5 }; val7.transform.SetParent(val6.transform, false); Image val8 = val7.AddComponent(); ((Graphic)val8).raycastTarget = false; val8.preserveAspect = true; pinSlotUI.IconImage = val8; LayoutElement obj5 = val7.AddComponent(); obj5.minWidth = 28f; obj5.minHeight = 28f; obj5.preferredWidth = 28f; obj5.preferredHeight = 28f; obj5.flexibleWidth = 0f; GameObject val9 = new GameObject("Title", new Type[1] { typeof(RectTransform) }) { layer = 5 }; val9.transform.SetParent(val6.transform, false); Text val10 = val9.AddComponent(); ((Graphic)val10).raycastTarget = false; val10.font = font; val10.fontSize = 18; val10.alignment = (TextAnchor)3; val10.horizontalOverflow = (HorizontalWrapMode)0; val10.verticalOverflow = (VerticalWrapMode)1; ((Graphic)val10).color = ValheimOrange; pinSlotUI.HeaderText = val10; LayoutElement obj6 = val9.AddComponent(); obj6.minHeight = 24f; obj6.flexibleWidth = 1f; GameObject val11 = new GameObject("Divider", new Type[1] { typeof(RectTransform) }) { layer = 5 }; val11.transform.SetParent(val.transform, false); Image val12 = val11.AddComponent(); val12.sprite = GetBackgroundSprite(); if ((Object)(object)val3 != (Object)null && val3.border != Vector4.zero) { val12.type = (Type)1; } else { val12.type = (Type)0; } ((Graphic)val12).color = DividerColor; ((Graphic)val12).raycastTarget = false; LayoutElement obj7 = val11.AddComponent(); obj7.minHeight = 2f; obj7.preferredHeight = 2f; obj7.flexibleWidth = 1f; GameObject val13 = new GameObject("ResourceList", new Type[1] { typeof(RectTransform) }) { layer = 5 }; val13.transform.SetParent(val.transform, false); VerticalLayoutGroup obj8 = val13.AddComponent(); ((HorizontalOrVerticalLayoutGroup)obj8).childControlHeight = true; ((HorizontalOrVerticalLayoutGroup)obj8).childControlWidth = true; ((HorizontalOrVerticalLayoutGroup)obj8).childForceExpandHeight = false; ((HorizontalOrVerticalLayoutGroup)obj8).spacing = 3f; val13.AddComponent().verticalFit = (FitMode)2; pinSlotUI.ResourceListRoot = val13.transform; DebugLogger.Verbose("Created pin slot UI"); return pinSlotUI; } public static ResourceSlotUI CreateResourceSlot(Transform parent, Font font) { //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Expected O, but got Unknown //IL_009f: Unknown result type (might be due to invalid IL or missing references) //IL_00a4: Unknown result type (might be due to invalid IL or missing references) //IL_00ac: Expected O, but got Unknown //IL_0136: 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_0143: Expected O, but got Unknown //IL_01b8: Unknown result type (might be due to invalid IL or missing references) //IL_01ea: Unknown result type (might be due to invalid IL or missing references) //IL_01ef: Unknown result type (might be due to invalid IL or missing references) //IL_01f8: Expected O, but got Unknown GameObject val = new GameObject("ResSlot", new Type[1] { typeof(RectTransform) }) { layer = 5 }; val.transform.SetParent(parent, false); ResourceSlotUI resourceSlotUI = val.AddComponent(); HorizontalLayoutGroup obj = val.AddComponent(); ((HorizontalOrVerticalLayoutGroup)obj).childControlHeight = true; ((HorizontalOrVerticalLayoutGroup)obj).childControlWidth = true; ((HorizontalOrVerticalLayoutGroup)obj).childForceExpandHeight = false; ((HorizontalOrVerticalLayoutGroup)obj).childForceExpandWidth = false; ((LayoutGroup)obj).childAlignment = (TextAnchor)3; ((HorizontalOrVerticalLayoutGroup)obj).spacing = 6f; LayoutElement obj2 = val.AddComponent(); obj2.minHeight = 22f; obj2.flexibleHeight = 0f; GameObject val2 = new GameObject("Icon", new Type[1] { typeof(RectTransform) }) { layer = 5 }; val2.transform.SetParent(val.transform, false); resourceSlotUI.ResIcon = val2.AddComponent(); ((Graphic)resourceSlotUI.ResIcon).raycastTarget = false; resourceSlotUI.ResIcon.preserveAspect = true; LayoutElement obj3 = val2.AddComponent(); obj3.minWidth = 20f; obj3.minHeight = 20f; obj3.preferredWidth = 20f; obj3.preferredHeight = 20f; obj3.flexibleWidth = 0f; GameObject val3 = new GameObject("Name", new Type[1] { typeof(RectTransform) }) { layer = 5 }; val3.transform.SetParent(val.transform, false); resourceSlotUI.ResName = val3.AddComponent(); ((Graphic)resourceSlotUI.ResName).raycastTarget = false; resourceSlotUI.ResName.font = font; resourceSlotUI.ResName.fontSize = 15; resourceSlotUI.ResName.alignment = (TextAnchor)3; resourceSlotUI.ResName.horizontalOverflow = (HorizontalWrapMode)0; ((Graphic)resourceSlotUI.ResName).color = new Color(0.9f, 0.9f, 0.9f, 1f); val3.AddComponent().flexibleWidth = 1f; GameObject val4 = new GameObject("Amount", new Type[1] { typeof(RectTransform) }) { layer = 5 }; val4.transform.SetParent(val.transform, false); resourceSlotUI.ResAmount = val4.AddComponent(); ((Graphic)resourceSlotUI.ResAmount).raycastTarget = false; resourceSlotUI.ResAmount.font = font; resourceSlotUI.ResAmount.fontSize = 15; resourceSlotUI.ResAmount.alignment = (TextAnchor)5; val4.AddComponent().minWidth = 40f; DebugLogger.Verbose("Created resource slot UI"); return resourceSlotUI; } public static GameObject CreatePaginationContainer(Transform parent) { //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_0031: 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_0076: Unknown result type (might be due to invalid IL or missing references) //IL_008a: Expected O, but got Unknown GameObject val = new GameObject("PaginationDots", new Type[1] { typeof(RectTransform) }) { layer = 5 }; val.transform.SetParent(parent, false); val.AddComponent().ignoreLayout = true; HorizontalLayoutGroup obj = val.AddComponent(); ((HorizontalOrVerticalLayoutGroup)obj).childControlHeight = false; ((HorizontalOrVerticalLayoutGroup)obj).childControlWidth = false; ((HorizontalOrVerticalLayoutGroup)obj).childForceExpandHeight = false; ((HorizontalOrVerticalLayoutGroup)obj).childForceExpandWidth = false; ((HorizontalOrVerticalLayoutGroup)obj).spacing = RecipePinnerPlugin.PaginationDotSpacing.Value; ((LayoutGroup)obj).childAlignment = (TextAnchor)4; ContentSizeFitter obj2 = val.AddComponent(); obj2.horizontalFit = (FitMode)2; obj2.verticalFit = (FitMode)2; return val; } public static Image CreatePageDot(Transform parent) { //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_0031: 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_0074: Unknown result type (might be due to invalid IL or missing references) GameObject val = new GameObject("PageDot", new Type[1] { typeof(RectTransform) }) { layer = 5 }; val.transform.SetParent(parent, false); Image val2 = val.AddComponent(); val2.type = (Type)0; ((Graphic)val2).raycastTarget = false; int value = RecipePinnerPlugin.PaginationDotSize.Value; RectTransform component = val.GetComponent(); component.sizeDelta = new Vector2((float)value, (float)value); ((Transform)component).localRotation = Quaternion.Euler(0f, 0f, 45f); return val2; } public static GatheringListUI CreateGatheringListPanel(Transform parent, Font font, string title) { //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Expected O, but got Unknown //IL_0063: Unknown result type (might be due to invalid IL or missing references) //IL_0068: 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_00f3: Unknown result type (might be due to invalid IL or missing references) //IL_00fd: Expected O, but got Unknown //IL_0128: Unknown result type (might be due to invalid IL or missing references) //IL_012d: 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_0146: Unknown result type (might be due to invalid IL or missing references) //IL_0188: Unknown result type (might be due to invalid IL or missing references) //IL_01d4: Unknown result type (might be due to invalid IL or missing references) //IL_01d9: Unknown result type (might be due to invalid IL or missing references) //IL_01e0: 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_0210: 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_0235: Unknown result type (might be due to invalid IL or missing references) //IL_0284: Unknown result type (might be due to invalid IL or missing references) //IL_0289: Unknown result type (might be due to invalid IL or missing references) //IL_0292: Expected O, but got Unknown //IL_02b7: Unknown result type (might be due to invalid IL or missing references) //IL_02cc: Unknown result type (might be due to invalid IL or missing references) //IL_031c: Unknown result type (might be due to invalid IL or missing references) //IL_0321: Unknown result type (might be due to invalid IL or missing references) //IL_032a: Expected O, but got Unknown //IL_037d: Unknown result type (might be due to invalid IL or missing references) GameObject val = new GameObject("GatheringListPanel", new Type[1] { typeof(RectTransform) }) { layer = 5 }; val.transform.SetParent(parent, false); GatheringListUI gatheringListUI = val.AddComponent(); gatheringListUI.PanelRect = val.GetComponent(); Image val2 = val.AddComponent(); Sprite val3 = (val2.sprite = GetBackgroundSprite()); if ((Object)(object)val3 != (Object)null && val3.border != Vector4.zero) { val2.type = (Type)1; } else { val2.type = (Type)0; } float num = ((RecipePinnerPlugin.BackgroundOpacity != null) ? RecipePinnerPlugin.BackgroundOpacity.Value : 0.45f); ((Graphic)val2).color = new Color(0f, 0f, 0f, num); ((Graphic)val2).raycastTarget = false; gatheringListUI.BgImage = val2; VerticalLayoutGroup obj = val.AddComponent(); ((HorizontalOrVerticalLayoutGroup)obj).childControlHeight = true; ((HorizontalOrVerticalLayoutGroup)obj).childControlWidth = true; ((HorizontalOrVerticalLayoutGroup)obj).childForceExpandHeight = false; ((HorizontalOrVerticalLayoutGroup)obj).spacing = 4f; ((LayoutGroup)obj).padding = new RectOffset(14, 8, 8, 8); ContentSizeFitter obj2 = val.AddComponent(); obj2.horizontalFit = (FitMode)0; obj2.verticalFit = (FitMode)2; GameObject val4 = new GameObject("Header", new Type[1] { typeof(RectTransform) }) { layer = 5 }; val4.transform.SetParent(val.transform, false); Text val5 = val4.AddComponent(); ((Graphic)val5).raycastTarget = false; val5.font = font; int fontSize = ((RecipePinnerPlugin.GatheringListFontSizeTitle != null) ? RecipePinnerPlugin.GatheringListFontSizeTitle.Value : 15); val5.fontSize = fontSize; val5.alignment = (TextAnchor)4; ((Graphic)val5).color = ValheimOrange; val5.text = title; gatheringListUI.TitleText = val5; LayoutElement obj3 = val4.AddComponent(); obj3.minHeight = 24f; obj3.flexibleWidth = 1f; GameObject val6 = new GameObject("Divider", new Type[1] { typeof(RectTransform) }) { layer = 5 }; val6.transform.SetParent(val.transform, false); Image val7 = val6.AddComponent(); val7.sprite = GetBackgroundSprite(); if ((Object)(object)val3 != (Object)null && val3.border != Vector4.zero) { val7.type = (Type)1; } else { val7.type = (Type)0; } ((Graphic)val7).color = DividerColor; ((Graphic)val7).raycastTarget = false; LayoutElement obj4 = val6.AddComponent(); obj4.minHeight = 2f; obj4.preferredHeight = 2f; obj4.flexibleWidth = 1f; GameObject val8 = new GameObject("ItemList", new Type[1] { typeof(RectTransform) }) { layer = 5 }; val8.transform.SetParent(val.transform, false); GridLayoutGroup obj5 = val8.AddComponent(); obj5.cellSize = new Vector2(58f, 65f); obj5.spacing = new Vector2(4f, 3f); obj5.constraint = (Constraint)1; obj5.constraintCount = 4; ((LayoutGroup)obj5).childAlignment = (TextAnchor)1; val8.AddComponent().verticalFit = (FitMode)2; gatheringListUI.ItemListRoot = val8.transform; GameObject val9 = new GameObject("HintText", new Type[1] { typeof(RectTransform) }) { layer = 5 }; val9.transform.SetParent(val.transform, false); Text val10 = val9.AddComponent(); ((Graphic)val10).raycastTarget = false; val10.font = font; val10.fontSize = 20; val10.alignment = (TextAnchor)4; ((Graphic)val10).color = new Color(0.7f, 0.7f, 0.7f, 0.7f); val10.text = ""; gatheringListUI.HintText = val10; LayoutElement obj6 = val9.AddComponent(); obj6.minHeight = 22f; obj6.flexibleWidth = 1f; DebugLogger.Verbose("Created gathering list panel"); return gatheringListUI; } public static GatheringItemUI CreateGatheringItemSlot(Transform parent, Font font) { //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Expected O, but got Unknown //IL_0071: Unknown result type (might be due to invalid IL or missing references) //IL_007b: Expected O, but got Unknown //IL_0093: Unknown result type (might be due to invalid IL or missing references) //IL_0098: Unknown result type (might be due to invalid IL or missing references) //IL_00a0: Expected O, but got Unknown //IL_011f: Unknown result type (might be due to invalid IL or missing references) //IL_0124: Unknown result type (might be due to invalid IL or missing references) //IL_012c: Expected O, but got Unknown GameObject val = new GameObject("GatherItem", new Type[1] { typeof(RectTransform) }) { layer = 5 }; val.transform.SetParent(parent, false); GatheringItemUI gatheringItemUI = val.AddComponent(); VerticalLayoutGroup obj = val.AddComponent(); ((HorizontalOrVerticalLayoutGroup)obj).childControlHeight = true; ((HorizontalOrVerticalLayoutGroup)obj).childControlWidth = false; ((HorizontalOrVerticalLayoutGroup)obj).childForceExpandHeight = false; ((HorizontalOrVerticalLayoutGroup)obj).childForceExpandWidth = false; ((LayoutGroup)obj).childAlignment = (TextAnchor)1; ((HorizontalOrVerticalLayoutGroup)obj).spacing = 1f; ((LayoutGroup)obj).padding = new RectOffset(0, 0, 1, 0); GameObject val2 = new GameObject("Icon", new Type[1] { typeof(RectTransform) }) { layer = 5 }; val2.transform.SetParent(val.transform, false); gatheringItemUI.Icon = val2.AddComponent(); ((Graphic)gatheringItemUI.Icon).raycastTarget = false; gatheringItemUI.Icon.preserveAspect = true; LayoutElement obj2 = val2.AddComponent(); obj2.minWidth = 45f; obj2.minHeight = 45f; obj2.preferredWidth = 45f; obj2.preferredHeight = 45f; GameObject val3 = new GameObject("Amount", new Type[1] { typeof(RectTransform) }) { layer = 5 }; val3.transform.SetParent(val.transform, false); gatheringItemUI.AmountText = val3.AddComponent(); ((Graphic)gatheringItemUI.AmountText).raycastTarget = false; gatheringItemUI.AmountText.font = font; int fontSize = ((RecipePinnerPlugin.GatheringListFontSizeMaterials != null) ? RecipePinnerPlugin.GatheringListFontSizeMaterials.Value : 15); gatheringItemUI.AmountText.fontSize = fontSize; gatheringItemUI.AmountText.alignment = (TextAnchor)4; gatheringItemUI.AmountText.horizontalOverflow = (HorizontalWrapMode)1; val3.AddComponent().minHeight = 16f; return gatheringItemUI; } } public class PinSlotUI : MonoBehaviour { [CompilerGenerated] private sealed class d__17 : IEnumerator, IDisposable, IEnumerator { private int <>1__state; private object <>2__current; public PinSlotUI <>4__this; object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public d__17(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <>1__state = -2; } private bool MoveNext() { int num = <>1__state; PinSlotUI pinSlotUI = <>4__this; switch (num) { default: return false; case 0: <>1__state = -1; <>2__current = null; <>1__state = 1; return true; case 1: <>1__state = -1; if ((Object)(object)pinSlotUI.ResourceListRoot != (Object)null) { Transform resourceListRoot = pinSlotUI.ResourceListRoot; LayoutRebuilder.ForceRebuildLayoutImmediate((RectTransform)(object)((resourceListRoot is RectTransform) ? resourceListRoot : null)); } if ((Object)(object)pinSlotUI.Rect != (Object)null) { LayoutRebuilder.ForceRebuildLayoutImmediate(pinSlotUI.Rect); } if ((Object)(object)((Component)pinSlotUI).transform.parent != (Object)null) { Transform parent = ((Component)pinSlotUI).transform.parent; LayoutRebuilder.ForceRebuildLayoutImmediate((RectTransform)(object)((parent is RectTransform) ? parent : null)); } return false; } } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } public RectTransform Rect; public Image IconImage; public Text HeaderText; public Transform ResourceListRoot; public Image AccentBar; public PinnedRecipeData CurrentData; private Coroutine _layoutCoroutine; private Image _cachedBg; private ContentSizeFitter _cachedCsf; public List ResourceSlots = new List(); public Image BgImage { get { if (!Object.op_Implicit((Object)(object)_cachedBg)) { return _cachedBg = ((Component)this).GetComponent(); } return _cachedBg; } } public ContentSizeFitter Csf { get { if (!Object.op_Implicit((Object)(object)_cachedCsf)) { return _cachedCsf = ((Component)this).GetComponent(); } return _cachedCsf; } } public void SetActive(bool active) { ((Component)this).gameObject.SetActive(active); } public void UpdateData(PinnedRecipeData data, Font font) { //IL_004e: Unknown result type (might be due to invalid IL or missing references) IconImage.sprite = data.Icon; HeaderText.text = data.CachedHeader; HeaderText.font = font; HeaderText.fontSize = RecipePinnerPlugin.FontSizeRecipeName.Value; ((Graphic)HeaderText).color = RecipePinnerPlugin.ColorHeader.Value; int count = data.Resources.Count; while (ResourceSlots.Count < count) { ResourceSlots.Add(UIBuilder.CreateResourceSlot(ResourceListRoot, font)); } for (int i = 0; i < ResourceSlots.Count; i++) { if (i < count) { ResourceSlots[i].SetActive(active: true); ResourceSlots[i].UpdateResource(data.Resources[i]); } else { ResourceSlots[i].SetActive(active: false); } } if (((Component)this).gameObject.activeInHierarchy) { if (_layoutCoroutine != null) { ((MonoBehaviour)this).StopCoroutine(_layoutCoroutine); } _layoutCoroutine = ((MonoBehaviour)this).StartCoroutine(FixLayout()); } } private void OnDisable() { _layoutCoroutine = null; } [IteratorStateMachine(typeof(d__17))] private IEnumerator FixLayout() { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new d__17(0) { <>4__this = this }; } } public class ResourceSlotUI : MonoBehaviour { public Image ResIcon; public Text ResName; public Text ResAmount; public void SetActive(bool active) { ((Component)this).gameObject.SetActive(active); } public void UpdateResource(PinnedResData res) { ResIcon.sprite = res.Icon; ResName.text = res.CachedName; ResAmount.text = res.CachedAmountString; if (RecipePinnerPlugin.FontSizeMaterials != null) { int value = RecipePinnerPlugin.FontSizeMaterials.Value; ResName.fontSize = value; ResAmount.fontSize = value; } } } public class UIManager { private Transform _pinListRoot; private readonly List _pinPool = new List(); private Font _cachedFont; private readonly Dictionary _reusableInvCounts = new Dictionary(); private int _currentPage; private GameObject _paginationRoot; private readonly List _pageDots = new List(); private GatheringListUI _gatheringListPanel; private bool _gatheringListVisible; private bool _gatheringListRepositioned; private readonly List _gatheringData = new List(); private readonly Dictionary _gatheringAggregator = new Dictionary(); private int _previousPinCount; private string _lastHintKey; public void DestroyUI() { DebugLogger.Verbose("DestroyUI"); if ((Object)(object)_pinListRoot != (Object)null) { Object.Destroy((Object)(object)((Component)_pinListRoot).gameObject); _pinListRoot = null; } _pinPool?.Clear(); _pageDots.Clear(); _paginationRoot = null; if ((Object)(object)_gatheringListPanel != (Object)null) { Object.Destroy((Object)(object)((Component)_gatheringListPanel).gameObject); _gatheringListPanel = null; } _gatheringData.Clear(); _gatheringAggregator.Clear(); _lastHintKey = null; _previousPinCount = 0; DebugLogger.Log("UI destroyed"); } public void ResetPage() { _currentPage = 0; } public void CyclePage() { int count = RecipePinnerPlugin.Instance.RecipeMgr.CachedPins.Count; int value = RecipePinnerPlugin.PinsPerPage.Value; if (count > value) { int num = Mathf.CeilToInt((float)count / (float)value); _currentPage++; if (_currentPage >= num) { _currentPage = 0; } DebugLogger.Log($"Switched to Page: {_currentPage + 1}/{num}"); UpdateUI(isVisible: true); } } public void UpdateUI(bool isVisible) { //IL_02e1: Unknown result type (might be due to invalid IL or missing references) //IL_02eb: Unknown result type (might be due to invalid IL or missing references) //IL_033d: Unknown result type (might be due to invalid IL or missing references) //IL_0305: Unknown result type (might be due to invalid IL or missing references) //IL_031b: Unknown result type (might be due to invalid IL or missing references) //IL_0331: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)Player.m_localPlayer == (Object)null || ((Character)Player.m_localPlayer).IsDead()) { return; } Inventory inventory = ((Humanoid)Player.m_localPlayer).GetInventory(); if (inventory == null) { return; } RecipePinnerPlugin instance = RecipePinnerPlugin.Instance; RecipeManager recipeMgr = instance.RecipeMgr; ContainerScanner containerMgr = instance.ContainerMgr; if (_pinPool.Count < RecipePinnerPlugin.MaximumPins.Value) { DebugLogger.Log($"Pin limit changed ({_pinPool.Count} -> {RecipePinnerPlugin.MaximumPins.Value}), rebuilding"); DestroyUI(); } if ((Object)(object)_pinListRoot == (Object)null) { _pinPool.Clear(); CreateCanvasUI(); if ((Object)(object)_pinListRoot == (Object)null) { return; } foreach (PinnedRecipeData cachedPin in recipeMgr.CachedPins) { cachedPin.IsDirty = true; } } UpdateLayout(); if ((Object)(object)_pinListRoot == (Object)null) { return; } bool flag = (Object)(object)InventoryGui.instance != (Object)null && InventoryGui.IsVisible(); bool flag2 = isVisible && !InputHelper.IsInputBlocked() && recipeMgr.CachedPins.Count > 0; if (!flag2 && _gatheringListVisible && (Object)(object)_gatheringListPanel != (Object)null && recipeMgr.CachedPins.Count > 0) { if (!((Component)_pinListRoot).gameObject.activeSelf) { ((Component)_pinListRoot).gameObject.SetActive(true); } for (int i = 0; i < _pinPool.Count; i++) { if ((Object)(object)_pinPool[i] != (Object)null && ((Component)_pinPool[i]).gameObject.activeSelf) { _pinPool[i].SetActive(active: false); } } if ((Object)(object)_paginationRoot != (Object)null && _paginationRoot.activeSelf) { _paginationRoot.SetActive(false); } _gatheringListPanel.SetActive(active: true); (((Component)_gatheringListPanel).GetComponent() ?? ((Component)_gatheringListPanel).gameObject.AddComponent()).ignoreLayout = true; RectTransform panelRect = _gatheringListPanel.PanelRect; bool num = RecipePinnerPlugin.LayoutModeConfig.Value == RecipePinnerPlugin.PinLayoutMode.ForceBottomRightHorizontal; bool flag3 = (Object)(object)Player.m_localPlayer.GetControlledShip() != (Object)null; bool num2 = num || flag3 || flag; bool flag4 = RecipePinnerPlugin.Instance.IsHorizontalMode || flag3 || flag; float num3 = (num2 ? RecipePinnerPlugin.BottomRightColumnWidth.Value : (flag4 ? RecipePinnerPlugin.HorizontalColumnWidth.Value : RecipePinnerPlugin.VerticalListWidth.Value)); if (flag && (Object)(object)ReflectionHelper.GetCurrentContainer(InventoryGui.instance) != (Object)null) { RepositionGatheringListForInventory(); } else { if (_gatheringListRepositioned) { RestoreGatheringListParent(); _gatheringListRepositioned = false; } panelRect.sizeDelta = new Vector2(num3, panelRect.sizeDelta.y); if (!flag4) { panelRect.anchorMin = new Vector2(0.5f, 1f); panelRect.anchorMax = new Vector2(0.5f, 1f); panelRect.pivot = new Vector2(0.5f, 1f); } panelRect.anchoredPosition = Vector2.zero; } Inventory inventory2 = ((Humanoid)Player.m_localPlayer).GetInventory(); if (inventory2 != null) { _reusableInvCounts.Clear(); foreach (ItemData allItem in inventory2.GetAllItems()) { string name = allItem.m_shared.m_name; if (_reusableInvCounts.TryGetValue(name, out var value)) { _reusableInvCounts[name] = value + allItem.m_stack; } else { _reusableInvCounts[name] = allItem.m_stack; } } } UpdateGatheringList(); return; } if (((Component)_pinListRoot).gameObject.activeSelf != flag2) { ((Component)_pinListRoot).gameObject.SetActive(flag2); } if (!flag2) { if (_gatheringListRepositioned && (Object)(object)_gatheringListPanel != (Object)null) { RestoreGatheringListParent(); _gatheringListRepositioned = false; _gatheringListPanel.SetActive(_gatheringListVisible); } return; } if (flag && (Object)(object)_gatheringListPanel != (Object)null && recipeMgr.CachedPins.Count > 0 && _gatheringListVisible) { bool num4 = (Object)(object)ReflectionHelper.GetCurrentContainer(InventoryGui.instance) != (Object)null; _gatheringListPanel.SetActive(active: true); if (num4) { RepositionGatheringListForInventory(); } } else if (_gatheringListRepositioned && (Object)(object)_gatheringListPanel != (Object)null) { RestoreGatheringListParent(); _gatheringListRepositioned = false; _gatheringListPanel.SetActive(_gatheringListVisible); } int count = recipeMgr.CachedPins.Count; if (RecipePinnerPlugin.AutoOpenGatheringList.Value && RecipePinnerPlugin.EnableGatheringList.Value && !_gatheringListVisible && count >= 2 && _previousPinCount < 2) { _gatheringListVisible = true; _gatheringListPanel?.SetActive(active: true); DebugLogger.Log("Gathering list auto-opened (2+ pins detected)"); } if (_gatheringListVisible && count < 2 && _previousPinCount >= 2) { _gatheringListVisible = false; _gatheringListPanel?.SetActive(active: false); DebugLogger.Log("Gathering list auto-closed (less than 2 pins)"); } _previousPinCount = count; _reusableInvCounts.Clear(); foreach (ItemData allItem2 in inventory.GetAllItems()) { string name2 = allItem2.m_shared.m_name; if (_reusableInvCounts.TryGetValue(name2, out var value2)) { _reusableInvCounts[name2] = value2 + allItem2.m_stack; } else { _reusableInvCounts[name2] = allItem2.m_stack; } } int count2 = recipeMgr.CachedPins.Count; int value3 = RecipePinnerPlugin.PinsPerPage.Value; int num5 = _currentPage * value3; if (num5 >= count2 && _currentPage > 0) { _currentPage--; num5 = _currentPage * value3; } int num6 = Mathf.Min(num5 + value3, count2); for (int j = 0; j < _pinPool.Count; j++) { if (!((Object)(object)_pinPool[j] == (Object)null)) { int num7 = num5 + j; if (num7 < num6) { UpdatePinSlot(j, recipeMgr.CachedPins[num7], containerMgr); } else if (((Component)_pinPool[j]).gameObject.activeSelf) { _pinPool[j].SetActive(active: false); } } } bool flag5 = (Object)(object)Player.m_localPlayer.GetControlledShip() != (Object)null; bool flag6 = (Object)(object)InventoryGui.instance != (Object)null && InventoryGui.IsVisible(); bool isHorizontal = RecipePinnerPlugin.Instance.IsHorizontalMode || flag5 || flag6; EqualizePinHeights(num5, num6, isHorizontal); int totalPages = 1; if (count2 > 0) { totalPages = Mathf.CeilToInt((float)count2 / (float)value3); } UpdatePageDots(totalPages); UpdateGatheringList(); } private void UpdatePageDots(int totalPages) { //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_011a: Unknown result type (might be due to invalid IL or missing references) //IL_011b: Unknown result type (might be due to invalid IL or missing references) //IL_013a: Unknown result type (might be due to invalid IL or missing references) //IL_0156: Unknown result type (might be due to invalid IL or missing references) //IL_00e7: 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) if ((Object)(object)_paginationRoot == (Object)null) { return; } HorizontalLayoutGroup component = _paginationRoot.GetComponent(); if ((Object)(object)component != (Object)null) { ((HorizontalOrVerticalLayoutGroup)component).spacing = RecipePinnerPlugin.PaginationDotSpacing.Value; } if (totalPages <= 1) { if (_paginationRoot.activeSelf) { _paginationRoot.SetActive(false); } return; } if (!_paginationRoot.activeSelf) { _paginationRoot.SetActive(true); } while (_pageDots.Count < totalPages) { _pageDots.Add(UIBuilder.CreatePageDot(_paginationRoot.transform)); } int value = RecipePinnerPlugin.PaginationDotSize.Value; Color value2 = RecipePinnerPlugin.ColorPaginationActive.Value; for (int i = 0; i < _pageDots.Count; i++) { if (i < totalPages) { ((Component)_pageDots[i]).gameObject.SetActive(true); if (i == _currentPage) { ((Graphic)_pageDots[i]).color = value2; ((Graphic)_pageDots[i]).rectTransform.sizeDelta = new Vector2((float)value * 1.2f, (float)value * 1.2f); continue; } Color color = value2; color.a = RecipePinnerPlugin.PaginationInactiveOpacity.Value; ((Graphic)_pageDots[i]).color = color; ((Graphic)_pageDots[i]).rectTransform.sizeDelta = new Vector2((float)value, (float)value); } else { ((Component)_pageDots[i]).gameObject.SetActive(false); } } } private void UpdateDotsPosition() { //IL_0149: Unknown result type (might be due to invalid IL or missing references) //IL_015e: 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_0188: Unknown result type (might be due to invalid IL or missing references) //IL_00f7: Unknown result type (might be due to invalid IL or missing references) //IL_010c: Unknown result type (might be due to invalid IL or missing references) //IL_0121: Unknown result type (might be due to invalid IL or missing references) //IL_0133: Unknown result type (might be due to invalid IL or missing references) //IL_00a5: Unknown result type (might be due to invalid IL or missing references) //IL_00ba: Unknown result type (might be due to invalid IL or missing references) //IL_00cf: Unknown result type (might be due to invalid IL or missing references) //IL_00e1: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_paginationRoot == (Object)null || (Object)(object)_pinListRoot == (Object)null) { return; } RectTransform component = _paginationRoot.GetComponent(); bool flag = RecipePinnerPlugin.LayoutModeConfig.Value == RecipePinnerPlugin.PinLayoutMode.ForceBottomRightHorizontal; bool flag2 = (Object)(object)Player.m_localPlayer.GetControlledShip() != (Object)null; bool flag3 = (Object)(object)InventoryGui.instance != (Object)null && InventoryGui.IsVisible(); if (RecipePinnerPlugin.Instance.IsHorizontalMode || flag2 || flag3) { bool num = flag || flag2 || flag3; float num2 = 0f - (num ? RecipePinnerPlugin.BottomRightColumnWidth.Value : RecipePinnerPlugin.HorizontalColumnWidth.Value) / 2f; if (num) { component.anchorMin = new Vector2(1f, 0f); component.anchorMax = new Vector2(1f, 0f); component.pivot = new Vector2(0.5f, 1f); component.anchoredPosition = new Vector2(num2, -15f); } else { component.anchorMin = new Vector2(1f, 1f); component.anchorMax = new Vector2(1f, 1f); component.pivot = new Vector2(0.5f, 0f); component.anchoredPosition = new Vector2(num2, 15f); } } else { component.anchorMin = new Vector2(0.5f, 1f); component.anchorMax = new Vector2(0.5f, 1f); component.pivot = new Vector2(0.5f, 0f); component.anchoredPosition = new Vector2(0f, 20f); } } private void EqualizePinHeights(int startIndex, int endIndex, bool isHorizontal) { //IL_0052: Unknown result type (might be due to invalid IL or missing references) //IL_0058: Invalid comparison between Unknown and I4 //IL_0037: Unknown result type (might be due to invalid IL or missing references) for (int i = 0; i < _pinPool.Count; i++) { PinSlotUI pinSlotUI = _pinPool[i]; if ((Object)(object)pinSlotUI?.Csf == (Object)null) { continue; } bool flag = startIndex + i < endIndex; if (isHorizontal && flag) { if ((int)pinSlotUI.Csf.verticalFit != 0) { pinSlotUI.Csf.verticalFit = (FitMode)0; } } else if ((int)pinSlotUI.Csf.verticalFit != 2) { pinSlotUI.Csf.verticalFit = (FitMode)2; } } } private void UpdatePinSlot(int index, PinnedRecipeData pinData, ContainerScanner containerMgr) { //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_008d: Unknown result type (might be due to invalid IL or missing references) //IL_010f: Unknown result type (might be due to invalid IL or missing references) //IL_012e: Unknown result type (might be due to invalid IL or missing references) //IL_0138: Unknown result type (might be due to invalid IL or missing references) //IL_0219: Unknown result type (might be due to invalid IL or missing references) //IL_021e: Unknown result type (might be due to invalid IL or missing references) //IL_0225: Unknown result type (might be due to invalid IL or missing references) //IL_020d: Unknown result type (might be due to invalid IL or missing references) //IL_0201: Unknown result type (might be due to invalid IL or missing references) //IL_0330: Unknown result type (might be due to invalid IL or missing references) //IL_0324: Unknown result type (might be due to invalid IL or missing references) //IL_0335: Unknown result type (might be due to invalid IL or missing references) //IL_033d: Unknown result type (might be due to invalid IL or missing references) //IL_0342: Unknown result type (might be due to invalid IL or missing references) //IL_0351: Unknown result type (might be due to invalid IL or missing references) PinSlotUI pinSlotUI = _pinPool[index]; if ((Object)(object)pinSlotUI == (Object)null || (Object)(object)((Component)pinSlotUI).gameObject == (Object)null) { return; } if (!((Component)pinSlotUI).gameObject.activeSelf) { pinSlotUI.SetActive(active: true); } if ((Object)(object)pinSlotUI.BgImage != (Object)null && Mathf.Abs(((Graphic)pinSlotUI.BgImage).color.a - RecipePinnerPlugin.BackgroundOpacity.Value) > 0.01f) { ((Graphic)pinSlotUI.BgImage).color = new Color(0f, 0f, 0f, RecipePinnerPlugin.BackgroundOpacity.Value); } bool flag = RecipePinnerPlugin.LayoutModeConfig.Value == RecipePinnerPlugin.PinLayoutMode.ForceBottomRightHorizontal; bool flag2 = (Object)(object)Player.m_localPlayer.GetControlledShip() != (Object)null; bool flag3 = (Object)(object)InventoryGui.instance != (Object)null && InventoryGui.IsVisible(); if (RecipePinnerPlugin.Instance.IsHorizontalMode || flag2 || flag3) { RectTransform val = pinSlotUI.Rect ?? ((Component)pinSlotUI).GetComponent(); float num = ((flag || flag2 || flag3) ? RecipePinnerPlugin.BottomRightColumnWidth.Value : RecipePinnerPlugin.HorizontalColumnWidth.Value); if (Mathf.Abs(val.sizeDelta.x - num) > 1f) { val.sizeDelta = new Vector2(num, val.sizeDelta.y); } } bool flag4 = pinSlotUI.CurrentData != pinData; pinSlotUI.CurrentData = pinData; foreach (PinnedResData resource in pinData.Resources) { _reusableInvCounts.TryGetValue(resource.ItemName, out var value); int value2 = 0; if (RecipePinnerPlugin.EnableChestScanning.Value) { containerMgr.ContainerCache.TryGetValue(resource.ItemName, out value2); } int num2 = value + value2; if (num2 != resource.LastKnownAmount || value != resource.LastKnownInvAmount || resource.CachedAmountString == null) { resource.LastKnownAmount = num2; resource.LastKnownInvAmount = value; Color val2 = ((value >= resource.RequiredAmount) ? RecipePinnerPlugin.ColorEnoughInInventory.Value : ((num2 >= resource.RequiredAmount) ? RecipePinnerPlugin.ColorEnoughWithChests.Value : RecipePinnerPlugin.ColorMissing.Value)); string arg = "#" + ColorUtility.ToHtmlStringRGBA(val2); string text = $"{num2}/{resource.RequiredAmount}"; if (resource.CachedAmountString != text) { resource.CachedAmountString = text; pinData.IsDirty = true; } } } if ((Object)(object)pinSlotUI.AccentBar != (Object)null) { if (RecipePinnerPlugin.EnableCraftReadiness.Value) { if (!((Component)pinSlotUI.AccentBar).gameObject.activeSelf) { ((Component)pinSlotUI.AccentBar).gameObject.SetActive(true); } bool flag5 = true; for (int i = 0; i < pinData.Resources.Count; i++) { if (pinData.Resources[i].LastKnownAmount < pinData.Resources[i].RequiredAmount) { flag5 = false; break; } } Color val3 = (flag5 ? RecipePinnerPlugin.ColorCraftReady.Value : RecipePinnerPlugin.ColorCraftNotReady.Value); if (((Graphic)pinSlotUI.AccentBar).color != val3) { ((Graphic)pinSlotUI.AccentBar).color = val3; } } else if (((Component)pinSlotUI.AccentBar).gameObject.activeSelf) { ((Component)pinSlotUI.AccentBar).gameObject.SetActive(false); } } if (flag4 || pinData.IsDirty) { pinSlotUI.UpdateData(pinData, _cachedFont); pinData.IsDirty = false; } } private void CreateCanvasUI() { //IL_009e: Unknown result type (might be due to invalid IL or missing references) //IL_00a3: Unknown result type (might be due to invalid IL or missing references) //IL_00ab: Expected O, but got Unknown //IL_00ca: 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_00f4: 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_011d: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_pinListRoot != (Object)null) { return; } if ((Object)(object)Hud.instance == (Object)null || (Object)(object)Hud.instance.m_rootObject == (Object)null) { DebugLogger.Warning("Cannot create canvas - Hud.instance is null"); return; } if ((Object)(object)_cachedFont == (Object)null) { _cachedFont = GetGameFont(); } if ((Object)(object)_cachedFont == (Object)null) { DebugLogger.Error("Cannot create UI - no valid font found"); return; } DebugLogger.Log("CreateCanvasUI"); Transform transform = Hud.instance.m_rootObject.transform; GameObject val = new GameObject("PinListRoot", new Type[1] { typeof(RectTransform) }) { layer = 5 }; val.transform.SetParent(transform, false); _pinListRoot = val.transform; _pinListRoot.localScale = Vector3.one * RecipePinnerPlugin.UIScale.Value; RectTransform component = val.GetComponent(); component.anchorMin = new Vector2(1f, 1f); component.anchorMax = new Vector2(1f, 1f); component.pivot = new Vector2(1f, 1f); bool flag = (Object)(object)Player.m_localPlayer != (Object)null && (Object)(object)Player.m_localPlayer.GetControlledShip() != (Object)null; bool flag2 = RecipePinnerPlugin.LayoutModeConfig.Value == RecipePinnerPlugin.PinLayoutMode.ForceBottomRightHorizontal; bool flag3 = (Object)(object)InventoryGui.instance != (Object)null && InventoryGui.IsVisible(); bool flag4 = flag || flag2 || flag3; bool flag5 = RecipePinnerPlugin.Instance.IsHorizontalMode || flag || flag3; DebugLogger.Verbose($"UI Layout - Horizontal: {flag5}, BottomRight: {flag4}, Sailing: {flag}"); if (flag5) { HorizontalLayoutGroup obj = val.AddComponent(); ((HorizontalOrVerticalLayoutGroup)obj).childControlHeight = true; ((HorizontalOrVerticalLayoutGroup)obj).childControlWidth = false; ((HorizontalOrVerticalLayoutGroup)obj).childForceExpandHeight = true; ((HorizontalOrVerticalLayoutGroup)obj).childForceExpandWidth = false; ((LayoutGroup)obj).childAlignment = (TextAnchor)(flag4 ? 8 : 2); ((HorizontalOrVerticalLayoutGroup)obj).spacing = RecipePinnerPlugin.HorizontalPinSpacing.Value; ContentSizeFitter obj2 = val.AddComponent(); obj2.horizontalFit = (FitMode)2; obj2.verticalFit = (FitMode)2; } else { VerticalLayoutGroup obj3 = val.AddComponent(); ((HorizontalOrVerticalLayoutGroup)obj3).childControlHeight = true; ((HorizontalOrVerticalLayoutGroup)obj3).childControlWidth = true; ((HorizontalOrVerticalLayoutGroup)obj3).childForceExpandHeight = false; ((HorizontalOrVerticalLayoutGroup)obj3).spacing = 8f; val.AddComponent().verticalFit = (FitMode)2; } for (int i = 0; i < RecipePinnerPlugin.MaximumPins.Value; i++) { PinSlotUI pinSlotUI = UIBuilder.CreatePinSlot(_pinListRoot, _cachedFont); if ((Object)(object)pinSlotUI != (Object)null) { pinSlotUI.SetActive(active: false); _pinPool.Add(pinSlotUI); } } _paginationRoot = UIBuilder.CreatePaginationContainer(_pinListRoot); _paginationRoot.transform.SetAsLastSibling(); if (RecipePinnerPlugin.EnableGatheringList.Value) { string title = RecipePinnerPlugin.Instance?.LocalizationMgr?.GetText("gathering_title") ?? "TOTAL NEEDS"; _gatheringListPanel = UIBuilder.CreateGatheringListPanel(_pinListRoot, _cachedFont, title); _gatheringListPanel.SetActive(_gatheringListVisible); DebugLogger.Log("Gathering list panel ready"); } DebugLogger.Log($"UI ready ({_pinPool.Count} slots)"); } private void UpdateLayout() { //IL_008c: Unknown result type (might be due to invalid IL or missing references) //IL_00a8: Unknown result type (might be due to invalid IL or missing references) //IL_00b7: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_pinListRoot == (Object)null) { return; } RecipePinnerPlugin instance = RecipePinnerPlugin.Instance; bool num = RecipePinnerPlugin.LayoutModeConfig.Value == RecipePinnerPlugin.PinLayoutMode.ForceBottomRightHorizontal; bool flag = !num && (Object)(object)Player.m_localPlayer.GetControlledShip() != (Object)null; bool flag2 = (Object)(object)InventoryGui.instance != (Object)null && InventoryGui.IsVisible(); bool flag3 = num || flag || flag2; bool flag4 = instance.IsHorizontalMode || flag || flag2; bool flag5 = (Object)(object)((Component)_pinListRoot).GetComponent() != (Object)null; if (flag4 != flag5) { DebugLogger.Log("Layout mode changed - rebuilding UI"); DestroyUI(); return; } if (_pinListRoot.localScale.x != RecipePinnerPlugin.UIScale.Value) { _pinListRoot.localScale = Vector3.one * RecipePinnerPlugin.UIScale.Value; } RectTransform component = ((Component)_pinListRoot).GetComponent(); if (flag4) { UpdateHorizontalLayout(component, flag3); } else { UpdateVerticalLayout(component); } UpdateDotsPosition(); UpdateGatheringListPosition(flag4, flag3); } private void UpdateHorizontalLayout(RectTransform rootRect, bool isBottomRightMode) { //IL_00e1: Unknown result type (might be due to invalid IL or missing references) //IL_00f0: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_0107: Unknown result type (might be due to invalid IL or missing references) //IL_011c: Unknown result type (might be due to invalid IL or missing references) //IL_0131: 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_004e: Unknown result type (might be due to invalid IL or missing references) //IL_0063: Unknown result type (might be due to invalid IL or missing references) //IL_0145: Unknown result type (might be due to invalid IL or missing references) //IL_014b: Invalid comparison between Unknown and I4 //IL_0077: Unknown result type (might be due to invalid IL or missing references) //IL_007d: Invalid comparison between Unknown and I4 //IL_018f: Unknown result type (might be due to invalid IL or missing references) //IL_0194: Unknown result type (might be due to invalid IL or missing references) //IL_00c1: 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) //IL_00c8: Unknown result type (might be due to invalid IL or missing references) //IL_00cd: Unknown result type (might be due to invalid IL or missing references) //IL_01fd: Unknown result type (might be due to invalid IL or missing references) //IL_0202: 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_020b: Unknown result type (might be due to invalid IL or missing references) //IL_01b4: Unknown result type (might be due to invalid IL or missing references) //IL_01d8: Unknown result type (might be due to invalid IL or missing references) HorizontalLayoutGroup component = ((Component)_pinListRoot).GetComponent(); if (isBottomRightMode) { if (rootRect.anchorMin != new Vector2(1f, 0f)) { rootRect.anchorMin = new Vector2(1f, 0f); rootRect.anchorMax = new Vector2(1f, 0f); rootRect.pivot = new Vector2(1f, 0f); } if ((Object)(object)component != (Object)null && (int)((LayoutGroup)component).childAlignment != 8) { ((LayoutGroup)component).childAlignment = (TextAnchor)8; } if ((Object)(object)component != (Object)null && Mathf.Abs(((HorizontalOrVerticalLayoutGroup)component).spacing - RecipePinnerPlugin.BottomRightPinSpacing.Value) > 0.01f) { ((HorizontalOrVerticalLayoutGroup)component).spacing = RecipePinnerPlugin.BottomRightPinSpacing.Value; } Vector2 value = RecipePinnerPlugin.BottomRightPosition.Value; if (rootRect.anchoredPosition != value) { rootRect.anchoredPosition = value; } return; } if (rootRect.anchorMin != new Vector2(1f, 1f)) { rootRect.anchorMin = new Vector2(1f, 1f); rootRect.anchorMax = new Vector2(1f, 1f); rootRect.pivot = new Vector2(1f, 1f); } if ((Object)(object)component != (Object)null && (int)((LayoutGroup)component).childAlignment != 2) { ((LayoutGroup)component).childAlignment = (TextAnchor)2; } if ((Object)(object)component != (Object)null && Mathf.Abs(((HorizontalOrVerticalLayoutGroup)component).spacing - RecipePinnerPlugin.HorizontalPinSpacing.Value) > 0.01f) { ((HorizontalOrVerticalLayoutGroup)component).spacing = RecipePinnerPlugin.HorizontalPinSpacing.Value; } Vector2 value2 = RecipePinnerPlugin.HorizontalPosition.Value; if (Game.m_noMap && RecipePinnerPlugin.Instance._mluiInstalled && RecipePinnerPlugin.Instance._mluiNoMapListEnabled) { if (Mathf.Abs(value2.x - -250f) < 1f) { value2.x = -270f; } if (Mathf.Abs(value2.y - -40f) < 1f) { value2.y = -15f; } } if (rootRect.anchoredPosition != value2) { rootRect.anchoredPosition = value2; } } private void UpdateVerticalLayout(RectTransform rootRect) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0010: 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_003c: Unknown result type (might be due to invalid IL or missing references) //IL_0051: Unknown result type (might be due to invalid IL or missing references) //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_00d9: Unknown result type (might be due to invalid IL or missing references) //IL_00de: Unknown result type (might be due to invalid IL or missing references) //IL_00ee: Unknown result type (might be due to invalid IL or missing references) //IL_00e7: 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) if (rootRect.anchorMin != new Vector2(1f, 1f)) { rootRect.anchorMin = new Vector2(1f, 1f); rootRect.anchorMax = new Vector2(1f, 1f); rootRect.pivot = new Vector2(1f, 1f); } VerticalLayoutGroup component = ((Component)_pinListRoot).GetComponent(); if ((Object)(object)component != (Object)null && Mathf.Abs(((HorizontalOrVerticalLayoutGroup)component).spacing - RecipePinnerPlugin.VerticalPinSpacing.Value) > 0.01f) { ((HorizontalOrVerticalLayoutGroup)component).spacing = RecipePinnerPlugin.VerticalPinSpacing.Value; } Vector2 value = RecipePinnerPlugin.VerticalPosition.Value; if (RecipePinnerPlugin.Instance.RecipeMgr.CachedPins.Count > RecipePinnerPlugin.PinsPerPage.Value) { value.y -= 30f; } if (rootRect.anchoredPosition != value) { rootRect.anchoredPosition = value; } if (Mathf.Abs(rootRect.sizeDelta.x - RecipePinnerPlugin.VerticalListWidth.Value) > 1f) { rootRect.sizeDelta = new Vector2(RecipePinnerPlugin.VerticalListWidth.Value, 0f); } } private Font GetGameFont() { Font[] array = Resources.FindObjectsOfTypeAll(); Font[] array2 = array; foreach (Font val in array2) { if ((Object)(object)val != (Object)null && ((Object)val).name == "AveriaSerifLibre-Bold") { DebugLogger.Log("Found game font: AveriaSerifLibre-Bold"); return val; } } array2 = array; foreach (Font val2 in array2) { if ((Object)(object)val2 != (Object)null && ((Object)val2).name == "Arial") { DebugLogger.Log("Using fallback font: Arial"); return val2; } } try { DebugLogger.Log("Creating dynamic font from OS: Arial"); return Font.CreateDynamicFontFromOSFont("Arial", 14); } catch { DebugLogger.Warning("Failed to create dynamic font, using first available font"); return (array.Length != 0) ? array[0] : null; } } public void ToggleGatheringList() { RecipeManager recipeManager = RecipePinnerPlugin.Instance?.RecipeMgr; if (!_gatheringListVisible && (recipeManager == null || recipeManager.CachedPins.Count == 0)) { DebugLogger.Log("Gathering list toggle blocked: no pins"); if ((Object)(object)Player.m_localPlayer != (Object)null) { string text = (RecipePinnerPlugin.Instance?.LocalizationMgr)?.GetText("gathering_empty") ?? "No Recipes Pinned"; ((Character)Player.m_localPlayer).Message((MessageType)2, text, 0, (Sprite)null); } return; } _gatheringListVisible = !_gatheringListVisible; DebugLogger.Log($"Gathering list toggled: {_gatheringListVisible}"); _gatheringListPanel?.SetActive(_gatheringListVisible); if ((Object)(object)Player.m_localPlayer != (Object)null) { LocalizationManager localizationManager = RecipePinnerPlugin.Instance?.LocalizationMgr; string text2 = ((!_gatheringListVisible) ? (localizationManager?.GetText("gathering_closed") ?? "Gathering List Closed") : (localizationManager?.GetText("gathering_opened") ?? "Gathering List Opened")); ((Character)Player.m_localPlayer).Message((MessageType)2, text2, 0, (Sprite)null); } } public void CloseGatheringList() { _gatheringListVisible = false; _gatheringListPanel?.SetActive(active: false); if (_gatheringListRepositioned) { RestoreGatheringListParent(); _gatheringListRepositioned = false; } _gatheringData.Clear(); _gatheringAggregator.Clear(); if (!((Object)(object)_gatheringListPanel != (Object)null)) { return; } foreach (GatheringItemUI itemSlot in _gatheringListPanel.ItemSlots) { if ((Object)(object)itemSlot != (Object)null && ((Component)itemSlot).gameObject.activeSelf) { itemSlot.SetActive(active: false); } } } private void UpdateGatheringListPosition(bool isHorizontal, bool isBottomRight) { //IL_0065: Unknown result type (might be due to invalid IL or missing references) //IL_006f: Unknown result type (might be due to invalid IL or missing references) //IL_00dc: Unknown result type (might be due to invalid IL or missing references) //IL_00f1: Unknown result type (might be due to invalid IL or missing references) //IL_0106: Unknown result type (might be due to invalid IL or missing references) //IL_011b: 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_009c: Unknown result type (might be due to invalid IL or missing references) //IL_00b1: 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) if ((Object)(object)_gatheringListPanel == (Object)null) { return; } LayoutElement val = ((Component)_gatheringListPanel).GetComponent() ?? ((Component)_gatheringListPanel).gameObject.AddComponent(); RectTransform panelRect = _gatheringListPanel.PanelRect; if (isHorizontal) { val.ignoreLayout = true; float num = (isBottomRight ? RecipePinnerPlugin.BottomRightColumnWidth.Value : RecipePinnerPlugin.HorizontalColumnWidth.Value); panelRect.sizeDelta = new Vector2(num, panelRect.sizeDelta.y); if (isBottomRight) { panelRect.anchorMin = new Vector2(1f, 1f); panelRect.anchorMax = new Vector2(1f, 1f); panelRect.pivot = new Vector2(1f, 0f); panelRect.anchoredPosition = new Vector2(0f, 10f); } else { panelRect.anchorMin = new Vector2(1f, 0f); panelRect.anchorMax = new Vector2(1f, 0f); panelRect.pivot = new Vector2(1f, 1f); panelRect.anchoredPosition = new Vector2(0f, -10f); } } else { val.ignoreLayout = false; } } private void RepositionGatheringListForInventory() { //IL_00c1: 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_00c6: Unknown result type (might be due to invalid IL or missing references) //IL_00d2: Unknown result type (might be due to invalid IL or missing references) //IL_00e7: Unknown result type (might be due to invalid IL or missing references) //IL_00fc: Unknown result type (might be due to invalid IL or missing references) //IL_0107: Unknown result type (might be due to invalid IL or missing references) //IL_0110: Unknown result type (might be due to invalid IL or missing references) //IL_011a: Unknown result type (might be due to invalid IL or missing references) //IL_0125: 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) if (!((Object)(object)_gatheringListPanel == (Object)null)) { Hud instance = Hud.instance; object obj; if (instance == null) { obj = null; } else { GameObject rootObject = instance.m_rootObject; obj = ((rootObject != null) ? rootObject.transform : null); } Transform val = (Transform)obj; if ((Object)(object)val != (Object)null && (Object)(object)((Component)_gatheringListPanel).transform.parent != (Object)(object)val) { ((Component)_gatheringListPanel).transform.SetParent(val, false); } (((Component)_gatheringListPanel).GetComponent() ?? ((Component)_gatheringListPanel).gameObject.AddComponent()).ignoreLayout = true; RectTransform panelRect = _gatheringListPanel.PanelRect; float num = RecipePinnerPlugin.BottomRightColumnWidth?.Value ?? 265f; Vector2 anchoredPosition = (Vector2)(((??)RecipePinnerPlugin.InventoryGatheringListPosition?.Value) ?? new Vector2(-460f, 0f)); panelRect.anchorMin = new Vector2(0.5f, 0.5f); panelRect.anchorMax = new Vector2(0.5f, 0.5f); panelRect.pivot = new Vector2(0.5f, 1f); panelRect.anchoredPosition = anchoredPosition; panelRect.sizeDelta = new Vector2(num, panelRect.sizeDelta.y); ((Transform)panelRect).localScale = Vector3.one * RecipePinnerPlugin.UIScale.Value; _gatheringListRepositioned = true; } } private void RestoreGatheringListParent() { //IL_005c: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)_gatheringListPanel == (Object)null) && !((Object)(object)_pinListRoot == (Object)null)) { if ((Object)(object)((Component)_gatheringListPanel).transform.parent != (Object)(object)_pinListRoot) { ((Component)_gatheringListPanel).transform.SetParent(_pinListRoot, false); ((Component)_gatheringListPanel).transform.localScale = Vector3.one; } LayoutElement component = ((Component)_gatheringListPanel).GetComponent(); if ((Object)(object)component != (Object)null) { component.ignoreLayout = false; } } } private void UpdateGatheringList() { //IL_0052: 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_03c5: Unknown result type (might be due to invalid IL or missing references) //IL_03ca: Unknown result type (might be due to invalid IL or missing references) //IL_031f: Unknown result type (might be due to invalid IL or missing references) //IL_0313: Unknown result type (might be due to invalid IL or missing references) //IL_0324: Unknown result type (might be due to invalid IL or missing references) //IL_032b: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_gatheringListPanel == (Object)null) { return; } bool activeSelf = ((Component)_gatheringListPanel).gameObject.activeSelf; if (!_gatheringListVisible && !_gatheringListRepositioned && !activeSelf) { return; } if ((Object)(object)_gatheringListPanel.BgImage != (Object)null && Mathf.Abs(((Graphic)_gatheringListPanel.BgImage).color.a - RecipePinnerPlugin.BackgroundOpacity.Value) > 0.01f) { ((Graphic)_gatheringListPanel.BgImage).color = new Color(0f, 0f, 0f, RecipePinnerPlugin.BackgroundOpacity.Value); } RecipeManager recipeManager = RecipePinnerPlugin.Instance?.RecipeMgr; if (recipeManager == null) { return; } ContainerScanner containerMgr = RecipePinnerPlugin.Instance.ContainerMgr; _gatheringAggregator.Clear(); _gatheringData.Clear(); foreach (PinnedRecipeData cachedPin in recipeManager.CachedPins) { foreach (PinnedResData resource in cachedPin.Resources) { if (_gatheringAggregator.TryGetValue(resource.ItemName, out var value)) { value.TotalRequired += resource.RequiredAmount; continue; } GatheringItemData gatheringItemData = new GatheringItemData { ItemName = resource.ItemName, DisplayName = (resource.CachedName ?? resource.ItemName), Icon = resource.Icon, TotalRequired = resource.RequiredAmount }; _gatheringAggregator[resource.ItemName] = gatheringItemData; _gatheringData.Add(gatheringItemData); } } foreach (GatheringItemData gatheringDatum in _gatheringData) { _reusableInvCounts.TryGetValue(gatheringDatum.ItemName, out var value2); int value3 = 0; if (RecipePinnerPlugin.EnableChestScanning.Value) { containerMgr.ContainerCache.TryGetValue(gatheringDatum.ItemName, out value3); } gatheringDatum.TotalHave = value2 + value3; gatheringDatum.IsComplete = gatheringDatum.TotalHave >= gatheringDatum.TotalRequired; } GatheringListUI gatheringListPanel = _gatheringListPanel; while (gatheringListPanel.ItemSlots.Count < _gatheringData.Count) { gatheringListPanel.ItemSlots.Add(UIBuilder.CreateGatheringItemSlot(gatheringListPanel.ItemListRoot, _cachedFont)); } for (int i = 0; i < gatheringListPanel.ItemSlots.Count; i++) { if (i < _gatheringData.Count) { GatheringItemUI gatheringItemUI = gatheringListPanel.ItemSlots[i]; GatheringItemData gatheringItemData2 = _gatheringData[i]; if (!((Component)gatheringItemUI).gameObject.activeSelf) { gatheringItemUI.SetActive(active: true); } gatheringItemUI.Icon.sprite = gatheringItemData2.Icon; Color val = (gatheringItemData2.IsComplete ? RecipePinnerPlugin.ColorEnoughInInventory.Value : RecipePinnerPlugin.ColorMissing.Value); string arg = "#" + ColorUtility.ToHtmlStringRGBA(val); gatheringItemUI.AmountText.text = $"{gatheringItemData2.TotalHave}/{gatheringItemData2.TotalRequired}"; } else if (((Component)gatheringListPanel.ItemSlots[i]).gameObject.activeSelf) { gatheringListPanel.ItemSlots[i].SetActive(active: false); } } if ((Object)(object)gatheringListPanel.HintText != (Object)null) { KeyCode value4 = RecipePinnerPlugin.HotkeyGatheringList.Value; string text = ((object)(KeyCode)(ref value4)).ToString(); if (_lastHintKey != text) { _lastHintKey = text; string format = (RecipePinnerPlugin.Instance?.LocalizationMgr)?.GetText("gathering_hint") ?? "Open/Close: {0}"; gatheringListPanel.HintText.text = string.Format(format, text); } ((Component)gatheringListPanel.HintText).transform.SetAsLastSibling(); } gatheringListPanel.RefreshLayout(); } }