Please disclose if your mod was created primarily using AI tools by adding the 'AI Generated' category. Failing to do so may result in the mod being removed from Thunderstore.
Decompiled source of VNEI v0.17.4
VNEI.dll
Decompiled 4 days ago
The result has been truncated due to the large size, download it to view full contents!
using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Linq; using System.Reflection; using System.Reflection.Emit; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using System.Text.RegularExpressions; using System.Threading.Tasks; using Auga; using BepInEx; using BepInEx.Bootstrap; using BepInEx.Configuration; using BepInEx.Logging; using EpicLoot.Crafting; using EpicLoot.CraftingV2; using HarmonyLib; using JetBrains.Annotations; using Jotunn; using Jotunn.Entities; using Jotunn.GUI; using Jotunn.Managers; using Jotunn.Utils; 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.Serialization; using YamlDotNet.Serialization.NamingConventions; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)] [assembly: AssemblyTitle("VNEI")] [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("")] [assembly: AssemblyProduct("VNEI")] [assembly: AssemblyCopyright("Copyright © 2021")] [assembly: AssemblyTrademark("")] [assembly: ComVisible(false)] [assembly: Guid("43367351-2A51-4BC5-9028-1303450B71AB")] [assembly: AssemblyFileVersion("0.17.4")] [assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("0.17.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.17.4")] [BepInDependency(/*Could not decode attribute arguments.*/)] [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.17.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> 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_0438: Unknown result type (might be due to invalid IL or missing references) //IL_0442: 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>())); 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(); EpicLootCompat.Init(); WackysDatabaseCompat.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 { [CompilerGenerated] private sealed class <UpdateOtherTabs>d__1 : IEnumerator<object>, IDisposable, IEnumerator { private int <>1__state; private object <>2__current; private WaitForSeconds <wait>5__1; object IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <UpdateOtherTabs>d__1(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <wait>5__1 = null; <>1__state = -2; } private bool MoveNext() { //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Expected O, but got Unknown switch (<>1__state) { default: return false; case 0: <>1__state = -1; <wait>5__1 = new WaitForSeconds(1f); break; case 1: <>1__state = -1; MainVneiHandler.Instance.UpdateOtherTabs(); break; } <>2__current = <wait>5__1; <>1__state = 1; return true; } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } [HarmonyPatch(typeof(InventoryGui), "Awake")] [HarmonyPostfix] [HarmonyPriority(200)] public static void AwakePatch(InventoryGui __instance) { if (!Plugin.IsAugaLoaded()) { MainVneiHandler.Instance.GetTabButton(); ((MonoBehaviour)__instance).StartCoroutine(UpdateOtherTabs()); } else { MainVneiHandlerAuga.Instance.CreateBaseUI(); } } [IteratorStateMachine(typeof(<UpdateOtherTabs>d__1))] private static IEnumerator UpdateOtherTabs() { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <UpdateOtherTabs>d__1(0); } [HarmonyPatch(typeof(InventoryGui), "UpdateCraftingPanel")] [HarmonyPostfix] [HarmonyAfter(new string[] { "org.bepinex.plugins.jewelcrafting" })] public static void UpdateCraftingPanelPatch() { if (!Plugin.IsAugaLoaded()) { MainVneiHandler.Instance.UpdateTabPosition(); if (MainVneiHandler.Instance.VneiTabActive) { MainVneiHandler.Instance.SetTabActive(); } } } [HarmonyPatch(typeof(InventoryGui), "OnTabCraftPressed")] [HarmonyPatch(typeof(InventoryGui), "OnTabUpgradePressed")] [HarmonyPrefix] public static void OnTabCraftPressedPatch() { if (!Plugin.IsAugaLoaded()) { MainVneiHandler.Instance.SetTabInactive(); } } [HarmonyPatch(typeof(InventoryGui), "SetupCrafting")] [HarmonyPostfix] [HarmonyAfter(new string[] { "org.bepinex.plugins.jewelcrafting" })] public static void SetupCraftingPatch() { if (!Plugin.IsAugaLoaded() && MainVneiHandler.Instance.VneiTabActive) { MainVneiHandler.Instance.SetTabActive(); } } } public class ModCompat { private class ValheimRecycleFix { [CompilerGenerated] private sealed class <TargetMethods>d__0 : IEnumerable<MethodBase>, IEnumerable, IEnumerator<MethodBase>, IDisposable, IEnumerator { private int <>1__state; private MethodBase <>2__current; private int <>l__initialThreadId; private Type <valheimRecycle>5__1; MethodBase IEnumerator<MethodBase>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <TargetMethods>d__0(int <>1__state) { this.<>1__state = <>1__state; <>l__initialThreadId = Environment.CurrentManagedThreadId; } [DebuggerHidden] void IDisposable.Dispose() { <valheimRecycle>5__1 = null; <>1__state = -2; } private bool MoveNext() { switch (<>1__state) { default: return false; case 0: <>1__state = -1; <valheimRecycle>5__1 = Type.GetType("ValheimRecycle.ValheimRecycle, ValheimRecycle, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"); <>2__current = <valheimRecycle>5__1.GetMethod("GetOrCreateRecycleTab", BindingFlags.Instance | BindingFlags.NonPublic); <>1__state = 1; return true; case 1: <>1__state = -1; return false; } } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } [DebuggerHidden] IEnumerator<MethodBase> IEnumerable<MethodBase>.GetEnumerator() { if (<>1__state == -2 && <>l__initialThreadId == Environment.CurrentManagedThreadId) { <>1__state = 0; return this; } return new <TargetMethods>d__0(0); } [DebuggerHidden] IEnumerator IEnumerable.GetEnumerator() { return ((IEnumerable<MethodBase>)this).GetEnumerator(); } } [IteratorStateMachine(typeof(<TargetMethods>d__0))] [UsedImplicitly] private static IEnumerable<MethodBase> TargetMethods() { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <TargetMethods>d__0(-2); } [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; [HarmonyPatch(typeof(Player), "UpdateKnownRecipesList")] [HarmonyPatch(typeof(Player), "OnSpawned")] [HarmonyPatch(typeof(Player), "ResetCharacterKnownItems")] [HarmonyPostfix] public static void UpdateKnownRecipesListPatch() { KnownRecipesPatches.OnUpdateKnownRecipes?.Invoke(); } } } 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; } if ((int)((KeyboardShortcut)(ref shortcut)).MainKey == 0 || !Input.GetKeyDown(((KeyboardShortcut)(ref shortcut)).MainKey) || !((KeyboardShortcut)(ref shortcut)).Modifiers.All((Func<KeyCode, bool>)Input.GetKey)) { return false; } if (TextInput.IsVisible()) { return false; } return true; } } 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) { //IL_0098: Unknown result type (might be due to invalid IL or missing references) //IL_00a7: Expected O, but got Unknown 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 val = ((BuilderSkeleton<SerializerBuilder>)new SerializerBuilder()).WithNamingConvention(CamelCaseNamingConvention.Instance).Build(); ItemDrop val2 = default(ItemDrop); List<(string, string, string)> source = (from item in FilterInvalidItems(items, itemNamesFilterExcluded, modNamesFilterExcluded, modNamesFilterInclude) select (item.prefab.TryGetComponent<ItemDrop>(ref val2) ? ((object)(ItemType)(ref val2.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 = val.Serialize((object)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_0155: Unknown result type (might be due to invalid IL or missing references) //IL_015a: Unknown result type (might be due to invalid IL or missing references) //IL_0164: Unknown result type (might be due to invalid IL or missing references) //IL_0176: Unknown result type (might be due to invalid IL or missing references) //IL_017d: Expected O, but got Unknown //IL_018b: 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); val = icon.textureRect; int num4 = (int)(((Rect)(ref val)).y - icon.textureRectOffset.y); Texture2D val2 = new Texture2D(num, num2); val2.ReadPixels(new Rect((float)num3, (float)num4, (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 AfterIndexingItems; public static event Action AfterIndexingRecipes; 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) { //IL_02b3: Unknown result type (might be due to invalid IL or missing references) //IL_02b8: Unknown result type (might be due to invalid IL or missing references) 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; Item item = new Item(name, shared.m_name, shared.m_description, icon, itemType, prefab, shared.m_maxQuality); item.itemDropType = itemData.m_shared.m_itemType; AddItem(item); if (Object.op_Implicit((Object)(object)itemData.m_shared.m_buildPieces)) { pieceTables.Add(CleanupName(name), itemData.m_shared.m_buildPieces); } } 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); } } foreach (PieceTable value in pieceTables.Values) { foreach (GameObject piece in value.m_pieces) { TryAddItem<Piece>(piece, (Func<Piece, string>)((Piece i) => i.m_name), ((Object)piece).name, ItemType.Piece, (Func<Piece, string>)((Piece i) => i.m_description), (Func<Piece, Sprite>)((Piece i) => i.m_icon)); try { Indexing.OnIndexingItems?.Invoke(piece); } catch (Exception data2) { Log.LogError(data2); } } } try { Indexing.AfterIndexingItems?.Invoke(); } catch (Exception data3) { Log.LogError(data3); } } 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) { bool flag = WackysDatabaseCompat.HasRecipeEnableOverride(recipe); if (!(recipe.m_enabled || flag) || !Object.op_Implicit((Object)(object)recipe.m_item)) { continue; } for (int i = 1; i <= recipe.m_item.m_itemData.m_shared.m_maxQuality; i++) { if ((!flag || i != 1 || !WackysDatabaseCompat.CanBeUpgraded(recipe)) && (!flag || i <= 1 || !WackysDatabaseCompat.CanBeCrafted(recipe))) { 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))); } } } try { Indexing.AfterIndexingRecipes?.Invoke(); } catch (Exception data2) { Log.LogError(data2); } } 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 ItemType itemDropType; 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_00f4: Unknown result type (might be due to invalid IL or missing references) //IL_00f9: Unknown result type (might be due to invalid IL or missing references) //IL_00fa: Unknown result type (might be due to invalid IL or missing references) //IL_0105: Unknown result type (might be due to invalid IL or missing references) //IL_0112: Unknown result type (might be due to invalid IL or missing references) //IL_011b: 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); 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() { 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; } } if (WhichModAddedThis.IsLoaded) { return description.TrimEnd(Array.Empty<char>()) + WhichModAddedThis.GetTooltipModName(GetModName()); } return description; } 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()) { if (prefab != null && Object.op_Implicit((Object)(object)prefab.Prefab)) { 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"); } public RecipeInfo(Amount ingredientAmount, IEnumerable<(string, int)> ingredients, Amount resultAmount, IEnumerable<(string, int)> results, string station, int ingredientQuality = 1, int resultQuality = 1, int stationLevel = 1) : this() { foreach (var ingredient in ingredients) { AddIngredient(ingredient.Item1, ingredientAmount, new Amount(ingredient.Item2), ingredientQuality); } foreach (var result in results) { AddResult(result.Item1, resultAmount, new Amount(result.Item2), resultQuality); } AddStation(station, stationLevel); } 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; } public override string ToString() { return string.Join(", ", Ingredients.SelectMany((KeyValuePair<Amount, List<Part>> parts) => parts.Value.Select((Part part) => parts.Key.ToString() + " " + part.item.GetPrimaryName()))) + " -> " + string.Join(", ", Results.SelectMany((KeyValuePair<Amount, List<Part>> parts) => parts.Value.Select((Part part) => parts.Key.ToString() + " " + part.item.GetPrimaryName()))) + " @ " + string.Join(", ", Stations.Select((Part s) => s.item.GetPrimaryName())); } } } namespace VNEI.Logic.Compatibility { public static class EpicLootCompat { public static void Init() { if (Chainloader.PluginInfos.ContainsKey("randyknapp.mods.epicloot")) { Indexing.AfterIndexingRecipes += IndexMaterialConversions; Indexing.AfterIndexingRecipes += IndexSacrifices; } } private static void IndexMaterialConversions() { //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Unknown result type (might be due to invalid IL or missing references) foreach (KeyValuePair<MaterialConversionType, List<MaterialConversion>> item in (Dictionary<MaterialConversionType, List<MaterialConversion>>)(object)MaterialConversions.Conversions) { MaterialConversionType key = item.Key; List<MaterialConversion> value = item.Value; foreach (MaterialConversion item2 in value) { AddMaterialConversion(item2); } } } private static void AddMaterialConversion(MaterialConversion conversion) { Indexing.AddRecipeToItems(new RecipeInfo(Amount.One, conversion.Resources.Select((MaterialConversionRequirement r) => (r.Item, r.Amount)), Amount.One, new(string, int)[1] { (conversion.Product, conversion.Amount) }, "piece_enchantingtable")); } private static void IndexSacrifices() { foreach (DisenchantProductsConfig disenchantProduct in EnchantCostsHelper.Config.DisenchantProducts) { if (disenchantProduct.ItemNames.Count <= 0) { continue; } foreach (string itemName in disenchantProduct.ItemNames) { AddSacrifice(itemName, disenchantProduct); } } } private static void AddSacrifice(string itemName, DisenchantProductsConfig disenchantProductsConfig) { Indexing.AddRecipeToItems(new RecipeInfo(Amount.One, new(string, int)[1] { (itemName, 1) }, Amount.One, disenchantProductsConfig.Products.Select((ItemAmountConfig p) => (p.Item, p.Amount)), "piece_enchantingtable")); } } 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"); } }; } } public static class WackysDatabaseCompat { public static Dictionary<Recipe, bool> RequiredUpgradeItemsString = new Dictionary<Recipe, bool>(); public static Dictionary<Recipe, bool> RequiredCraftItemsString = new Dictionary<Recipe, bool>(); public static bool WackyMoleDatabaseLoaded { get; private set; } public static void Init() { WackyMoleDatabaseLoaded = Chainloader.PluginInfos.ContainsKey("WackyMole.WackysDatabase"); if (WackyMoleDatabaseLoaded) { Type type = AccessTools.TypeByName("wackydatabase.WMRecipeCust, WackysDatabase"); FieldInfo fieldInfo = AccessTools.Field(type, "RequiredUpgradeItemsString"); RequiredUpgradeItemsString = (Dictionary<Recipe, bool>)fieldInfo.GetValue(null); FieldInfo fieldInfo2 = AccessTools.Field(type, "RequiredCraftItemsString"); RequiredCraftItemsString = (Dictionary<Recipe, bool>)fieldInfo2.GetValue(null); } } public static bool HasRecipeEnableOverride(Recipe recipe) { if (!WackyMoleDatabaseLoaded) { return false; } if (RequiredUpgradeItemsString.TryGetValue(recipe, out var value) && value) { return true; } if (RequiredCraftItemsString.TryGetValue(recipe, out value) && value) { return true; } return false; } public static bool CanBeCrafted(Recipe recipe) { if (!WackyMoleDatabaseLoaded) { return true; } if (RequiredUpgradeItemsString.TryGetValue(recipe, out var value) && value) { return false; } return true; } public static bool CanBeUpgraded(Recipe recipe) { if (!WackyMoleDatabaseLoaded) { return true; } if (RequiredCraftItemsString.TryGetValue(recipe, out var value) && value) { return false; } return true; } } public class WhichModAddedThis { private static MethodInfo GetTooltipModNameMethod; public static bool IsLoaded => Chainloader.PluginInfos.ContainsKey("com.maxsch.valheim.WhichModAddedThis"); static WhichModAddedThis() { if (IsLoaded) { Type type = AccessTools.TypeByName("WhichModAddedThis.Patches, WhichModAddedThis"); GetTooltipModNameMethod = AccessTools.Method(type, "GetTooltipModName", (Type[])null, (Type[])null); } } public static string GetTooltipModName(string modName) { if (IsLoaded) { return (string)GetTooltipModNameMethod.Invoke(null, new object[1] { modName }); } return string.Empty; } } } 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_00bd: 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) bool isFocused = searchUi.searchField.isFocused; bool activeInHierarchy = ((Component)searchUi.searchField).gameObject.activeInHierarchy; bool flag = Object.op_Implicit((Object)(object)Hud.instance) && Hud.instance.IsVisible(); if (!BlockInput && isFocused && activeInHierarchy && flag) { GUIManager.BlockInput(true); BlockInput = true; } if (BlockInput && (!isFocused || !activeInHierarchy || !flag)) { 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, lastVie