Decompiled source of VNEI v0.15.4
VNEI.dll
Decompiled 2 months ago
The result has been truncated due to the large size, download it to view full contents!
using System; using System.Collections; using System.Collections.Concurrent; using System.Collections.Generic; using System.Collections.ObjectModel; using System.ComponentModel; using System.Diagnostics; using System.Diagnostics.CodeAnalysis; using System.Globalization; using System.IO; using System.Linq; using System.Linq.Expressions; using System.Reflection; using System.Reflection.Emit; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Serialization; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using System.Text; using System.Text.RegularExpressions; using System.Threading.Tasks; using Auga; using BepInEx; using BepInEx.Bootstrap; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; using JetBrains.Annotations; using Jotunn; using Jotunn.Entities; using Jotunn.GUI; using Jotunn.Managers; using Jotunn.Utils; using Microsoft.CodeAnalysis; using SimpleJson; using TMPro; using UnityEngine; using UnityEngine.EventSystems; using UnityEngine.Events; using UnityEngine.UI; using VNEI.Logic; using VNEI.Logic.Compatibility; using VNEI.Patches; using VNEI.UI; using YamlDotNet.Core; using YamlDotNet.Core.Events; using YamlDotNet.Core.Tokens; using YamlDotNet.Helpers; using YamlDotNet.Serialization; using YamlDotNet.Serialization.Converters; using YamlDotNet.Serialization.EventEmitters; using YamlDotNet.Serialization.NamingConventions; using YamlDotNet.Serialization.NodeDeserializers; using YamlDotNet.Serialization.NodeTypeResolvers; using YamlDotNet.Serialization.ObjectFactories; using YamlDotNet.Serialization.ObjectGraphTraversalStrategies; using YamlDotNet.Serialization.ObjectGraphVisitors; using YamlDotNet.Serialization.Schemas; using YamlDotNet.Serialization.TypeInspectors; using YamlDotNet.Serialization.TypeResolvers; using YamlDotNet.Serialization.Utilities; using YamlDotNet.Serialization.ValueDeserializers; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: AssemblyTitle("VNEI")] [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)] [assembly: AssemblyProduct("VNEI")] [assembly: AssemblyCopyright("Copyright © 2021")] [assembly: AssemblyTrademark("")] [assembly: ComVisible(false)] [assembly: Guid("43367351-2A51-4BC5-9028-1303450B71AB")] [assembly: AssemblyFileVersion("0.15.4")] [assembly: AssemblyCompany("")] [assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("0.15.4.0")] [module: UnverifiableCode] namespace VNEI { internal static class Log { internal static ManualLogSource _logSource; internal static void Init(ManualLogSource logSource) { _logSource = logSource; } internal static void LogDebug(object data) { _logSource.LogDebug(data); } internal static void LogError(object data) { _logSource.LogError(data); } internal static void LogFatal(object data) { _logSource.LogFatal(data); } internal static void LogInfo(object data) { _logSource.LogInfo(data); } internal static void LogMessage(object data) { _logSource.LogMessage(data); } internal static void LogWarning(object data) { _logSource.LogWarning(data); } } [BepInPlugin("com.maxsch.valheim.vnei", "VNEI", "0.15.4")] [BepInDependency(/*Could not decode attribute arguments.*/)] [NetworkCompatibility(/*Could not decode attribute arguments.*/)] public class Plugin : BaseUnityPlugin { public enum InputButtonWrapper { Left = 0, Right = 1, Middle = 2, None = -1 } public const string ModName = "VNEI"; public const string ModGuid = "com.maxsch.valheim.vnei"; public const string ModVersion = "0.15.4"; public static ConfigEntry<bool> useBlacklist; public static ConfigEntry<bool> invertScroll; public static ConfigEntry<bool> normalizeScroll; public static ConfigEntry<bool> attachToCrafting; public static ConfigEntry<bool> hideUIAtStartup; public static ConfigEntry<int> rowCount; public static ConfigEntry<int> columnCount; public static ConfigEntry<int> transparency; public static ConfigEntry<KeyboardShortcut> openHotkey; public static ConfigEntry<KeyboardShortcut> viewRecipeHotkey; public static ConfigEntry<InputButtonWrapper> itemCheatHotkey; public static ConfigEntry<InputButtonWrapper> removeRecentHotkey; public static ConfigEntry<KeyboardShortcut> goForwardHotkey; public static ConfigEntry<KeyboardShortcut> goBackHotkey; private static ConfigEntry<bool> showOnlyKnown; private static ConfigEntry<bool> forceShowOnlyKnown; public static ConfigEntry<bool> showRecentItems; public static ConfigEntry<string> tabName; public static ConfigEntry<bool> showModTooltip; public static ConfigEntry<bool> cheating; public static ConfigEntry<bool> cheatCreatures; public static bool isUiOpen = true; public Sprite noIconSprite; public Sprite starSprite; public Sprite noStarSprite; public Sprite inventoryIcon; public GameObject vneiUI; public GameObject displayItemTemplate; public GameObject craftingStationTemplate; public Item allStations; public Item handStation; public Item noStation; private static readonly Regex RichTagRegex = new Regex("<[^>]*>"); private Harmony harmony; public static Plugin Instance { get; private set; } public static AssetBundle AssetBundle { get; private set; } private static HashSet<string> ItemBlacklist { get; set; } = new HashSet<string>(); public static bool ShowOnlyKnown => showOnlyKnown.Value || forceShowOnlyKnown.Value; public static event Action OnOpenHotkey; private void Awake() { //IL_005f: Unknown result type (might be due to invalid IL or missing references) //IL_0069: Expected O, but got Unknown //IL_0090: Unknown result type (might be due to invalid IL or missing references) //IL_009a: Expected O, but got Unknown //IL_00c4: Unknown result type (might be due to invalid IL or missing references) //IL_00c9: Unknown result type (might be due to invalid IL or missing references) //IL_00d2: Expected O, but got Unknown //IL_00d2: Unknown result type (might be due to invalid IL or missing references) //IL_00dc: Expected O, but got Unknown //IL_0103: Unknown result type (might be due to invalid IL or missing references) //IL_010d: Expected O, but got Unknown //IL_0134: Unknown result type (might be due to invalid IL or missing references) //IL_013e: Expected O, but got Unknown //IL_0165: Unknown result type (might be due to invalid IL or missing references) //IL_016f: Expected O, but got Unknown //IL_0194: Unknown result type (might be due to invalid IL or missing references) //IL_01c5: Unknown result type (might be due to invalid IL or missing references) //IL_0245: Unknown result type (might be due to invalid IL or missing references) //IL_0279: Unknown result type (might be due to invalid IL or missing references) //IL_02b6: Unknown result type (might be due to invalid IL or missing references) //IL_02c0: Expected O, but got Unknown //IL_02e7: Unknown result type (might be due to invalid IL or missing references) //IL_02f1: Expected O, but got Unknown //IL_0318: Unknown result type (might be due to invalid IL or missing references) //IL_0322: Expected O, but got Unknown //IL_0349: Unknown result type (might be due to invalid IL or missing references) //IL_0353: Expected O, but got Unknown //IL_037a: Unknown result type (might be due to invalid IL or missing references) //IL_0384: Expected O, but got Unknown //IL_03af: Unknown result type (might be due to invalid IL or missing references) //IL_03b9: Expected O, but got Unknown //IL_03e0: Unknown result type (might be due to invalid IL or missing references) //IL_03ea: Expected O, but got Unknown //IL_0411: Unknown result type (might be due to invalid IL or missing references) //IL_041b: Expected O, but got Unknown //IL_0442: Unknown result type (might be due to invalid IL or missing references) //IL_044c: Expected O, but got Unknown //IL_0469: Unknown result type (might be due to invalid IL or missing references) //IL_0473: Expected O, but got Unknown Instance = this; Log.Init(((BaseUnityPlugin)this).Logger); AcceptableValueRange<int> val = new AcceptableValueRange<int>(1, 25); AcceptableValueRange<int> val2 = new AcceptableValueRange<int>(0, 100); string text = AssetUtils.LoadTextFromResources("Localization.Config.json", Assembly.GetExecutingAssembly()); Dictionary<string, string> dictionary = SimpleJson.DeserializeObject<Dictionary<string, string>>(text); useBlacklist = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "Use Item Blacklist", true, new ConfigDescription(dictionary["UseItemBlacklist"], (AcceptableValueBase)null, Array.Empty<object>())); showOnlyKnown = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "Show Only Known", false, new ConfigDescription(dictionary["ShowOnlyKnown"], (AcceptableValueBase)null, Array.Empty<object>())); forceShowOnlyKnown = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "Force Show Only Known", false, new ConfigDescription(dictionary["ForceShowOnlyKnown"], (AcceptableValueBase)null, new object[1] { (object)new ConfigurationManagerAttributes { IsAdminOnly = true } })); showRecentItems = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "Show Recent Items", true, new ConfigDescription(dictionary["ShowRecentItems"], (AcceptableValueBase)null, Array.Empty<object>())); invertScroll = ((BaseUnityPlugin)this).Config.Bind<bool>("Hotkeys", "Invert Scroll", false, new ConfigDescription(dictionary["InvertScroll"], (AcceptableValueBase)null, Array.Empty<object>())); normalizeScroll = ((BaseUnityPlugin)this).Config.Bind<bool>("Hotkeys", "Normalize Scroll", true, new ConfigDescription(dictionary["NormalizeScroll"], (AcceptableValueBase)null, Array.Empty<object>())); openHotkey = ((BaseUnityPlugin)this).Config.Bind<KeyboardShortcut>("Hotkeys", "Open UI Hotkey", new KeyboardShortcut((KeyCode)104, (KeyCode[])(object)new KeyCode[1] { (KeyCode)308 }), dictionary["OpenUIHotkey"]); viewRecipeHotkey = ((BaseUnityPlugin)this).Config.Bind<KeyboardShortcut>("Hotkeys", "View Recipe Hotkey", new KeyboardShortcut((KeyCode)114, Array.Empty<KeyCode>()), dictionary["ViewRecipeHotkey"]); itemCheatHotkey = ((BaseUnityPlugin)this).Config.Bind<InputButtonWrapper>("Hotkeys", "Item Cheat Mouse Button", InputButtonWrapper.Right, dictionary["ItemCheatMouseButton"]); removeRecentHotkey = ((BaseUnityPlugin)this).Config.Bind<InputButtonWrapper>("Hotkeys", "Remove Recent Item Mouse Button", InputButtonWrapper.Middle, dictionary["RemoveRecentMouseButton"]); goForwardHotkey = ((BaseUnityPlugin)this).Config.Bind<KeyboardShortcut>("Hotkeys", "Go Forward Hotkey", new KeyboardShortcut((KeyCode)275, Array.Empty<KeyCode>()), dictionary["GoForwardHotkey"]); goBackHotkey = ((BaseUnityPlugin)this).Config.Bind<KeyboardShortcut>("Hotkeys", "Go Back Hotkey", new KeyboardShortcut((KeyCode)276, Array.Empty<KeyCode>()), dictionary["GoBackHotkey"]); columnCount = ((BaseUnityPlugin)this).Config.Bind<int>("UI", "Items Horizontal", 12, new ConfigDescription(dictionary["ItemsHorizontal"], (AcceptableValueBase)(object)val, Array.Empty<object>())); rowCount = ((BaseUnityPlugin)this).Config.Bind<int>("UI", "Items Vertical", 6, new ConfigDescription(dictionary["ItemsVertical"], (AcceptableValueBase)(object)val, Array.Empty<object>())); attachToCrafting = ((BaseUnityPlugin)this).Config.Bind<bool>("UI", "Attach To Crafting", true, new ConfigDescription(dictionary["AttachToCrafting"], (AcceptableValueBase)null, Array.Empty<object>())); hideUIAtStartup = ((BaseUnityPlugin)this).Config.Bind<bool>("UI", "Hide GUI At Start", false, new ConfigDescription(dictionary["HideGUIAtStart"], (AcceptableValueBase)null, Array.Empty<object>())); transparency = ((BaseUnityPlugin)this).Config.Bind<int>("Visual", "Background Transparency", 0, new ConfigDescription(dictionary["Transparency"], (AcceptableValueBase)(object)val2, Array.Empty<object>())); tabName = ((BaseUnityPlugin)this).Config.Bind<string>("Visual", "Tab Name", "VNEI", new ConfigDescription(dictionary["TabName"], (AcceptableValueBase)null, Array.Empty<object>())); showModTooltip = ((BaseUnityPlugin)this).Config.Bind<bool>("Tooltips", "Show Mod Name In Tooltip", true, new ConfigDescription(dictionary["ShowModTooltip"], (AcceptableValueBase)null, Array.Empty<object>())); cheating = ((BaseUnityPlugin)this).Config.Bind<bool>("Cheating", "Enable Cheating", false, new ConfigDescription(dictionary["EnableCheating"], (AcceptableValueBase)null, Array.Empty<object>())); cheatCreatures = ((BaseUnityPlugin)this).Config.Bind<bool>("Cheating", "Enable Spawning Creatures", false, new ConfigDescription(dictionary["AllowCreatureSpawn"], (AcceptableValueBase)null, Array.Empty<object>())); isUiOpen = !hideUIAtStartup.Value; harmony = new Harmony("com.maxsch.valheim.vnei"); harmony.PatchAll(); AssetBundle = AssetUtils.LoadAssetBundleFromResources("VNEI_AssetBundle"); CustomLocalization localization = LocalizationManager.Instance.GetLocalization(); localization.AddJsonFile("English", AssetUtils.LoadTextFromResources("Localization.English.json")); localization.AddJsonFile("German", AssetUtils.LoadTextFromResources("Localization.German.json")); LoadBlacklist(); noIconSprite = AssetBundle.LoadAsset<Sprite>("NoSprite.png"); starSprite = AssetBundle.LoadAsset<Sprite>("Star.png"); noStarSprite = AssetBundle.LoadAsset<Sprite>("NoStar.png"); inventoryIcon = AssetBundle.LoadAsset<Sprite>("Hand.png"); vneiUI = AssetBundle.LoadAsset<GameObject>("VNEI"); displayItemTemplate = AssetBundle.LoadAsset<GameObject>("_Template"); craftingStationTemplate = AssetBundle.LoadAsset<GameObject>("CraftingStationTemplate"); GUIManager.OnCustomGUIAvailable += delegate { GetMainUI().CreateBaseUI(); }; CommandManager.Instance.AddConsoleCommand((ConsoleCommand)(object)new SelectUITest.ToggleUIConsoleCommand()); CommandManager.Instance.AddConsoleCommand((ConsoleCommand)(object)new FileWriterControllerCSV()); CommandManager.Instance.AddConsoleCommand((ConsoleCommand)(object)new FileWriterControllerYAML()); CommandManager.Instance.AddConsoleCommand((ConsoleCommand)(object)new FileWriterControllerText()); CommandManager.Instance.AddConsoleCommand((ConsoleCommand)(object)new IconExport()); PrefabManager.OnPrefabsRegistered += ApplyMocks; ModQuery.Enable(); } private static void LoadBlacklist() { string text = AssetUtils.LoadTextFromResources("ItemBlacklist.json", Assembly.GetExecutingAssembly()); ItemBlacklist = SimpleJson.DeserializeObject<List<string>>(text).ToHashSet(); string path = Path.Combine(Paths.ConfigPath, "com.maxsch.valheim.vnei.blacklist.txt"); if (!File.Exists(path)) { File.WriteAllText(path, ""); return; } string[] array = File.ReadAllLines(path); foreach (string text2 in array) { string text3 = text2.Trim(); if (!string.IsNullOrEmpty(text3) && !ItemBlacklist.Contains(text3)) { ItemBlacklist.Add(text2); } } } private void Start() { ModCompat.Init(harmony); PlanBuild.Init(); } private void Update() { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_00ad: Unknown result type (might be due to invalid IL or missing references) if (openHotkey.Value.IsKeyDown()) { OpenUI(); } if (!Indexing.HasIndexed() && Object.op_Implicit((Object)(object)Player.m_localPlayer)) { Indexing.IndexAll(); Indexing.UpdateKnown(); showOnlyKnown.SettingChanged += delegate { Indexing.UpdateKnown(); }; forceShowOnlyKnown.SettingChanged += delegate { Indexing.UpdateKnown(); }; KnownRecipesPatches.OnUpdateKnownRecipes += Indexing.UpdateKnown; } if (!viewRecipeHotkey.Value.IsKeyDown() || !Object.op_Implicit((Object)(object)UITooltip.m_current)) { return; } string text = UITooltip.m_current.m_topic.Trim(); string text2 = UITooltip.m_current.m_text.Trim(); Item item = null; if (text.Length > 0) { item = Indexing.GetItem(text); } if (item == null && text2.Length > 0) { item = Indexing.GetItem(text2); } if (item == null && RichTagRegex.IsMatch(text)) { string name = RichTagRegex.Replace(text, string.Empty).Trim(); item = Indexing.GetItem(name); } if (item != null) { if (attachToCrafting.Value) { GetMainUI().SetTabActive(); } BaseUI baseUI = GetMainUI().GetBaseUI(); baseUI.ShowRecipe(item, trackHistory: true); } } public static void OpenUI() { isUiOpen = !isUiOpen; Plugin.OnOpenHotkey?.Invoke(); } public static bool AttachToCrafting() { return attachToCrafting.Value; } private void ApplyMocks() { PrefabExtension.FixReferences(vneiUI, true); PrefabExtension.FixReferences(displayItemTemplate, true); PrefabExtension.FixReferences(craftingStationTemplate, true); PrefabManager.OnPrefabsRegistered -= ApplyMocks; } public static bool IsItemBlacklisted(Item item) { return ItemBlacklist.Contains(item.internalName) || ItemBlacklist.Contains(Indexing.CleanupName(item.internalName)); } public static VneiHandler GetMainUI() { if (IsAugaLoaded()) { return MainVneiHandlerAuga.Instance; } return MainVneiHandler.Instance; } public static bool IsAugaLoaded() { return Chainloader.PluginInfos.ContainsKey("randyknapp.mods.auga"); } } } namespace VNEI.Patches { [HarmonyPatch] public class InventoryGuiPatch { [HarmonyPostfix] [HarmonyPatch(typeof(InventoryGui), "Awake")] [HarmonyPriority(200)] public static void AwakePatch(InventoryGui __instance) { if (!Plugin.IsAugaLoaded()) { MainVneiHandler.Instance.GetTabButton(); ((MonoBehaviour)__instance).StartCoroutine(UpdateOtherTabs()); } else { MainVneiHandlerAuga.Instance.CreateBaseUI(); } } private static IEnumerator UpdateOtherTabs() { WaitForSeconds wait = new WaitForSeconds(1f); while (true) { yield return wait; MainVneiHandler.Instance.UpdateOtherTabs(); } } [HarmonyPatch(typeof(InventoryGui), "UpdateCraftingPanel")] [HarmonyAfter(new string[] { "org.bepinex.plugins.jewelcrafting" })] [HarmonyPostfix] public static void UpdateCraftingPanelPatch() { if (!Plugin.IsAugaLoaded()) { MainVneiHandler.Instance.UpdateTabPosition(); } } [HarmonyAfter(new string[] { "org.bepinex.plugins.jewelcrafting" })] [HarmonyPostfix] [HarmonyPatch(typeof(InventoryGui), "SetupCrafting")] public static void SetupCraftingPatch() { if (!Plugin.IsAugaLoaded() && MainVneiHandler.Instance.VneiTabActive) { MainVneiHandler.Instance.SetTabActive(); } } } public class ModCompat { private class ValheimRecycleFix { [UsedImplicitly] private static IEnumerable<MethodBase> TargetMethods() { Type valheimRecycle = Type.GetType("ValheimRecycle.ValheimRecycle, ValheimRecycle, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"); yield return valheimRecycle.GetMethod("GetOrCreateRecycleTab", BindingFlags.Instance | BindingFlags.NonPublic); } [UsedImplicitly] private static void Postfix(GameObject __result) { __result.transform.SetSiblingIndex(2); } } public static void Init(Harmony harmony) { if (Chainloader.PluginInfos.ContainsKey("org.lafchi.plugins.valheim_recycle")) { harmony.PatchAll(typeof(ValheimRecycleFix)); } } } [HarmonyPatch] public class KnownRecipesPatches { public static event Action OnUpdateKnownRecipes; [HarmonyPostfix] [HarmonyPatch(typeof(Player), "ResetCharacterKnownItems")] [HarmonyPatch(typeof(Player), "OnSpawned")] [HarmonyPatch(typeof(Player), "UpdateKnownRecipesList")] public static void UpdateKnownRecipesListPatch() { KnownRecipesPatches.OnUpdateKnownRecipes?.Invoke(); } } [HarmonyPatch] public static class TooltipPatches { [HarmonyPriority(0)] [HarmonyPostfix] [HarmonyPatch(typeof(ItemData), "GetTooltip", new Type[] { typeof(ItemData), typeof(int), typeof(bool), typeof(float), typeof(int) })] [HarmonyAfter(new string[] { "randyknapp.mods.epicloot" })] public static void AppendModName(ref string __result, ItemData item) { if (Plugin.showModTooltip.Value) { string name = PrefabName(item); Item item2 = Indexing.GetItem(name); if (item2 != null) { __result = __result.TrimEnd(Array.Empty<char>()) + item2.GetTooltipModName(); } } } private static string PrefabName(ItemData item) { if (item == null) { return string.Empty; } if ((Object)(object)item.m_dropPrefab != (Object)null) { return ((Object)item.m_dropPrefab).name; } return item.m_shared.m_name; } } } namespace VNEI.Logic { public readonly struct Amount { public readonly int min; public readonly int max; public readonly float chance; public static Amount Zero { get; } = new Amount(0, 0, 0f); public static Amount One { get; } = new Amount(1); public Amount(int min, int max, float chance = 1f) { this.min = min; this.max = max; this.chance = chance; } public Amount(int amount, float chance = 1f) { min = amount; max = amount; this.chance = chance; } public static bool IsSameMinMax(Amount a, Amount b) { return a.min == b.min && a.max == b.max; } public override string ToString() { int num = Mathf.RoundToInt(chance * 100f); string text = ""; bool flag = false; if (num != 100) { text += $"{num}% "; flag = true; } if (min == max) { if (!flag || max != 1) { text += $"{max}x"; } } else { text += $"{min}-{max}x"; } return text; } public bool Equals(Amount other) { int result; if (min == other.min && max == other.max) { float num = chance; result = (num.Equals(other.chance) ? 1 : 0); } else { result = 0; } return (byte)result != 0; } public override bool Equals(object obj) { return obj is Amount other && Equals(other); } public override int GetHashCode() { int num = min; num = (num * 397) ^ max; int num2 = num * 397; float num3 = chance; return num2 ^ num3.GetHashCode(); } } public static class BepInExExtensions { public static bool IsKeyDown(this KeyboardShortcut shortcut) { //IL_0028: 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) BaseUI baseUI = Plugin.GetMainUI().GetBaseUI(); if (Object.op_Implicit((Object)(object)baseUI) && baseUI.BlockInput) { return false; } return (int)((KeyboardShortcut)(ref shortcut)).MainKey != 0 && Input.GetKeyDown(((KeyboardShortcut)(ref shortcut)).MainKey) && ((KeyboardShortcut)(ref shortcut)).Modifiers.All((Func<KeyCode, bool>)Input.GetKey); } } public class ComponentEvent { private readonly Dictionary<Component, Action> listener = new Dictionary<Component, Action>(); public void AddListener(Component component, Action action) { if (!listener.ContainsKey(component)) { listener.Add(component, action); } } public void RemoveListener(Component component) { listener.Remove(component); } public void Invoke() { bool flag = false; foreach (KeyValuePair<Component, Action> item in listener) { if (!Object.op_Implicit((Object)(object)item.Key)) { flag = true; } else { item.Value?.Invoke(); } } if (flag) { RemoveDestroyedKeys(); } } private void RemoveDestroyedKeys() { listener.Keys.Where((Component i) => !Object.op_Implicit((Object)(object)i)).ToList().ForEach(delegate(Component i) { listener.Remove(i); }); } } public static class ExportPaths { private static string GetMainExportFolder() { return Path.Combine(Paths.BepInExRootPath, "VNEI-Export"); } public static string GetExportLocation(string fileName, params string[] path) { string text = Path.Combine(GetMainExportFolder(), Path.Combine(path), fileName); string directoryName = Path.GetDirectoryName(text); if (directoryName == null || string.IsNullOrEmpty(directoryName)) { throw new DirectoryNotFoundException("Invalid directory for " + fileName + ": " + directoryName); } if (!Directory.Exists(directoryName)) { Directory.CreateDirectory(directoryName); } return text; } } public static class FileWriter { private const string FileName = "VNEI.indexed.items"; private const string MissingType = "missing-type"; public static void PrintSimpleTextFile(List<Item> items) { string exportLocation = ExportPaths.GetExportLocation("VNEI.indexed.items.txt"); Log.LogInfo("Writing indexed items to file " + exportLocation); File.WriteAllLines(exportLocation, items.Select((Item item) => item.PrintItem()).ToArray()); } public static void PrintCSVFile(List<Item> items, string separator) { string exportLocation = ExportPaths.GetExportLocation("VNEI.indexed.items.csv"); Log.LogInfo("Writing indexed items to file " + exportLocation); string text = Item.PrintCSVHeader(separator); string[] second = items.Select((Item item) => EncapsulateFields(item.PrintItemCSV(separator), separator)).ToArray(); File.WriteAllLines(exportLocation, new string[1] { text }.Concat(second).ToArray()); } private static string EncapsulateFields(string csvLine, string separator) { string[] source = csvLine.Split(new string[1] { separator }, StringSplitOptions.None); IEnumerable<string> values = source.Select((string field) => "\"" + field.Replace("\"", "\"\"") + "\""); return string.Join(separator, values); } public static void PrintCLLCItemConfigYaml(List<Item> items, List<string> itemNamesFilterExcluded, List<string> modNamesFilterExcluded, List<string> modNamesFilterInclude) { string exportLocation = ExportPaths.GetExportLocation("VNEI.indexed.items.yml"); Log.LogInfo("Writing indexed items to file " + exportLocation); Log.LogInfo("Excluding items via match terms '" + string.Join(",", itemNamesFilterExcluded) + "' and mods with names matching '" + string.Join(",", modNamesFilterExcluded) + "'"); if (modNamesFilterInclude.Count > 0) { Log.LogInfo("Including items from mods with names matching '" + string.Join(",", modNamesFilterInclude) + "'"); } ISerializer serializer = new SerializerBuilder().WithNamingConvention(CamelCaseNamingConvention.Instance).Build(); ItemDrop val = default(ItemDrop); List<(string, string, string)> source = (from item in FilterInvalidItems(items, itemNamesFilterExcluded, modNamesFilterExcluded, modNamesFilterInclude) select (item.prefab.TryGetComponent<ItemDrop>(ref val) ? ((object)(ItemType)(ref val.m_itemData.m_shared.m_itemType)).ToString() : item.itemType.ToString(), item.internalName, item.GetModName())).ToList(); Dictionary<string, List<string>> groups = (from @group in source.GroupBy<(string, string, string), string>(delegate((string itemType, string internalName, string modName) item) { string result; if (!(item.modName != string.Empty)) { (result, _, _) = item; } else { result = item.itemType + "_" + CleanModName(item.modName); } return result; }) where @group.Key != "missing-type" select @group).ToDictionary((IGrouping<string, (string itemType, string internalName, string modName)> group) => group.Key, (IGrouping<string, (string itemType, string internalName, string modName)> group) => group.Select(((string itemType, string internalName, string modName) groupedItem) => groupedItem.internalName).ToList()); string contents = serializer.Serialize(new AllGroups(groups)); File.WriteAllText(exportLocation, contents); } private static List<Item> FilterInvalidItems(List<Item> items, List<string> itemNamesFilterExcluded, List<string> modNamesFilterExcluded, List<string> modNamesFilterInclude) { return (from item in items where (Object)(object)item.prefab != (Object)null where itemNamesFilterExcluded.All((string filterExclude) => !item.internalName.Contains(filterExclude)) select item).FilterExcludeMod(modNamesFilterExcluded).FilterIncludeMod(modNamesFilterInclude).ToList(); } private static IEnumerable<Item> FilterExcludeMod(this IEnumerable<Item> items, List<string> modNamesFilterExcluded) { return items.Where((Item item) => modNamesFilterExcluded.All((string filterExclude) => !item.GetModName().Contains(filterExclude))).ToList(); } private static IEnumerable<Item> FilterIncludeMod(this IEnumerable<Item> items, List<string> modNamesFilterInclude) { if (modNamesFilterInclude.Count == 0) { return items; } return items.Where((Item item) => modNamesFilterInclude.Any((string filterInclude) => item.GetModName().Contains(filterInclude))).ToList(); } private static string CleanModName(string modNameOriginal) { return Regex.Replace(modNameOriginal, "[^\\w]+", "_"); } } public class AllGroups { [UsedImplicitly] public readonly Dictionary<string, List<string>> Groups; public AllGroups(Dictionary<string, List<string>> groups) { Groups = groups; } } public abstract class FileWriterController : ConsoleCommand { public override string Help => "Writes all indexed items to a file"; protected static List<Item> GetItems() { return (from tuple in Indexing.GetActiveItems() select tuple.Value).ToList(); } } public class FileWriterControllerCSV : FileWriterController { public override string Name => "vnei_export_csv"; public override void Run(string[] args) { FileWriter.PrintCSVFile(separator: ((args.Length != 0) ? args[0] : string.Empty) switch { "comma" => ",", "tab" => "\t", "semicolon" => ";", _ => ",", }, items: FileWriterController.GetItems()); } public override List<string> CommandOptionList() { return new List<string> { "comma", "semicolon", "tab" }; } } public class FileWriterControllerYAML : FileWriterController { public override string Name => "vnei_export_yaml"; public override void Run(string[] args) { Log.LogInfo("args '" + string.Join("' '", args) + "'"); List<string> itemNamesFilterExcluded = ((args.Length != 0) ? args[0].Split(new char[1] { ',' }).ToList() : new List<string>()); List<string> modNamesFilterExcluded = ((args.Length > 1) ? args[1].Split(new char[1] { ',' }).ToList() : new List<string>()); List<string> modNamesFilterInclude = ((args.Length > 2) ? args[2].Split(new char[1] { ',' }).ToList() : new List<string>()); FileWriter.PrintCLLCItemConfigYaml(FileWriterController.GetItems(), itemNamesFilterExcluded, modNamesFilterExcluded, modNamesFilterInclude); } } public class FileWriterControllerText : FileWriterController { public override string Name => "vnei_export_text"; public override void Run(string[] args) { FileWriter.PrintSimpleTextFile(FileWriterController.GetItems()); } } public class IconExport : ConsoleCommand { public override string Name => "vnei_export_icons"; public override string Help => "Exports icons"; public override void Run(string[] args) { List<Item> source = (from tuple in Indexing.GetActiveItems() select tuple.Value).ToList(); Log.LogInfo("Exporting icons into " + ExportPaths.GetExportLocation("", "icons")); foreach (IGrouping<string, Item> item in from item in source group item by item.GetModName()) { if (args.Length >= 1 && !args[0].Split(new char[1] { ',' }).Contains(item.Key)) { continue; } Log.LogInfo($"Exporting {item.Count()} icons for {item.Key}"); foreach (Item item2 in item) { SaveIcon(item2); } } } private static void SaveIcon(Item item) { //IL_0113: Unknown result type (might be due to invalid IL or missing references) //IL_0118: 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_012a: Unknown result type (might be due to invalid IL or missing references) //IL_0137: Unknown result type (might be due to invalid IL or missing references) //IL_013c: 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_0158: Unknown result type (might be due to invalid IL or missing references) //IL_015d: Unknown result type (might be due to invalid IL or missing references) //IL_0167: Unknown result type (might be due to invalid IL or missing references) //IL_017e: Unknown result type (might be due to invalid IL or missing references) //IL_0185: Expected O, but got Unknown //IL_0193: Unknown result type (might be due to invalid IL or missing references) if (!Object.op_Implicit((Object)(object)item.prefab)) { return; } Sprite icon = item.GetIcon(); if (!Object.op_Implicit((Object)(object)icon)) { Log.LogWarning("No icon for " + item.internalName); return; } string fileName = Path.GetInvalidFileNameChars().Aggregate(item.internalName + ".png", (string current, char c) => current.Replace(c, '_')); string text = Path.GetInvalidPathChars().Aggregate(item.GetModName(), (string current, char c) => current.Replace(c, '_')); string exportLocation = ExportPaths.GetExportLocation(fileName, "icons", text); int width = ((Texture)icon.texture).width; int height = ((Texture)icon.texture).height; RenderTexture temporary = RenderTexture.GetTemporary(width, height); Graphics.Blit((Texture)(object)icon.texture, temporary); RenderTexture active = RenderTexture.active; RenderTexture.active = temporary; Rect val = icon.rect; int num = (int)((Rect)(ref val)).width; val = icon.rect; int num2 = (int)((Rect)(ref val)).height; val = icon.textureRect; int num3 = (int)(((Rect)(ref val)).x - icon.textureRectOffset.x); float num4 = height; val = icon.textureRect; int num5 = (int)(num4 - (((Rect)(ref val)).y - icon.textureRectOffset.y + (float)num2)); Texture2D val2 = new Texture2D(num, num2); val2.ReadPixels(new Rect((float)num3, (float)num5, (float)num, (float)num2), 0, 0); val2.Apply(); RenderTexture.active = active; RenderTexture.ReleaseTemporary(temporary); File.WriteAllBytes(exportLocation, ImageConversion.EncodeToPNG(val2)); } } public class FavouritesSave { public const string favouritesFileName = "com.maxsch.valheim.vnei.favourites.txt"; public static string GetFavouritesFilePath() { return Path.Combine(Paths.ConfigPath, "com.maxsch.valheim.vnei.favourites.txt"); } public static void Load() { string favouritesFilePath = GetFavouritesFilePath(); if (!File.Exists(favouritesFilePath)) { return; } using StreamReader streamReader = File.OpenText(favouritesFilePath); while (!streamReader.EndOfStream) { string text = streamReader.ReadLine(); if (!string.IsNullOrEmpty(text)) { Item item = Indexing.GetItem(text); if (item != null) { item.isFavorite = true; } } } } public static void Save() { using StreamWriter streamWriter = File.CreateText(GetFavouritesFilePath()); foreach (KeyValuePair<string, Item> activeItem in Indexing.GetActiveItems()) { if (activeItem.Value.isFavorite) { streamWriter.WriteLine(activeItem.Value.internalName); } } } } public static class Indexing { private static int currentKnownCount; private static bool currentShowOnlyKnown; private static Dictionary<string, Item> Items { get; } = new Dictionary<string, Item>(); private static Dictionary<string, Item> ItemsByPreLocalizedName { get; } = new Dictionary<string, Item>(); private static Dictionary<string, Item> ItemsByLocalizedName { get; } = new Dictionary<string, Item>(); public static event Action<GameObject> OnIndexingItems; public static event Action<GameObject> OnDisableItems; public static event Action AfterDisableItems; public static event Action<Recipe> OnIndexingRecipes; public static event Action<GameObject> OnIndexingItemRecipes; public static event Action IndexFinished; public static event Action AfterUpdateKnownItems; public static void IndexAll() { if (HasIndexed()) { return; } if (!Object.op_Implicit((Object)(object)ZNetScene.instance)) { Log.LogWarning("Cannot index: ZNetScene.instance is null"); return; } Log.LogInfo("Index items and recipes"); ModNames.IndexModNames(); Dictionary<string, PieceTable> pieceTables = new Dictionary<string, PieceTable>(); List<GameObject> prefabs = GetPrefabs(); IndexItems(prefabs, pieceTables); DisableItems(prefabs); IndexRecipes(); IndexItemRecipes(prefabs, pieceTables); foreach (RecipeInfo recipe in RecipeInfo.Recipes) { recipe.CalculateIsOnBlacklist(); recipe.CalculateWidth(); } FavouritesSave.Load(); Log.LogInfo($"Loaded {GetActiveItems().Count()} items and {RecipeInfo.Recipes.Count} recipes"); try { Indexing.IndexFinished?.Invoke(); } catch (Exception data) { Log.LogError(data); } } private static List<GameObject> GetPrefabs() { HashSet<GameObject> first = new HashSet<GameObject>(ZNetScene.instance.m_prefabs); HashSet<GameObject> second = new HashSet<GameObject>(ZNetScene.instance.m_namedPrefabs.Values); List<GameObject> list = first.Union(second).ToList(); list.RemoveAll((GameObject prefab) => !Object.op_Implicit((Object)(object)prefab)); return list; } private static void IndexItems(List<GameObject> prefabs, Dictionary<string, PieceTable> pieceTables) { AddItem(new Item("vnei_any_item", "$vnei_any_item", string.Empty, null, ItemType.Undefined, null)); AddItem(new Item("vnei_unknown_item", "$vnei_unknown_item", string.Empty, null, ItemType.Undefined, null)); AddItem(new Item("vnei_all_stations", "$vnei_all_stations", "", null, ItemType.Undefined, null)); AddItem(new Item("vnei_hand_station", "$vnei_hand_station", "", Plugin.Instance.inventoryIcon, ItemType.Undefined, null)); AddItem(new Item("vnei_no_station", "$vnei_no_station", "", null, ItemType.Undefined, null)); Plugin.Instance.allStations = GetItem("vnei_all_stations"); Plugin.Instance.handStation = GetItem("vnei_hand_station"); Plugin.Instance.noStation = GetItem("vnei_no_station"); DisableItem("vnei_any_item", "is not an item"); DisableItem("vnei_unknown_item", "is not an item"); DisableItem("vnei_all_stations", "is not an item"); DisableItem("vnei_hand_station", "is not an item"); DisableItem("vnei_no_station", "is not an item"); HoverText val = default(HoverText); CraftingStation val2 = default(CraftingStation); ItemDrop val3 = default(ItemDrop); foreach (GameObject prefab in prefabs) { string name = ((Object)prefab).name; string text = string.Empty; if (prefab.TryGetComponent<HoverText>(ref val)) { text = val.m_text; } if (string.IsNullOrEmpty(text) && prefab.TryGetComponent<CraftingStation>(ref val2)) { text = val2.m_name; } if (name.StartsWith("TreasureChest")) { TryAddItem<Piece>(prefab, (Func<Piece, string>)((Piece i) => i.m_name), text, ItemType.Piece, (Func<Piece, string>)((Piece i) => i.m_description), (Func<Piece, Sprite>)((Piece i) => i.m_icon)); } if (prefab.TryGetComponent<ItemDrop>(ref val3)) { ItemData itemData = val3.m_itemData; Sprite icon = null; if (Object.op_Implicit((Object)(object)val3) && itemData.m_shared.m_icons.Length != 0) { icon = itemData.GetIcon(); } if (itemData.m_shared.m_damageModifiers == null) { itemData.m_shared.m_damageModifiers = new List<DamageModPair>(); } ItemType itemType = ItemTypeHelper.GetItemType(itemData); SharedData shared = itemData.m_shared; AddItem(new Item(((Object)prefab).name, shared.m_name, shared.m_description, icon, itemType, prefab, shared.m_maxQuality)); if (Object.op_Implicit((Object)(object)itemData.m_shared.m_buildPieces)) { pieceTables.Add(CleanupName(name), itemData.m_shared.m_buildPieces); foreach (GameObject piece in itemData.m_shared.m_buildPieces.m_pieces) { TryAddItem<Piece>(piece, (Func<Piece, string>)((Piece i) => i.m_name), text, ItemType.Piece, (Func<Piece, string>)((Piece i) => i.m_description), (Func<Piece, Sprite>)((Piece i) => i.m_icon)); } } } TryAddItem<Character>(prefab, (Func<Character, string>)((Character i) => i.m_name), text, ItemType.Creature, (Func<Character, string>)null, (Func<Character, Sprite>)null); TryAddItem<MineRock>(prefab, (Func<MineRock, string>)((MineRock i) => i.m_name), text, ItemType.Undefined, (Func<MineRock, string>)null, (Func<MineRock, Sprite>)null); TryAddItem<MineRock5>(prefab, (Func<MineRock5, string>)((MineRock5 i) => i.m_name), text, ItemType.Undefined, (Func<MineRock5, string>)null, (Func<MineRock5, Sprite>)null); TryAddItem<DropOnDestroyed>(prefab, (Func<DropOnDestroyed, string>)((DropOnDestroyed i) => string.Empty), text, ItemType.Undefined, (Func<DropOnDestroyed, string>)null, (Func<DropOnDestroyed, Sprite>)null); TryAddItem<Pickable>(prefab, (Func<Pickable, string>)((Pickable i) => string.Empty), text, ItemType.Undefined, (Func<Pickable, string>)null, (Func<Pickable, Sprite>)null); TryAddItem<SpawnArea>(prefab, (Func<SpawnArea, string>)((SpawnArea i) => string.Empty), text, ItemType.Creature, (Func<SpawnArea, string>)null, (Func<SpawnArea, Sprite>)null); TryAddItem<Destructible>(prefab, (Func<Destructible, string>)((Destructible i) => string.Empty), text, ItemType.Undefined, (Func<Destructible, string>)null, (Func<Destructible, Sprite>)null); TryAddItem<TreeBase>(prefab, (Func<TreeBase, string>)((TreeBase i) => string.Empty), text, ItemType.Undefined, (Func<TreeBase, string>)null, (Func<TreeBase, Sprite>)null); TryAddItem<Trader>(prefab, (Func<Trader, string>)((Trader i) => i.m_name), text, ItemType.Undefined, (Func<Trader, string>)null, (Func<Trader, Sprite>)null); try { Indexing.OnIndexingItems?.Invoke(prefab); } catch (Exception data) { Log.LogError(data); } } } private static void DisableItems(List<GameObject> prefabs) { Piece val = default(Piece); Humanoid val2 = default(Humanoid); foreach (GameObject prefab in prefabs) { if (prefab.TryGetComponent<Piece>(ref val) && GetItem(((Object)prefab).name) == null) { Log.LogDebug("not indexed piece " + ((Object)val).name + ": not buildable"); } if (prefab.TryGetComponent<Humanoid>(ref val2)) { DisableArray(prefab, val2.m_defaultItems); DisableArray(prefab, val2.m_randomWeapon); DisableArray(prefab, val2.m_randomShield); DisableArray(prefab, val2.m_randomArmor); if (val2.m_randomSets != null) { ItemSet[] randomSets = val2.m_randomSets; for (int i = 0; i < randomSets.Length; i++) { DisableArray(prefab, randomSets[i]?.m_items); } } DisableEffectList(prefab, ((Character)val2).m_hitEffects); DisableEffectList(prefab, ((Character)val2).m_critHitEffects); DisableEffectList(prefab, ((Character)val2).m_backstabHitEffects); DisableEffectList(prefab, ((Character)val2).m_deathEffects); DisableEffectList(prefab, ((Character)val2).m_waterEffects); DisableEffectList(prefab, ((Character)val2).m_tarEffects); DisableEffectList(prefab, ((Character)val2).m_slideEffects); DisableEffectList(prefab, ((Character)val2).m_jumpEffects); DisableEffectList(prefab, val2.m_pickupEffects); DisableEffectList(prefab, val2.m_dropEffects); DisableEffectList(prefab, val2.m_consumeItemEffects); DisableEffectList(prefab, val2.m_equipEffects); DisableEffectList(prefab, val2.m_perfectBlockEffect); } try { Indexing.OnDisableItems?.Invoke(prefab); } catch (Exception data) { Log.LogError(data); } } try { Indexing.AfterDisableItems?.Invoke(); } catch (Exception data2) { Log.LogError(data2); } } private static void DisableArray(GameObject from, GameObject[] array) { if (array == null) { return; } foreach (GameObject item in array.Where((GameObject i) => Object.op_Implicit((Object)(object)i))) { ItemDrop component = item.GetComponent<ItemDrop>(); if (Object.op_Implicit((Object)(object)component)) { ItemData itemData = component.m_itemData; if (itemData != null && itemData.m_shared?.m_icons?.Length > 0) { Log.LogDebug("Not disabling item " + ((Object)item).name + " because it has icons"); continue; } } DisableItem(((Object)item).name, "is defaultItem from " + ((Object)from).name); } } private static void DisableEffectList(GameObject from, EffectList effectList) { if (effectList?.m_effectPrefabs == null) { return; } foreach (EffectData item in effectList.m_effectPrefabs.Where((EffectData i) => i != null && Object.op_Implicit((Object)(object)i.m_prefab))) { DisableItem(((Object)item.m_prefab).name, "is defaultItem from " + ((Object)from).name); } } private static void IndexRecipes() { if (!Object.op_Implicit((Object)(object)ObjectDB.instance)) { Log.LogWarning("Cannot index recipes: ObjectDB.instance is null"); return; } foreach (Recipe recipe in ObjectDB.instance.m_recipes) { if (!recipe.m_enabled) { Log.LogDebug("skipping " + ((Object)recipe).name + ": not enabled"); continue; } if (!Object.op_Implicit((Object)(object)recipe.m_item)) { Log.LogDebug("skipping " + ((Object)recipe).name + ": item is null"); continue; } for (int i = 1; i <= recipe.m_item.m_itemData.m_shared.m_maxQuality; i++) { AddRecipeToItems(new RecipeInfo(recipe, i)); } try { Indexing.OnIndexingRecipes?.Invoke(recipe); } catch (Exception data) { Log.LogError(data); } } } private static void IndexItemRecipes(List<GameObject> prefabs, Dictionary<string, PieceTable> pieceTables) { Incinerator val = default(Incinerator); Piece val2 = default(Piece); Container val3 = default(Container); Destructible val4 = default(Destructible); foreach (GameObject prefab in prefabs) { TryAddRecipeToItemsForEach<Smelter, ItemConversion>(prefab, (Func<Smelter, List<ItemConversion>>)((Smelter i) => i.m_conversion), (Func<Smelter, ItemConversion, RecipeInfo>)((Smelter s, ItemConversion i) => new RecipeInfo(i, s))); TryAddRecipeToItemsForEach<Fermenter, ItemConversion>(prefab, (Func<Fermenter, List<ItemConversion>>)((Fermenter i) => i.m_conversion), (Func<Fermenter, ItemConversion, RecipeInfo>)((Fermenter f, ItemConversion i) => new RecipeInfo(i, f))); TryAddRecipeToItemsForEach<CookingStation, ItemConversion>(prefab, (Func<CookingStation, List<ItemConversion>>)((CookingStation i) => i.m_conversion), (Func<CookingStation, ItemConversion, RecipeInfo>)((CookingStation c, ItemConversion i) => new RecipeInfo(i, c))); if (prefab.TryGetComponent<Incinerator>(ref val)) { AddRecipeToItems(new RecipeInfo(val)); foreach (IncineratorConversion conversion in val.m_conversions) { if (conversion.m_requireOnlyOneIngredient) { foreach (Requirement requirement in conversion.m_requirements) { AddRecipeToItems(new RecipeInfo(conversion, requirement, val)); } } else { AddRecipeToItems(new RecipeInfo(conversion, val)); } } } TryAddRecipeToItems<CharacterDrop>(prefab, (Func<CharacterDrop, RecipeInfo>)((CharacterDrop i) => new RecipeInfo(i)), (Func<CharacterDrop, bool>)((CharacterDrop i) => Object.op_Implicit((Object)(object)((Component)i).GetComponent<Character>()))); TryAddRecipeToItems<Growup>(prefab, (Func<Growup, RecipeInfo>)((Growup i) => new RecipeInfo(i)), (Func<Growup, bool>)null); TryAddRecipeToItems<MineRock>(prefab, (Func<MineRock, RecipeInfo>)((MineRock i) => new RecipeInfo(prefab, i.m_dropItems)), (Func<MineRock, bool>)null); TryAddRecipeToItems<MineRock5>(prefab, (Func<MineRock5, RecipeInfo>)((MineRock5 i) => new RecipeInfo(prefab, i.m_dropItems)), (Func<MineRock5, bool>)null); TryAddRecipeToItems<DropOnDestroyed>(prefab, (Func<DropOnDestroyed, RecipeInfo>)((DropOnDestroyed i) => new RecipeInfo(prefab, i.m_dropWhenDestroyed)), (Func<DropOnDestroyed, bool>)null); prefab.TryGetComponent<Piece>(ref val2); if (Object.op_Implicit((Object)(object)val2) && prefab.TryGetComponent<Container>(ref val3) && val3.m_defaultItems.m_drops.Count > 0) { AddRecipeToItems(new RecipeInfo(((Component)val3).gameObject, val3.m_defaultItems)); } TryAddRecipeToItems<Pickable>(prefab, (Func<Pickable, RecipeInfo>)((Pickable i) => new RecipeInfo(prefab, i)), (Func<Pickable, bool>)null); TryAddRecipeToItems<SpawnArea>(prefab, (Func<SpawnArea, RecipeInfo>)((SpawnArea i) => new RecipeInfo(i)), (Func<SpawnArea, bool>)null); if (prefab.TryGetComponent<Destructible>(ref val4)) { if (Object.op_Implicit((Object)(object)val4.m_spawnWhenDestroyed) && GetItem(((Object)val4.m_spawnWhenDestroyed).name) != null) { AddRecipeToItems(new RecipeInfo(val4)); } else if (((Behaviour)val4).enabled && !Object.op_Implicit((Object)(object)prefab.GetComponent<DropOnDestroyed>()) && !Object.op_Implicit((Object)(object)prefab.GetComponent<Plant>())) { DisableItem(((Object)prefab).name, "destructible.m_spawnWhenDestroyed is null or not indexed"); } } TryAddRecipeToItems<TreeBase>(prefab, (Func<TreeBase, RecipeInfo>)((TreeBase i) => new RecipeInfo(i)), (Func<TreeBase, bool>)null); TryAddRecipeToItemsForEach<Trader, TradeItem>(prefab, (Func<Trader, List<TradeItem>>)((Trader i) => i.m_items), (Func<Trader, TradeItem, RecipeInfo>)((Trader t, TradeItem i) => new RecipeInfo(t, i))); try { Indexing.OnIndexingItemRecipes?.Invoke(prefab); } catch (Exception data) { Log.LogError(data); } } Piece val5 = default(Piece); foreach (KeyValuePair<string, PieceTable> pieceTable in pieceTables) { if (!Object.op_Implicit((Object)(object)pieceTable.Value)) { Log.LogDebug("IndexItemRecipes: pieceTable " + pieceTable.Key + " is null"); continue; } foreach (GameObject piece in pieceTable.Value.m_pieces) { if (!Object.op_Implicit((Object)(object)piece)) { Log.LogDebug("IndexItemRecipes: prefab in pieceTables " + pieceTable.Key + " is null"); } else if (piece.TryGetComponent<Piece>(ref val5) && !val5.m_repairPiece) { AddRecipeToItems(new RecipeInfo(piece, val5, GetItem(pieceTable.Key))); } } } } private static void TryAddItem<T>(GameObject target, Func<T, string> getName, string fallbackLocalizedName, ItemType itemType, Func<T, string> getDescription = null, Func<T, Sprite> getIcon = null) where T : Component { T arg = default(T); if (!target.TryGetComponent<T>(ref arg)) { return; } try { string description = getDescription?.Invoke(arg) ?? string.Empty; Sprite icon = getIcon?.Invoke(arg); string text = getName(arg); if (string.IsNullOrEmpty(text)) { text = fallbackLocalizedName; } Item item = new Item(((Object)target).name, text, description, icon, itemType, target); AddItem(item); } catch (Exception ex) { Log.LogError(((Object)target).name + Environment.NewLine + ex?.ToString() + Environment.NewLine); } } private static void TryAddRecipeToItems<T>(GameObject target, Func<T, RecipeInfo> getRecipe, Func<T, bool> check = null) where T : Component { T arg = default(T); if (target.TryGetComponent<T>(ref arg) && (check == null || check(arg))) { RecipeInfo recipeInfo; try { recipeInfo = getRecipe(arg); } catch (Exception ex) { Log.LogError(((Object)target).name + Environment.NewLine + ex?.ToString() + Environment.NewLine); return; } AddRecipeToItems(recipeInfo); } } private static void TryAddRecipeToItemsForEach<T1, T2>(GameObject target, Func<T1, List<T2>> getArray, Func<T1, T2, RecipeInfo> getRecipe) where T1 : Component { T1 val = default(T1); if (!target.TryGetComponent<T1>(ref val)) { return; } foreach (T2 item in getArray(val)) { try { AddRecipeToItems(getRecipe(val, item)); } catch (Exception ex) { Log.LogError(((Object)target).name + Environment.NewLine + ex?.ToString() + Environment.NewLine); } } } public static bool HasIndexed() { return Items.Count > 0; } public static void DisableItem(string name, string context) { Item item = GetItem(name); if (item != null) { item.isActive = false; Log.LogDebug("disabling " + name + ": " + context); } } public static void AddItem(Item item) { string key = CleanupName(item.internalName); if (!Items.ContainsKey(key)) { Items[key] = item; } if (!string.IsNullOrEmpty(item.preLocalizeName) && (!ItemsByPreLocalizedName.TryGetValue(item.preLocalizeName, out var value) || IsSaplingItem(value))) { ItemsByPreLocalizedName[item.preLocalizeName] = item; } if (!string.IsNullOrEmpty(item.localizedName) && (!ItemsByLocalizedName.TryGetValue(item.localizedName, out var value2) || IsSaplingItem(value2))) { ItemsByLocalizedName[item.localizedName] = item; } } private static bool IsSaplingItem(Item item) { return item.internalName.StartsWith("sapling_") || Object.op_Implicit((Object)(object)item.prefab.GetComponent<Plant>()); } public static void ItemObtainedInRecipe(string name, RecipeInfo recipeInfo) { Item item = GetItem(name); if (item != null) { item.result.Add(recipeInfo); } else { Log.LogDebug("cannot add recipe to obtaining, '" + CleanupName(name) + "' is not indexed"); } } public static void ItemUsedInRecipe(string name, RecipeInfo recipeInfo) { Item item = GetItem(name); if (item != null) { item.ingredient.Add(recipeInfo); } else { Log.LogDebug("cannot add recipe to using, '" + CleanupName(name) + "' is not indexed"); } } public static void AddRecipeToItems(RecipeInfo recipeInfo) { foreach (Part item in recipeInfo.Ingredients.SelectMany((KeyValuePair<Amount, List<Part>> i) => i.Value)) { ItemUsedInRecipe(item.item.internalName, recipeInfo); } foreach (Part item2 in recipeInfo.Results.SelectMany((KeyValuePair<Amount, List<Part>> i) => i.Value)) { ItemObtainedInRecipe(item2.item.internalName, recipeInfo); } foreach (Part station in recipeInfo.Stations) { ItemUsedInRecipe(station.item.internalName, recipeInfo); } } public static string CleanupName(string name) { return name.Replace("JVLmock_", "").ToLower(); } [Obsolete] public static void SetModOfPrefab(string prefabName, BepInPlugin mod) { ModNames.SetModOfPrefab(prefabName, mod); } [Obsolete] public static BepInPlugin GetModByPrefabName(string name) { return ModNames.GetModByPrefabName(name); } public static IEnumerable<KeyValuePair<string, Item>> GetActiveItems() { return Items.Where((KeyValuePair<string, Item> i) => i.Value.isActive); } public static Item GetItem(string name) { if (Items.TryGetValue(CleanupName(name), out var value)) { return value; } if (ItemsByPreLocalizedName.TryGetValue(name, out value)) { return value; } if (ItemsByLocalizedName.TryGetValue(name, out value)) { return value; } return null; } public static void UpdateKnown() { if (!Object.op_Implicit((Object)(object)Player.m_localPlayer)) { return; } int num = Player.m_localPlayer.m_knownMaterial.Count + Player.m_localPlayer.m_knownRecipes.Count + Player.m_localPlayer.m_knownStations.Count + Player.m_localPlayer.m_knownTexts.Count + Player.m_localPlayer.m_knownBiome.Count; if (currentKnownCount == num && currentShowOnlyKnown == Plugin.ShowOnlyKnown) { return; } currentKnownCount = num; currentShowOnlyKnown = Plugin.ShowOnlyKnown; foreach (Item value in Items.Values) { value.UpdateSelfKnown(); } foreach (RecipeInfo recipe in RecipeInfo.Recipes) { recipe.UpdateKnown(); } foreach (Item value2 in Items.Values) { value2.UpdateKnown(); } Indexing.AfterUpdateKnownItems?.Invoke(); } } public class Item { public readonly string internalName; public readonly string preLocalizeName; public string localizedName; public readonly string description; public string localizedDescription; public readonly GameObject prefab; public readonly bool isOnBlacklist; public readonly ItemType itemType; public readonly BepInPlugin mod; public bool isActive = true; public int maxQuality; public bool isFavorite; private bool isKnown; private readonly Dictionary<int, string> tooltipsCache = new Dictionary<int, string>(); public readonly HashSet<RecipeInfo> result = new HashSet<RecipeInfo>(); public readonly HashSet<RecipeInfo> ingredient = new HashSet<RecipeInfo>(); public readonly ComponentEvent onFavoriteChanged = new ComponentEvent(); public readonly ComponentEvent onKnownChanged = new ComponentEvent(); private Sprite icon; public bool IsKnown => isKnown || !Plugin.ShowOnlyKnown; public bool IsSelfKnown { get; private set; } public static event Action OnAnyFavoriteChanged; public Item(string name, string preLocalizeName, string description, Sprite icon, ItemType itemType, GameObject prefab, int maxQuality = 1) { //IL_010b: 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_0111: 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_0129: Unknown result type (might be due to invalid IL or missing references) //IL_0132: Expected O, but got Unknown internalName = name; this.preLocalizeName = preLocalizeName ?? ""; this.description = description; this.prefab = prefab; this.itemType = itemType; this.maxQuality = maxQuality; isOnBlacklist = Plugin.IsItemBlacklisted(this); Plugin.showModTooltip.SettingChanged += ClearTooltipCache; Localization.OnLanguageChange = (Action)Delegate.Combine(Localization.OnLanguageChange, new Action(UpdateLocalizedName)); UpdateLocalizedName(); if (Object.op_Implicit((Object)(object)prefab)) { mod = ModNames.GetModByPrefabName(((Object)prefab).name); } if (Object.op_Implicit((Object)(object)icon)) { SetIcon(icon); } else if (Object.op_Implicit((Object)(object)prefab)) { RenderRequest val = new RenderRequest(prefab) { Rotation = RenderManager.IsometricRotation, TargetPlugin = mod, UseCache = true }; SetIcon(RenderManager.Instance.Render(val)); } } ~Item() { Plugin.showModTooltip.SettingChanged -= ClearTooltipCache; Localization.OnLanguageChange = (Action)Delegate.Remove(Localization.OnLanguageChange, new Action(UpdateLocalizedName)); } public string GetNameContext() { return internalName + Environment.NewLine + GetModName(); } public string GetDescription() { return description; } public string GetTooltip(int quality) { if (tooltipsCache.TryGetValue(quality, out var value)) { return value; } value = GenerateTooltip(quality); tooltipsCache.Add(quality, value); return value; } private void UpdateLocalizedName() { localizedName = Localization.instance.Localize(preLocalizeName); localizedDescription = Localization.instance.Localize(description); } private void ClearTooltipCache(object sender, EventArgs e) { tooltipsCache.Clear(); } private string GenerateTooltip(int quality) { ItemDrop val = default(ItemDrop); if (Object.op_Implicit((Object)(object)prefab) && prefab.TryGetComponent<ItemDrop>(ref val)) { if (!Object.op_Implicit((Object)(object)val.m_itemData.m_dropPrefab)) { val.m_itemData.m_dropPrefab = prefab; } try { return ItemData.GetTooltip(val.m_itemData, quality, true, (float)Game.m_worldLevel, -1); } catch (Exception arg) { Log.LogWarning($"Failed to generate tooltip for '{internalName}': {arg}"); return string.Empty; } } return description.TrimEnd(Array.Empty<char>()) + GetTooltipModName(); } public string GetTooltipModName() { if (!Plugin.showModTooltip.Value) { return string.Empty; } string text = "orange"; if (Chainloader.PluginInfos.ContainsKey("randyknapp.mods.epicloot")) { text = "#ADD8E6FF"; } return "\n\n<color=" + text + ">" + GetModName() + "</color>"; } public void SetIcon(Sprite sprite) { if (!Object.op_Implicit((Object)(object)icon)) { icon = sprite; } } public Sprite GetIcon() { return Object.op_Implicit((Object)(object)icon) ? icon : Plugin.Instance.noIconSprite; } public string GetPrimaryName() { return (localizedName.Length > 0) ? localizedName : internalName; } public string GetModName() { return (mod != null) ? mod.Name : "Valheim"; } public string PrintItem() { if (string.IsNullOrEmpty(internalName)) { return " -- invalid item -- "; } string text = GetDescription().Replace('\n', ' '); string text2 = itemType.ToString(); string text3 = "Internal Name: " + internalName + ", Localized Name: " + GetPrimaryName() + ", Item Type: " + text2; if (!string.IsNullOrEmpty(text)) { text3 = text3 + ", Description: " + text; } if (!string.IsNullOrEmpty(GetModName())) { text3 = text3 + ", Source Mod: " + GetModName(); } return text3; } public string PrintItemCSV(string separator) { if (string.IsNullOrEmpty(internalName)) { return " -- invalid item -- "; } string text = GetDescription().Replace('\n', ' '); return internalName + separator + GetPrimaryName() + separator + $"{itemType}{separator}" + text + separator + GetModName(); } public static string PrintCSVHeader(string separator) { return "Internal Name" + separator + "Localized Name" + separator + "Item Type" + separator + "Description" + separator + "Source Mod"; } public void UpdateFavorite(bool favorite) { isFavorite = favorite; onFavoriteChanged.Invoke(); Item.OnAnyFavoriteChanged?.Invoke(); } public void UpdateSelfKnown() { isKnown = false; if (!Plugin.ShowOnlyKnown) { IsSelfKnown = true; } else { IsSelfKnown = Player.m_localPlayer.m_knownMaterial.Contains(preLocalizeName) || Player.m_localPlayer.m_knownStations.ContainsKey(preLocalizeName); } } public void UpdateKnown() { if (IsSelfKnown) { isKnown = true; onKnownChanged.Invoke(); } else if (result.Any((RecipeInfo recipe) => recipe.IsSelfKnown) || ingredient.Any((RecipeInfo recipe) => recipe.IsSelfKnown)) { isKnown = true; onKnownChanged.Invoke(); } else { isKnown = false; onKnownChanged.Invoke(); } } public IEnumerable<Item> GetStations() { List<Item> list = new List<Item>(); list.AddRange(ingredient.SelectMany((RecipeInfo r) => r.GetStationItems())); list.AddRange(result.SelectMany((RecipeInfo r) => r.GetStationItems())); return list.Distinct().ToList(); } } public enum ItemType { Undefined, Creature, Piece, Item, Food, Armor, Weapon } public class ItemTypeHelper { public static ItemType GetItemType(ItemData itemData) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_006b: Expected I4, but got Unknown ItemType itemType = itemData.m_shared.m_itemType; ItemType val = itemType; switch (val - 2) { case 0: return ItemType.Food; case 4: case 5: case 9: case 10: case 15: return ItemType.Armor; case 1: case 2: case 3: case 12: case 13: case 20: return ItemType.Weapon; default: return ItemType.Item; } } } public class ModNames { private static readonly Dictionary<string, BepInPlugin> SourceMod = new Dictionary<string, BepInPlugin>(); public static void IndexModNames() { foreach (IModPrefab prefab in ModQuery.GetPrefabs()) { SetModOfPrefab(((Object)prefab.Prefab).name, prefab.SourceMod); } } public static void SetModOfPrefab(string prefabName, BepInPlugin mod) { if (!SourceMod.ContainsKey(prefabName)) { SourceMod[prefabName] = mod; } } public static BepInPlugin GetModByPrefabName(string name) { if (SourceMod.TryGetValue(name, out var value)) { return value; } return null; } } public class Part { public readonly Item item; public readonly Amount amount; public readonly int quality; public Part(Item item, Amount amount, int quality) { this.item = item; this.amount = amount; this.quality = quality; } protected bool Equals(Part other) { return object.Equals(item, other.item) && amount.Equals(other.amount) && quality == other.quality; } public override bool Equals(object obj) { if (obj == null) { return false; } if (this == obj) { return true; } if (obj.GetType() != GetType()) { return false; } return Equals((Part)obj); } public override int GetHashCode() { int num = ((item != null) ? item.GetHashCode() : 0); num = (num * 397) ^ amount.GetHashCode(); return (num * 397) ^ quality; } } public class RecipeInfo { public Dictionary<Amount, List<Part>> Ingredients { get; private set; } = new Dictionary<Amount, List<Part>>(); public Dictionary<Amount, List<Part>> Results { get; private set; } = new Dictionary<Amount, List<Part>>(); public List<Part> Stations { get; private set; } = new List<Part>(); public bool IsOnBlacklist { get; private set; } public static List<RecipeInfo> Recipes { get; private set; } = new List<RecipeInfo>(); public bool IsSelfKnown { get; private set; } public float Width { get; private set; } public IEnumerable<Item> GetStationItems() { if (Stations.Count >= 1) { return new Item[1] { Stations[0].item ?? Plugin.Instance.noStation }; } return new Item[1] { Plugin.Instance.noStation }; } public void UpdateKnown() { IsSelfKnown = CalcSelfKnown(); } private static bool AnySelfKnown(Dictionary<Amount, List<Part>> list) { return list.Where((KeyValuePair<Amount, List<Part>> pair) => pair.Key.max != 0 && pair.Value != null).Any((KeyValuePair<Amount, List<Part>> pair) => pair.Value.Any((Part part) => part.item.IsSelfKnown)); } private static bool AllSelfKnown(Dictionary<Amount, List<Part>> list) { return list.Where((KeyValuePair<Amount, List<Part>> pair) => pair.Key.max != 0 && pair.Value != null).All((KeyValuePair<Amount, List<Part>> pair) => pair.Value.All((Part part) => part.item.IsSelfKnown)); } private bool CalcSelfKnown() { if (!Plugin.ShowOnlyKnown) { return true; } if (Stations.Any((Part s) => !s.item.IsSelfKnown)) { return false; } if (AllSelfKnown(Ingredients)) { return true; } if (AllSelfKnown(Results)) { return true; } return false; } public void AddIngredient(string name, Amount groupAmount, Amount count, int quality) { Item item = Indexing.GetItem(name); if (item != null) { if (!Ingredients.ContainsKey(groupAmount)) { Ingredients.Add(groupAmount, new List<Part>()); } Ingredients[groupAmount].Add(new Part(item, count, quality)); } } public void AddIngredient<T>(T target, Amount groupAmount, Amount count, int quality, string context) where T : Object { if (Object.op_Implicit((Object)(object)target)) { AddIngredient(((Object)target).name, groupAmount, count, quality); } else { Log.LogDebug($"cannot add ingredient to '{context}', item is null (uses amount {count})"); } } public void AddResult(string name, Amount groupAmount, Amount count, int quality) { Item item = Indexing.GetItem(name); if (item != null) { if (!Results.ContainsKey(groupAmount)) { Results.Add(groupAmount, new List<Part>()); } Results[groupAmount].Add(new Part(item, count, quality)); } } public void AddResult<T>(T target, Amount groupAmount, Amount count, int quality, string context) where T : Object { if (Object.op_Implicit((Object)(object)target)) { AddResult(((Object)target).name, groupAmount, count, quality); } else { Log.LogDebug($"cannot add result to '{context}', item is null (uses amount {count})"); } } public void AddStation(Item item, int level) { if (item != null) { Stations.Add(new Part(item, new Amount(1), level)); } } public void AddStation(string name, int level) { AddStation(Indexing.GetItem(name), level); } public void AddStation<T>(T target, int level) where T : Object { if ((Object)(object)target != (Object)null) { AddStation(((Object)target).name, level); } else { Log.LogDebug("cannot set station: is null"); } } public void CalculateIsOnBlacklist() { if (Ingredients.SelectMany((KeyValuePair<Amount, List<Part>> i) => i.Value).Any((Part i) => i.item.isOnBlacklist)) { IsOnBlacklist = true; } else if (Results.SelectMany((KeyValuePair<Amount, List<Part>> i) => i.Value).Any((Part i) => i.item.isOnBlacklist)) { IsOnBlacklist = true; } } public RecipeInfo() { Recipes.Add(this); } public RecipeInfo(Recipe recipe, int quality) : this() { if ((Object)(object)recipe.GetRequiredStation(quality) != (Object)null) { this.AddStation<CraftingStation>(recipe.GetRequiredStation(quality), recipe.GetRequiredStationLevel(quality)); } else { AddStation(Plugin.Instance.handStation, 1); } this.AddResult<ItemDrop>(recipe.m_item, Amount.One, new Amount(recipe.m_amount), quality, ((Object)recipe).name); if (quality > 1) { this.AddIngredient<ItemDrop>(recipe.m_item, Amount.One, Amount.One, quality - 1, ((Object)recipe).name); } Requirement[] resources = recipe.m_resources; foreach (Requirement val in resources) { Amount amount = new Amount(val.GetAmount(quality)); if (!Amount.IsSameMinMax(amount, Amount.Zero)) { this.AddIngredient<ItemDrop>(val.m_resItem, Amount.One, amount, 1, ((Object)recipe).name); } } } public RecipeInfo(ItemConversion conversion, Smelter smelter) : this() { this.AddStation<Smelter>(smelter, 1); this.AddIngredient<ItemDrop>(conversion.m_from, Amount.One, Amount.One, 1, ((Object)smelter).name); if (Object.op_Implicit((Object)(object)smelter.m_fuelItem)) { this.AddIngredient<ItemDrop>(smelter.m_fuelItem, Amount.One, new Amount(smelter.m_fuelPerProduct), 1, ((Object)smelter).name); } this.AddResult<ItemDrop>(conversion.m_to, Amount.One, Amount.One, 1, ((Object)smelter).name); } public RecipeInfo(ItemConversion conversion, Fermenter fermenter) : this() { this.AddStation<Fermenter>(fermenter, 1); this.AddIngredient<ItemDrop>(conversion.m_from, Amount.One, Amount.One, 1, ((Object)fermenter).name); this.AddResult<ItemDrop>(conversion.m_to, Amount.One, new Amount(conversion.m_producedItems), 1, ((Object)fermenter).name); } public RecipeInfo(ItemConversion conversion, CookingStation cookingStation) : this() { this.AddStation<CookingStation>(cookingStation, 1); this.AddIngredient<ItemDrop>(conversion.m_from, Amount.One, Amount.One, 1, ((Object)cookingStation).name); this.AddResult<ItemDrop>(conversion.m_to, Amount.One, Amount.One, 1, ((Object)cookingStation).name); } public RecipeInfo(Incinerator incinerator) : this() { this.AddStation<Incinerator>(incinerator, 1); this.AddResult<ItemDrop>(incinerator.m_defaultResult, Amount.One, Amount.One, 1, ((Object)incinerator).name); AddIngredient("vnei_any_item", Amount.One, new Amount(incinerator.m_defaultCost), 1); } public RecipeInfo(IncineratorConversion conversion, Incinerator incinerator) : this() { this.AddStation<Incinerator>(incinerator, 1); this.AddResult<ItemDrop>(conversion.m_result, Amount.One, new Amount(conversion.m_resultAmount), 1, ((Object)incinerator).name); foreach (Requirement requirement in conversion.m_requirements) { this.AddIngredient<ItemDrop>(requirement.m_resItem, Amount.One, new Amount(requirement.m_amount), 1, ((Object)incinerator).name); } } public RecipeInfo(IncineratorConversion conversion, Requirement requirement, Incinerator incinerator) : this() { this.AddStation<Incinerator>(incinerator, 1); this.AddResult<ItemDrop>(conversion.m_result, Amount.One, new Amount(conversion.m_resultAmount), 1, ((Object)incinerator).name); this.AddIngredient<ItemDrop>(requirement.m_resItem, Amount.One, new Amount(requirement.m_amount), 1, ((Object)incinerator).name); } public RecipeInfo(CharacterDrop characterDrop) : this() { Character component = ((Component)characterDrop).GetComponent<Character>(); this.AddIngredient<Character>(component, Amount.One, Amount.One, 1, ((Object)component).name); foreach (Drop drop in characterDrop.m_drops) { this.AddResult<GameObject>(count: new Amount(drop.m_amountMin, drop.m_amountMax, drop.m_chance), target: drop.m_prefab, groupAmount: Amount.One, quality: 1, context: ((Object)component).name); } } public RecipeInfo(GameObject prefab, Piece piece, Item crafter) : this() { Stations.Add(new Part(crafter, new Amount(1), 1)); if (Object.op_Implicit((Object)(object)piece.m_craftingStation)) { this.AddStation<CraftingStation>(piece.m_craftingStation, 1); } Requirement[] resources = piece.m_resources; foreach (Requirement val in resources) { this.AddIngredient<ItemDrop>(val.m_resItem, Amount.One, new Amount(val.m_amount), 1, ((Object)prefab).name); } Plant val2 = default(Plant); if (((Component)piece).TryGetComponent<Plant>(ref val2)) { GameObject[] grownPrefabs = val2.m_grownPrefabs; if (grownPrefabs != null && grownPrefabs.Length >= 1) { GameObject[] grownPrefabs2 = val2.m_grownPrefabs; foreach (GameObject target in grownPrefabs2) { this.AddResult<GameObject>(target, Amount.One, new Amount(1, 1f / (float)val2.m_grownPrefabs.Length), 1, ((Object)prefab).name); } Indexing.DisableItem(((Object)prefab).name, "Plant has grownPrefabs"); return; } } this.AddResult<GameObject>(prefab, Amount.One, Amount.One, 1, ((Object)prefab).name); } public RecipeInfo(GameObject prefab, Pickable pickable) : this() { this.AddIngredient<GameObject>(prefab, Amount.One, Amount.One, 1, ((Object)prefab).name); this.AddResult<GameObject>(pickable.m_itemPrefab, Amount.One, new Amount(pickable.m_amount), 1, ((Object)pickable).name); if (pickable.m_extraDrops != null && pickable.m_extraDrops.m_drops.Count > 0) { AddDropTable(prefab, pickable.m_extraDrops); } CombineGroupAmounts(Results); } public RecipeInfo(GameObject from, DropTable dropTable) : this() { this.AddIngredient<GameObject>(from, Amount.One, Amount.One, 1, ((Object)from).name); AddDropTable(from, dropTable); if (dropTable.m_drops != null && dropTable.m_drops.Count == 0) { Indexing.DisableItem(((Object)from).name, "No drops in DropTable"); } } public RecipeInfo(SpawnArea spawnArea) : this() { this.AddIngredient<SpawnArea>(spawnArea, Amount.One, Amount.One, 1, ((Object)spawnArea).name); foreach (SpawnData prefab in spawnArea.m_prefabs) { this.AddResult<GameObject>(prefab.m_prefab, Amount.One, new Amount(1, 1f / (float)spawnArea.m_prefabs.Count), 1, ((Object)spawnArea).name); } } public RecipeInfo(Destructible spawnArea) : this() { this.AddIngredient<Destructible>(spawnArea, Amount.One, Amount.One, 1, ((Object)spawnArea).name); this.AddResult<GameObject>(spawnArea.m_spawnWhenDestroyed, Amount.One, Amount.One, 1, ((Object)spawnArea).name); } private void AddTreeLog(GameObject logPrefab, int depth, string name, int treeCount) { TreeLog val = default(TreeLog); if (depth > 50) { Log.LogWarning("TreeLog is recursively " + name); } else if (Object.op_Implicit((Object)(object)logPrefab) && logPrefab.TryGetComponent<TreeLog>(ref val)) { if (val.m_subLogPoints != null) { AddTreeLog(val.m_subLogPrefab, depth + 1, name, val.m_subLogPoints.Length); } AddDropTable(((Component)val).gameObject, val.m_dropWhenDestroyed, treeCount); Indexing.DisableItem(((Object)((Component)val).gameObject).name, name); } } public RecipeInfo(TreeBase treeBase) : this() { this.AddIngredient<TreeBase>(treeBase, Amount.One, Amount.One, 1, ((Object)treeBase).name); AddTreeLog(treeBase.m_logPrefab, 0, ((Object)treeBase).name, 1); AddDropTable(((Component)treeBase).gameObject, treeBase.m_dropWhenDestroyed); DropOnDestroyed val = default(DropOnDestroyed); if (Object.op_Implicit((Object)(object)treeBase.m_stubPrefab) && treeBase.m_stubPrefab.TryGetComponent<DropOnDestroyed>(ref val)) { AddDropTable(((Component)treeBase).gameObject, val.m_dropWhenDestroyed); Indexing.DisableItem(((Object)treeBase.m_stubPrefab).name, ((Object)((Component)treeBase).gameObject).name); } } public RecipeInfo(Trader trader, TradeItem tradeItem) : this() { this.AddStation<Trader>(trader, 1); this.AddIngredient<ItemDrop>(StoreGui.instance.m_coinPrefab, Amount.One, new Amount(tradeItem.m_price), 1, ((Object)trader).name); this.AddResult<ItemDrop>(tradeItem.m_prefab, Amount.One, new Amount(tradeItem.m_stack), 1, ((Object)trader).name); } public RecipeInfo(Growup growup) : this() { this.AddIngredient<GameObject>(((Component)growup).gameObject, Amount.One, Amount.One, 1, "growup base "); this.AddResult<GameObject>(growup.m_grownPrefab, Amount.One, Amount.One, 1, "growup result"); } private void AddDropTable(GameObject from, DropTable dropTable, int groupMultiplier = 1) { //IL_005a: Unknown result type (might be due to invalid IL or missing references) //IL_005f: Unknown result type (might be due to invalid IL or missing references) //IL_0069: Unknown result type (might be due to invalid IL or missing references) //IL_007b: Unknown result type (might be due to invalid IL or missing references) //IL_0082: Unknown result type (might be due to invalid IL or missing references) //IL_0088: Unknown result type (might be due to invalid IL or missing references) Amount groupAmount = new Amount(dropTable.m_dropMin * groupMultiplier, dropTable.m_dropMax * groupMultiplier, dropTable.m_dropChance); float num = dropTable.m_drops.Sum((DropData i) => i.m_weight); foreach (DropData drop in dropTable.m_drops) { float chance = ((num == 0f) ? 1f : (drop.m_weight / num)); this.AddResult<GameObject>(drop.m_item, groupAmount, new Amount(drop.m_stackMin, drop.m_stackMax, chance), 1, ((Object)from).name); } } public bool IngredientsAndResultSame() { return Ingredients.SequenceEqual(Results); } public void CalculateWidth() { float num = 0f; num += (float)Mathf.Max(1, Stations.Count) * 50f; foreach (KeyValuePair<Amount, List<Part>> ingredient in Ingredients) { if (Ingredients.Count > 1 || ingredient.Key.min != 1 || ingredient.Key.max != 1 || Math.Abs(ingredient.Key.chance - 1f) > 0.01f) { num += 50f; } num += (float)ingredient.Value.Count * 50f; } foreach (KeyValuePair<Amount, List<Part>> result in Results) { if (Results.Count > 1 || result.Key.min != 1 || result.Key.max != 1 || Math.Abs(result.Key.chance - 1f) > 0.01f) { num += 50f; } num += (float)result.Value.Count * 50f; } Width = num; } private void CombineGroupAmounts(Dictionary<Amount, List<Part>> groups) { if (groups.Keys.Count > 1 && !groups.Keys.Any((Amount i) => Math.Abs(i.chance - groups.Keys.First().chance) > 0.001f) && groups.Values.Count > 1 && !groups.Values.Any((List<Part> i) => !i.SequenceEqual(groups.Values.First()))) { Amount key = new Amount(groups.Keys.Sum((Amount i) => i.min), groups.Keys.Sum((Amount i) => i.max), groups.Keys.First().chance); List<Part> value = groups.Values.First(); groups.Clear(); groups.Add(key, value); } } public bool IsUpgrade(out Item item) { List<Part> list = (from i in Ingredients.Values.SelectMany((List<Part> i) => i) where i.item.maxQuality > 1 select i).ToList(); List<Part> list2 = (from i in Results.Values.SelectMany((List<Part> i) => i) where i.item.maxQuality > 1 select i).ToList(); if (list.Count != 1 || list2.Count != 1) { item = null; return false; } Part part = list[0]; Part part2 = list2[0]; item = part.item; return part.item == part2.item && part.quality < part2.quality; } } } namespace VNEI.Logic.Compatibility { public class PlanBuild { private static List<string> disableToolPieces = new List<string> { "piece_bpcapture", "piece_bpselectadd", "piece_bpselectremove", "piece_bpselectedit", "piece_bpsnappoint", "piece_bpcenterpoint", "piece_bpterrainmod", "piece_bpdelete", "piece_bpterrain", "piece_bpobjects", "piece_bppaint", "piece_plan_delete" }; public static void Init() { if (!Chainloader.PluginInfos.ContainsKey("marcopogo.PlanBuild")) { return; } Indexing.OnDisableItems += delegate(GameObject prefab) { if (Object.op_Implicit((Object)(object)prefab.GetComponent("PlanBuild.Plans.PlanPiece"))) { Indexing.DisableItem(((Object)prefab).name, "is PlanBuild PlanPiece"); } }; Indexing.AfterDisableItems += delegate { foreach (string disableToolPiece in disableToolPieces) { Indexing.DisableItem(disableToolPiece, "is PlanBuild tool piece"); } }; } } } namespace VNEI.UI { public class SelectUITest : MonoBehaviour { public class ToggleUIConsoleCommand : ConsoleCommand { public override string Name => "vnei_toggle_select_test"; public override string Help => "Shows the selection test"; public override void Run(string[] args) { if (!Object.op_Implicit((Object)(object)instance)) { Create(); return; } bool flag = ((UIBehaviour)instance.background).IsActive(); ((Component)instance.background).gameObject.SetActive(!flag); ((Component)instance.root).gameObject.SetActive(!flag); } } private static SelectUITest instance; public RectTransform root; public Image background; public Text text; public Button select; private SelectUI selection; public static void Create() { GameObject val = Plugin.AssetBundle.LoadAsset<GameObject>("SelectUITest"); GameObject val2 = Object.Instantiate<GameObject>(val, GUIManager.CustomGUIFront.transform); instance = val2.GetComponent<SelectUITest>(); ((Component)instance.background).gameObject.AddComponent<DragWindowCntrl>(); GUIManager.Instance.ApplyWoodpanelStyle(((Component)instance.background).transform); GUIManager.Instance.ApplyTextStyle(instance.text, 16); GUIManager.Instance.ApplyButtonStyle(instance.select, 16); } private void Start() { //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Expected O, but got Unknown ((UnityEvent)select.onClick).AddListener((UnityAction)delegate { //IL_002d: Unknown result type (might be due to invalid IL or missing references) if (!Object.op_Implicit((Object)(object)selection)) { Action<string> onSelect = delegate(string prefabName) { text.text = prefabName; }; selection = SelectUI.CreateSelection(GUIManager.CustomGUIFront.transform, onSelect, Vector2.zero, new ItemType[2] { ItemType.Piece, ItemType.Item }); } }); } private void Update() { //IL_0012: Unknown result type (might be due to invalid IL or missing references) ((Transform)root).position = ((Component)background).transform.position; } } [DefaultExecutionOrder(5)] public class BaseUI : MonoBehaviour { [Header("Local References")] public RectTransform root; public RectTransform dragHandler; public RectTransform lastViewItemsParent; public SearchUI searchUi; public RecipeUI recipeUi; [Header("Prefabs")] public GameObject itemPrefab; public GameObject rowPrefab; public GameObject recipeDroppedTextPrefab; public GameObject arrowPrefab; private List<DisplayItem> lastViewedDisplayItems = new List<DisplayItem>(); private List<Item> lastViewedItems = new List<Item>(); public const string HistoryQueueKey = "VNEI_History"; private bool sizeDirty; [HideInInspector] public List<ItemTypeToggle> typeToggles = new List<ItemTypeToggle>(); [HideInInspector] public FavoriteTypeToggle favoriteToggle; public Action typeToggleChange; private bool canBeHidden; private bool usePluginSize = true; public bool BlockInput { get; private set; } public int ItemSizeX { get; private set; } public int ItemSizeY { get; private set; } public event Action RebuildedSize; public static BaseUI CreateBaseUI(bool canBeHidden = false, bool scaleWithPluginSetting = false, bool draggable = true) { GameObject val = Object.Instantiate<GameObject>(Plugin.Instance.vneiUI, Object.op_Implicit((Object)(object)GUIManager.CustomGUIFront) ? GUIManager.CustomGUIFront.transform : null); BaseUI component = val.GetComponent<BaseUI>(); component.canBeHidden = canBeHidden; component.usePluginSize = scaleWithPluginSetting; if (component.usePluginSize) { Plugin.columnCount.SettingChanged += component.RebuildSizeEvent; Plugin.rowCount.SettingChanged += component.RebuildSizeEvent; } if (draggable) { ((Component)component.dragHandler).gameObject.AddComponent<DragWindowCntrl>(); } return component; } private void Awake() { //IL_00ce: Unknown result type (might be due to invalid IL or missing references) //IL_00dd: Unknown result type (might be due to invalid IL or missing references) BlockInput = false; ShowSearch(trackHistory: false); ShowSearch(trackHistory: true); Styling.ApplyAllComponents((Transform)(object)root); Styling.ApplyAllComponents(Plugin.Instance.craftingStationTemplate.transform); GUIManager.Instance.ApplyWoodpanelStyle((Transform)(object)dragHandler); recipeUi.OnSetItem += AddItemToLastViewedQueue; Plugin.OnOpenHotkey += UpdateVisibility; Plugin.transparency.SettingChanged += UpdateTransparency; Plugin.showRecentItems.SettingChanged += UpdateLastViewItemsParent; if (Object.op_Implicit((Object)(object)InventoryGui.instance)) { ((Component)this).transform.SetParent((Transform)(object)InventoryGui.instance.m_player); ((RectTransform)((Component)this).transform).anchoredPosition = new Vector2(665f, -45f); UpdateVisibility(); } else { SetVisibility(visible: false); } UpdateTransparency(null, EventArgs.Empty); UpdateLastViewItemsParent(null, EventArgs.Empty); RebuildSize(); RebuildDisplayItemRows(); } private void RebuildSizeEvent(object sender, EventArgs e) { sizeDirty = true; } private void RebuildSize() { //IL_005b: Unknown result type (might be due to invalid IL or missing references) //IL_0072: Unknown result type (might be due to invalid IL or missing references) //IL_0081: Unknown result type (might be due to invalid IL or missing references) //IL_0086: Unknown result type (might be due to invalid IL or missing references) if (usePluginSize) { ItemSizeX = Plugin.columnCount.Value; ItemSizeY = Plugin.rowCount.Value; } root.sizeDelta = new Vector2((float)ItemSizeX * 50f + 10f, (float)ItemSizeY * 50f + 100f); dragHandler.sizeDelta = root.sizeDelta + new Vector2(10f, 10f); this.RebuildedSize?.Invoke(); } private void Update() { //IL_008c: Unknown result type (might be due to invalid IL or missing references) //IL_00aa: Unknown result type (might be due to invalid IL or missing references) if (searchUi.searchField.isFocused && !BlockInput) { GUIManager.BlockInput(true); BlockInput = true; } else if (!searchUi.searchField.isFocused && BlockInput) { GUIManager.BlockInput(false); BlockInput = false; } if (sizeDirty) { sizeDirty = false; RebuildSize(); RebuildDisplayItemRows(); } if (Plugin.goForwardHotkey.Value.IsKeyDown()) { NextView(); } else if (Plugin.goBackHotkey.Value.IsKeyDown()) { PreviousView(); } } public void PreviousView() { UndoManager.Instance.Undo("VNEI_History"); } public void NextView() { if (UndoManager.Instance.GetQueue("VNEI_History").GetIndex() == -1) { UndoManager.Instance.Redo("VNEI_History"); } UndoManager.Instance.Redo("VNEI_History"); } private void RebuildDisplayItemRows() { RebuildDisplayItemRow(lastViewedDisplayItems, lastViewItemsParent); UpdateDisplayItemRow(lastViewedDisplayItems, lastViewedItems); } private void RebuildDisplayItemRow(List<DisplayItem> displayItems, RectTransform parent) { //IL_007c: Unknown result type (might be due to invalid IL or missing references) //IL_0086: Unknown result type (might be due to invalid IL or missing references) //IL_009f: Unknown result type (might be due to invalid IL or missing references) //IL_00c2: Unknown result type (might be due to invalid IL or missing references) foreach (DisplayItem displayItem in displayItems) { Object.Destroy((Object)(object)((Component)displayItem).gameObject); } displayItems.Clear(); if (!Object.op_Implicit((Object)(object)((Component)this).GetComponent<SelectUI>())) { int num = Mathf.Max(ItemSizeX - 5, 0); parent.anchoredPosition = new Vector2((float)num * 50f / 2f + 5f, parent.anchoredPosition.y); parent.sizeDelta = new Vector2((float)num * 50f, 50f); for (int i = 0; i < num; i++) { DisplayItem item = SpawnDisplayItem(new Vector2(25f + (float)(i * 50), -25f), (Transform)(object)parent); displayItems.Add(item); } } } private DisplayItem SpawnDisplayItem(Vector2 anchoredPosition, Transform parent) { //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Unknown result type (might be due to invalid IL or missing references) GameObject val = Object.Instantiate<GameObject>(itemPrefab, parent); ((RectTransform)val.transform).anchoredPosition = anchoredPosition; DisplayItem component = val.GetComponent<DisplayItem>(); component.Init(this); return component; } private void LateUpdate() { //IL_000d: Unknown result type (might be due to invalid IL or missing references) root.anchoredPosition = dragHandler.anchoredPosition; } public void ShowSearch(bool trackHistory) { SwitchView(delegate { ((Component)recipeUi).gameObject.SetActive(false); ((Component)searchUi).gameObject.SetActive(true); }, trackHistory); } public void ShowRecipe(Item item, bool trackHistory) { SwitchView(delegate { recipeUi.SetItem(item); ((Component)recipeUi).gameObject.SetActive(true); ((Component)searchUi).gameObject.SetActive(false); }, trackHistory && item != recipeUi.GetItem()); } private void SwitchView(Action changeView, bool trackHistory) { if (trackHistory) { HistorySnapshot currentView = GetCurrentView(); changeView?.Invoke(); HistorySnapshot currentView2 = GetCurrentView(); UndoManager.Instance.Add("VNEI_History", (IUndoAction)(object)new HistoryElement(currentView, currentView2)); } else { changeView?.Invoke(); } } private HistorySnapshot GetCurrentView() { if (((Component)recipeUi).gameObject.activeSelf) { return new HistorySnapshotRecipe(this, recipeUi.GetItem()); } return new HistorySnapshotSearch(this); } private void AddItemToLastViewedQueue(Item item) { lastViewedItems.Insert(0, item); for (int i = 1; i < lastViewedItems.Count; i++) { if (lastViewedItems[i] == item) { lastViewedItems.RemoveAt(i); } } if (lastViewedItems.Count > 50) { lastViewedItems.RemoveAt(lastViewedItems.Count - 1); } UpdateDisplayItemRow(lastViewedDisplayItems, lastViewedItems); } public void RemoveItemFromLastViewedQueue(Item item) { lastViewedItems.Remove(item); UpdateDisplayItemRow(lastViewedDisplayItems, lastViewedItems); } private static void UpdateDisplayItemRow(List<DisplayItem> displayItems, List<Item> items) { for (int i = 0; i < displayItems.Count; i++) { if (i >= items.Count) { displayItems[i].SetItem(null, 1); } else { displayItems[i].SetItem(items[i], 1); } } } private void OnDestroy() { recipeUi.OnSetItem -= AddItemToLastViewedQueue; Plugin.OnOpenHotkey -= UpdateVisibility; Plugin.transparency.SettingChanged -= UpdateTransparency; Plugin.showRecentItems.SettingChanged -= UpdateLastViewItemsParent; } public void SetSize(bool usePluginSize, int itemsX, int itemsY) { this.usePluginSize = usePluginSize; ItemSizeX = itemsX; ItemSizeY = itemsY; RebuildSize(); RebuildDisplayItemRows(); } public void SetVisibility(bool visible) { ((Component)root).gameObject.SetActive(visible); ((Component)dragHandler).gameObject.SetActive(visible); } private void UpdateVisibility() { SetVisibility(!canBeHidden || Plugin.isUiOpen); } private void UpdateTransparency(object sender, EventArgs args) { //IL_0032: Unknown result type (might be due to invalid IL or missing references) ((Graphic)((Component)dragHandler).GetComponent<Image>()).color = new Color(1f, 1f, 1f, 1f - (float)Plugin.transparency.Value / 100f); } private void UpdateLastViewItemsParent(object sender, EventArgs args) { ((Component)lastViewItemsParent).gameObject.SetActive(Plugin.showRecentItems.Value); } } public class CraftingStationElement : MonoBehaviour { public Image icon; public Button button; public UITooltip tooltip; [SerializeField] private Item station; public Item Station { get { return station; } set { station?.onKnownChanged.RemoveListener((Component)(object)this); station = value; station?.onKnownChanged.AddListener((Component)(object)this, UpdateIconAndTooltip); } } public void UpdateIconAndTooltip() { //IL_00e0: Unknown result type (might be due to invalid IL or missing references) //IL_00e6: Unknown result type (might be due to invalid IL or missing references) //IL_007a: Unknown result type (might be due to invalid IL or missing references) //IL_00ae: Unknown result type (might be due to invalid IL or missing references) //IL_00b4: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_0063: Unknown result type (might be due to invalid IL or missing references) //IL_0069: Unknown result type (might be due to invalid IL or missing references) if (Station != null) { if (Station.IsKnown) { ((Graphic)icon).color = Color.white; icon.sprite = Station.GetIcon(); tooltip.Set(Station.preLocalizeName, "", (RectTransform)null, default(Vector2)); } else { ((Graphic)icon).color = DisplayItem.unknownColor; icon.sprite = Plugin.Instance.noIconSprite; tooltip.Set("$vnei_unknown_item", "", (RectTransform)null, default(Vector2)); } } else { icon.sprite = null; tooltip.Set("", "", (RectTransform)null, default(Vector2)); } } private void OnDestroy() { Station?.onKnownChanged.RemoveListener((Component)(object)this); } } public class CraftingStationList : MonoBehaviour { public List<CraftingStationElement> stationElements = new List<CraftingStationElement>(); private int currentPage; private float elementXSpace = 5f; [SerializeField] private Item activeStation; public Item ActiveStation { get { return activeStation; } private set { activeStation = value; UpdateButtons(); this.OnStationChange?.Invoke(); } } public event Action OnStationChange; public void SetStations(List<Item> stations) { //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Unknown result type (might be due to invalid IL or missing references) //IL_0057: Unknown result type (might be due to invalid IL or missing references) //IL_005c: Unknown result type (might be due to invalid IL or missing references) //IL_0061: 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_0135: Expected O, but got Unknown //IL_0146: Unknown result type (might be due to invalid IL or missing references) //IL_0150: Unknown result type (might be due to invalid IL or missing references) //IL_016f: Unknown result type (might be due to invalid IL or missing references) //IL_0179: Expected O, but got Unknown ActiveStation = (stations.Contains(ActiveStation) ? ActiveStation : stations.FirstOrDefault()); ClearStations(); float num = ((RectTransform)Plugin.Instance.craftingStationTemplate.transform).sizeDelta.x + elementXSpace; Rect rect = ((RectTransform)((Component)this).transform).rect; float width = ((Rect)(ref rect)).width; int stationsPerPage = GetStationsPerPage(); float num2 = (width - num * (float)stationsPerPage + num) / 2f; for (int i = 0; i < stations.Count; i++) { Item station = stations[i]; CraftingStationElement component = Object.Instantiate<GameObject>(Plugin.Instance.craftingStationTemplate, ((Component)this).transform).GetComponent<CraftingStationElement>(); stationElements.Add(component); ((Object)component).name = station.internalName; component.Station = station; component.UpdateIconAndTooltip(); ((Component)component).gameObject.SetActive(i >= currentPage * stationsPerPage && i < (currentPage + 1) * stationsPerPage); RectTransform val = (RectTransform)((Component)component).transform; float num3 = num2 + num * (float)(i % stationsPerPage); val.anchoredPosition = new Vector2(num3, val.anchoredPosition.y); ((UnityEvent)component.button.onClick).AddListener((UnityAction)delegate { ActiveStation = station; }); } UpdateButtons(); } private void UpdateButtons() { //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_0040: 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_004d: Unknown result type (might be due to invalid IL or missing references) //IL_005a: Unknown result type (might be due to invalid IL or missing references) //IL_0067: Unknown result type (might be due to invalid IL or missing references) //IL_0078: Unknown result type (might be due to invalid IL or missing references) //IL_009a: Unknown result type (might be due to invalid IL or missing references) //IL_0093: Unknown result type (might be due to invalid IL or missing references) int stationsPerPage = GetStationsPerPage(); for (int i = 0; i < stationElements.Count; i++) { CraftingStationElement craftingStationElement = stationElements[i]; ColorBlock colors = ((Selectable)craftingStationElement.button).colors; ((ColorBlock)(ref colors)).normalColor = ((ActiveStation == craftingStationElement.Station) ? Color.white : Color.gray); ((ColorBlock)(ref colors)).highlightedColor = Color.white; ((ColorBlock)(ref colors)).pressedColor = Color.white; ((ColorBlock)(ref colors)).selectedColor = Color.white; ((Selectable)craftingStationElement.button).colors = colors; ((Graphic)craftingStationElement.icon).color = ((ActiveStation == craftingStationElement.Station) ? Color.white : Color.gray); ((Component)craftingStationElement).gameObject.SetActive(i >= currentPage * stationsPerPage && i < (currentPage + 1) * stationsPerPage); } } private void ClearStations() { foreach (CraftingStationElement stationElement in stationElements) { Object.Destroy((Object)(object)((Component)stationElement).gameObject); } stationElements.Clear(); currentPage = 0; } public IEnumerable<RecipeInfo> FilterRecipes(IEnumerable<RecipeInfo> recipes) { if