Please disclose if any significant portion of your mod was created using AI tools by adding the 'AI Generated' category. Failing to do so may result in the mod being removed from Thunderstore.
Decompiled source of EnchantingPouch v1.2.11
plugins/EnchantingPouch.dll
Decompiled 7 hours agousing System; using System.Collections.Generic; using System.Diagnostics; using System.Globalization; using System.IO; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; using Microsoft.CodeAnalysis; using TMPro; using UnityEngine; using UnityEngine.Events; using UnityEngine.UI; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: IgnoresAccessChecksTo("assembly_guiutils")] [assembly: IgnoresAccessChecksTo("assembly_valheim")] [assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")] [assembly: AssemblyCompany("Valheim Overhaul")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyDescription("EpicLoot enchanting pouch with JamesJones progression, magic-blue world glow, no AzuEPI slot.")] [assembly: AssemblyFileVersion("1.2.0.0")] [assembly: AssemblyInformationalVersion("1.2.0")] [assembly: AssemblyProduct("EnchantingPouch")] [assembly: AssemblyTitle("EnchantingPouch")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.2.0.0")] [module: UnverifiableCode] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace EnchantingPouch { internal static class MatFilter { private static readonly HashSet<string> Exact = new HashSet<string>(StringComparer.OrdinalIgnoreCase) { "ForestToken", "IronBountyToken", "GoldBountyToken", "EtchedRunestoneMagic", "EtchedRunestoneRare", "EtchedRunestoneEpic", "EtchedRunestoneLegendary", "EtchedRunestoneMythic" }; internal static bool IsEnchantingMat(ItemData item) { if (item == null) { return false; } string text = null; if ((Object)(object)item.m_dropPrefab != (Object)null) { text = Utils.GetPrefabName(item.m_dropPrefab); } if (string.IsNullOrEmpty(text) && item.m_shared != null) { text = item.m_shared.m_name; } return IsEnchantingMatName(text); } internal static bool IsEnchantingMatName(string prefabOrToken) { if (string.IsNullOrEmpty(prefabOrToken)) { return false; } string text = prefabOrToken; if (text.StartsWith("$item_", StringComparison.OrdinalIgnoreCase)) { text = text.Substring(6); } if (Exact.Contains(text)) { return true; } if (text.StartsWith("Dust", StringComparison.OrdinalIgnoreCase) || text.StartsWith("Essence", StringComparison.OrdinalIgnoreCase) || text.StartsWith("Reagent", StringComparison.OrdinalIgnoreCase) || text.StartsWith("Shard", StringComparison.OrdinalIgnoreCase) || text.StartsWith("Runestone", StringComparison.OrdinalIgnoreCase) || text.StartsWith("EtchedRunestone", StringComparison.OrdinalIgnoreCase)) { return true; } if (text.IndexOf("_Unidentified", StringComparison.OrdinalIgnoreCase) >= 0) { return true; } return false; } } [HarmonyPatch(typeof(Humanoid), "UseItem")] internal static class Humanoid_UseItem_Patch { private static bool Prefix(Humanoid __instance, ItemData item) { Player val = (Player)(object)((__instance is Player) ? __instance : null); if (val == null || (Object)(object)val != (Object)(object)Player.m_localPlayer) { return true; } if (!PouchItem.IsPouch(item)) { return true; } PouchItem.ToggleEquip(val, item); return false; } } [HarmonyPatch(typeof(InventoryGui), "Update")] internal static class InventoryGui_Update_OpenPouch_Patch { internal static bool SuppressHideOnce; internal static int BlockShowFrames; private static void Prefix(InventoryGui __instance) { if (!Plugin.OpenWithE.Value || (Object)(object)__instance == (Object)null || !InventoryGui.IsVisible() || (Object)(object)__instance.m_dragGo != (Object)null || (!ZInput.GetButtonDown("Use") && !ZInput.GetButtonDown("JoyUse"))) { return; } ItemData val = GetHoveredItem(__instance.m_playerGrid) ?? GetHoveredItem(__instance.m_containerGrid); if (val != null && PouchItem.IsPouch(val)) { Player localPlayer = Player.m_localPlayer; if (!((Object)(object)localPlayer == (Object)null)) { ZInput.ResetButtonStatus("Use"); ZInput.ResetButtonStatus("JoyUse"); SuppressHideOnce = true; PouchContainer.Toggle(localPlayer, val); } } } private static void Postfix() { SuppressHideOnce = false; if (BlockShowFrames > 0) { BlockShowFrames--; } } private static ItemData GetHoveredItem(InventoryGrid grid) { //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_008a: Unknown result type (might be due to invalid IL or missing references) //IL_009e: Unknown result type (might be due to invalid IL or missing references) if (grid?.m_elements == null || grid.m_inventory == null) { return null; } Vector2 val = Vector2.op_Implicit(ZInput.mousePosition); foreach (Element element in grid.m_elements) { if ((Object)(object)element?.m_go == (Object)null || !element.m_go.activeInHierarchy) { continue; } Transform transform = element.m_go.transform; RectTransform val2 = (RectTransform)(object)((transform is RectTransform) ? transform : null); if (val2 != null) { Canvas componentInParent = element.m_go.GetComponentInParent<Canvas>(); Camera val3 = (((Object)(object)componentInParent != (Object)null && (int)componentInParent.renderMode != 0) ? componentInParent.worldCamera : null); if (RectTransformUtility.RectangleContainsScreenPoint(val2, val, val3)) { return grid.m_inventory.GetItemAt(element.m_pos.x, element.m_pos.y); } } } return null; } } [HarmonyPatch(typeof(Container), "IsOwner")] internal static class Container_IsOwner_Patch { private static void Postfix(Container __instance, ref bool __result) { if (!__result && PouchContainer.IsOurContainer(__instance)) { __result = true; } } } [HarmonyPatch(typeof(InventoryGui), "Hide")] internal static class InventoryGui_Hide_Patch { private static bool Prefix() { bool flag = ZInput.GetKeyDown((KeyCode)27, true) || ZInput.GetButtonDown("Inventory") || ZInput.GetButtonDown("JoyButtonB") || ZInput.GetButtonDown("JoyButtonY"); if (InventoryGui_Update_OpenPouch_Patch.SuppressHideOnce) { InventoryGui_Update_OpenPouch_Patch.SuppressHideOnce = false; if (!flag) { return false; } } if (PouchContainer.IsOpen || PouchContainer.BoundItem != null) { PouchContainer.Close(save: true); } PouchCloseButton.SetVisible(visible: false); InventoryGui_Update_OpenPouch_Patch.BlockShowFrames = 5; return true; } } [HarmonyPatch(typeof(InventoryGui), "Show")] internal static class InventoryGui_Show_Patch { private static bool Prefix(InventoryGui __instance, Container container) { if (PouchContainer.OpeningGuarded) { return true; } if (InventoryGui_Update_OpenPouch_Patch.BlockShowFrames <= 0) { return true; } if (InventoryGui.IsVisible()) { return true; } return false; } } [HarmonyPatch(typeof(InventoryGui), "CloseContainer")] internal static class InventoryGui_CloseContainer_Patch { private static void Prefix(InventoryGui __instance) { if (PouchContainer.IsBoundContainer(((Object)(object)__instance != (Object)null) ? __instance.m_currentContainer : null)) { PouchContainer.OnContainerClosing(); } } } [HarmonyPatch(typeof(Player), "GetAvailableRecipes")] internal static class Player_GetAvailableRecipes_Patch { private static void Postfix(Player __instance, ref List<Recipe> available) { PouchItem.EnsureAvailable(__instance, available); } } [HarmonyPatch(typeof(Player), "UpdateKnownRecipesList")] internal static class Player_UpdateKnownRecipesList_Patch { private static void Postfix(Player __instance) { PouchItem.UnlockKnownRecipe(__instance); } } [HarmonyPatch(typeof(Player), "OnSpawned")] internal static class Player_OnSpawned_Patch { private static void Postfix(Player __instance) { PouchItem.UnlockKnownRecipe(__instance); if ((Object)(object)ObjectDB.instance != (Object)null) { PouchItem.TryRegister(ObjectDB.instance); } PouchItem.FixDropPrefabs(((Humanoid)__instance).GetInventory()); } } internal static class WorldPickupGuard { [ThreadStatic] private static int _depth; internal static bool IsWorldPickup => _depth > 0; internal static void Enter() { _depth++; } internal static void Exit() { if (_depth > 0) { _depth--; } } } [HarmonyPatch(typeof(ItemDrop), "Pickup")] internal static class ItemDrop_Pickup_Patch { private static void Prefix() { WorldPickupGuard.Enter(); } private static void Finally() { WorldPickupGuard.Exit(); } } [HarmonyPatch(typeof(Inventory), "AddItem", new Type[] { typeof(ItemData) })] internal static class Inventory_AddItem_Patch { [ThreadStatic] private static bool _busy; private static bool Prefix(Inventory __instance, ItemData item, ref bool __result) { if (_busy || !Plugin.AutoDeposit.Value || !WorldPickupGuard.IsWorldPickup || item == null || !MatFilter.IsEnchantingMat(item)) { return true; } if (PouchContainer.IsOpen && PouchContainer.GetInventory() == __instance) { return true; } Player localPlayer = Player.m_localPlayer; if ((Object)(object)localPlayer == (Object)null || __instance != ((Humanoid)localPlayer).GetInventory()) { return true; } ItemData val = PouchItem.FindEquipped(localPlayer); if (val == null) { return true; } return TryDeposit(localPlayer, val, item, ref __result); } private static bool TryDeposit(Player player, ItemData pouch, ItemData item, ref bool __result) { Inventory val = ((PouchContainer.IsOpen && PouchContainer.BoundItem == pouch) ? PouchContainer.GetInventory() : null); _busy = true; try { if (val != null) { if (!val.CanAddItem(item, -1)) { return true; } val.AddItem(item); __result = true; return false; } Inventory val2 = PouchContainer.PeekInventory(pouch); if (!val2.CanAddItem(item, -1)) { return true; } val2.AddItem(item); PouchContainer.CommitPeek(pouch, val2); __result = true; return false; } finally { _busy = false; } } } [HarmonyPatch(typeof(Inventory), "AddItem", new Type[] { typeof(string), typeof(int), typeof(int), typeof(int), typeof(long), typeof(string), typeof(bool) })] internal static class Inventory_AddItem_Prefab_Patch { [ThreadStatic] private static bool _busy; private static bool Prefix(Inventory __instance, string name, int stack, int quality, int variant, long crafterID, string crafterName, ref ItemData __result) { if (_busy || !Plugin.AutoDeposit.Value || !WorldPickupGuard.IsWorldPickup || !MatFilter.IsEnchantingMatName(name)) { return true; } if (PouchContainer.IsOpen && PouchContainer.GetInventory() == __instance) { return true; } Player localPlayer = Player.m_localPlayer; if ((Object)(object)localPlayer == (Object)null || __instance != ((Humanoid)localPlayer).GetInventory()) { return true; } ItemData val = PouchItem.FindEquipped(localPlayer); if (val == null) { return true; } GameObject val2 = (((Object)(object)ObjectDB.instance != (Object)null) ? ObjectDB.instance.GetItemPrefab(name) : null); if ((Object)(object)val2 == (Object)null) { return true; } ItemData val3 = val2.GetComponent<ItemDrop>().m_itemData.Clone(); val3.m_stack = stack; val3.m_quality = quality; val3.m_variant = variant; val3.m_crafterID = crafterID; val3.m_crafterName = crafterName; val3.m_dropPrefab = val2; Inventory val4 = ((PouchContainer.IsOpen && PouchContainer.BoundItem == val) ? PouchContainer.GetInventory() : null); _busy = true; try { if (val4 != null) { if (!val4.CanAddItem(val3, -1)) { return true; } val4.AddItem(val3); __result = val3; return false; } Inventory val5 = PouchContainer.PeekInventory(val); if (!val5.CanAddItem(val3, -1)) { return true; } val5.AddItem(val3); PouchContainer.CommitPeek(val, val5); __result = val3; return false; } finally { _busy = false; } } } [BepInPlugin("valheimoverhaul.enchantingpouch", "Enchanting Pouch", "1.2.11")] [BepInDependency(/*Could not decode attribute arguments.*/)] public sealed class Plugin : BaseUnityPlugin { public const string PluginGuid = "valheimoverhaul.enchantingpouch"; public const string PluginName = "Enchanting Pouch"; public const string PluginVersion = "1.2.11"; internal const string PrefabName = "VO_EnchantingPouch"; internal const string ItemToken = "$item_vo_enchantingpouch"; internal const string DescToken = "$item_vo_enchantingpouch_desc"; internal const string CustomDataKey = "valheimoverhaul.enchantingpouch.inv"; internal const string WeightCacheKey = "valheimoverhaul.enchantingpouch.weight"; internal static Plugin Instance; internal static ManualLogSource Log; internal static ConfigEntry<int> Columns; internal static ConfigEntry<int> Rows; internal static ConfigEntry<bool> AutoDeposit; internal static ConfigEntry<bool> OpenWithE; internal static ConfigEntry<bool> OpenOnInventory; private void Awake() { //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Expected O, but got Unknown //IL_0064: Unknown result type (might be due to invalid IL or missing references) //IL_006e: Expected O, but got Unknown //IL_00d8: Unknown result type (might be due to invalid IL or missing references) //IL_00de: Expected O, but got Unknown Instance = this; Log = ((BaseUnityPlugin)this).Logger; Columns = ((BaseUnityPlugin)this).Config.Bind<int>("Storage", "Columns", 2, new ConfigDescription("Fallback columns if quality size fails (normal size comes from upgrade level).", (AcceptableValueBase)(object)new AcceptableValueRange<int>(2, 8), Array.Empty<object>())); Rows = ((BaseUnityPlugin)this).Config.Bind<int>("Storage", "Rows", 4, new ConfigDescription("Fallback rows if quality size fails (normal size comes from upgrade level).", (AcceptableValueBase)(object)new AcceptableValueRange<int>(2, 8), Array.Empty<object>())); AutoDeposit = ((BaseUnityPlugin)this).Config.Bind<bool>("Storage", "Auto Deposit", true, "While the pouch is equipped, auto-store EpicLoot mats picked up from the ground only."); OpenWithE = ((BaseUnityPlugin)this).Config.Bind<bool>("Controls", "Open With E", true, "Press E (Use) while hovering the pouch in the inventory to open it. Vanilla E closes inventory; this intercepts that when the pouch is under the cursor."); OpenOnInventory = ((BaseUnityPlugin)this).Config.Bind<bool>("Controls", "Open With Inventory", false, "Unused/legacy. Opening is via E hover; right-click equips."); Harmony val = new Harmony("valheimoverhaul.enchantingpouch"); Type[] types = typeof(Plugin).Assembly.GetTypes(); foreach (Type type in types) { try { val.CreateClassProcessor(type).Patch(); } catch (Exception ex) { Log.LogError((object)("Failed to patch " + type.Name + ": " + ex.Message)); } } Log.LogInfo((object)"Enchanting Pouch 1.2.11 loaded."); } } internal static class PouchCloseButton { [CompilerGenerated] private static class <>O { public static UnityAction <0>__OnClicked; } private static GameObject _root; private static Button _button; internal static void Ensure(InventoryGui gui) { //IL_0088: Unknown result type (might be due to invalid IL or missing references) //IL_009d: Unknown result type (might be due to invalid IL or missing references) //IL_00b2: Unknown result type (might be due to invalid IL or missing references) //IL_00c7: Unknown result type (might be due to invalid IL or missing references) //IL_00dc: Unknown result type (might be due to invalid IL or missing references) //IL_00e7: Unknown result type (might be due to invalid IL or missing references) //IL_0175: Unknown result type (might be due to invalid IL or missing references) //IL_017f: Expected O, but got Unknown //IL_0199: Unknown result type (might be due to invalid IL or missing references) //IL_019e: Unknown result type (might be due to invalid IL or missing references) //IL_01a4: Expected O, but got Unknown if (!((Object)(object)gui?.m_container == (Object)null) && !((Object)(object)gui.m_tabUpgrade == (Object)null) && (!((Object)(object)_root != (Object)null) || ((object)_root).Equals((object?)null))) { _root = Object.Instantiate<GameObject>(((Component)gui.m_tabUpgrade).gameObject, (Transform)(object)gui.m_container, false); ((Object)_root).name = "VO_PouchCloseX"; RectTransform component = _root.GetComponent<RectTransform>(); if ((Object)(object)component != (Object)null) { component.anchorMin = new Vector2(1f, 1f); component.anchorMax = new Vector2(1f, 1f); component.pivot = new Vector2(1f, 1f); component.anchoredPosition = new Vector2(-6f, -6f); component.sizeDelta = new Vector2(36f, 36f); ((Transform)component).localScale = Vector3.one; ((Transform)component).SetAsLastSibling(); } TMP_Text[] componentsInChildren = _root.GetComponentsInChildren<TMP_Text>(true); for (int i = 0; i < componentsInChildren.Length; i++) { componentsInChildren[i].text = "X"; } Text[] componentsInChildren2 = _root.GetComponentsInChildren<Text>(true); for (int i = 0; i < componentsInChildren2.Length; i++) { componentsInChildren2[i].text = "X"; } _button = _root.GetComponent<Button>(); if ((Object)(object)_button == (Object)null) { _button = _root.AddComponent<Button>(); } _button.onClick = new ButtonClickedEvent(); ButtonClickedEvent onClick = _button.onClick; object obj = <>O.<0>__OnClicked; if (obj == null) { UnityAction val = OnClicked; <>O.<0>__OnClicked = val; obj = (object)val; } ((UnityEvent)onClick).AddListener((UnityAction)obj); _root.SetActive(false); } } internal static void SetVisible(bool visible) { if (((Object)(object)_root == (Object)null || ((object)_root).Equals((object?)null)) && visible && (Object)(object)InventoryGui.instance != (Object)null) { Ensure(InventoryGui.instance); } if ((Object)(object)_root != (Object)null && !((object)_root).Equals((object?)null)) { _root.SetActive(visible); } } private static void OnClicked() { if (PouchContainer.IsOpen) { PouchContainer.Close(save: true); } SetVisible(visible: false); } } [HarmonyPatch(typeof(InventoryGui), "Awake")] internal static class InventoryGui_Awake_PouchClose_Patch { private static void Postfix(InventoryGui __instance) { PouchCloseButton.Ensure(__instance); } } [HarmonyPatch(typeof(InventoryGui), "UpdateContainer")] internal static class InventoryGui_UpdateContainer_PouchClose_Patch { private static void Postfix() { PouchCloseButton.SetVisible(PouchContainer.IsOpen); } } internal static class PouchContainer { private static Container _container; private static ItemData _boundItem; private static bool _suppressSave; internal static bool OpeningGuarded { get; private set; } internal static bool IsOpen { get { if (_boundItem != null && (Object)(object)InventoryGui.instance != (Object)null) { return (Object)(object)InventoryGui.instance.m_currentContainer == (Object)(object)_container; } return false; } } internal static ItemData BoundItem => _boundItem; internal static Inventory GetInventory() { if (!((Object)(object)_container != (Object)null)) { return null; } return _container.GetInventory(); } internal static bool IsOurContainer(Container container) { if ((Object)(object)container != (Object)null && (Object)(object)_container != (Object)null) { return container == _container; } return false; } internal static bool IsBoundContainer(Container container) { return IsOurContainer(container); } internal static void Toggle(Player player, ItemData pouch) { if (!((Object)(object)player == (Object)null) && pouch != null) { if (IsOpen && _boundItem == pouch) { Close(save: true); } else { Open(player, pouch); } } } internal static void Open(Player player, ItemData pouch) { if ((Object)(object)player == (Object)null || pouch == null || (Object)(object)InventoryGui.instance == (Object)null) { return; } EnsureContainer(player, pouch); if ((Object)(object)_container == (Object)null) { Plugin.Log.LogError((object)"Enchanting Pouch: failed to create container."); return; } if (_boundItem != null && _boundItem != pouch) { SaveBound(); } _suppressSave = true; try { Inventory inventory = _container.GetInventory(); inventory.RemoveAll(); LoadInto(inventory, pouch); } finally { _suppressSave = false; } _boundItem = pouch; InventoryGui instance = InventoryGui.instance; bool flag = InventoryGui.IsVisible(); OpeningGuarded = true; try { if (flag) { if ((Object)(object)instance.m_currentContainer != (Object)null && instance.m_currentContainer != _container) { instance.CloseContainer(); } instance.m_currentContainer = _container; _container.SetInUse(true); } else { instance.Show(_container, 1); } } finally { OpeningGuarded = false; } PouchCloseButton.SetVisible(visible: true); } internal static void Close(bool save) { if (save) { SaveBound(); } InventoryGui instance = InventoryGui.instance; bool num = (Object)(object)instance != (Object)null && (Object)(object)instance.m_currentContainer == (Object)(object)_container; _boundItem = null; PouchCloseButton.SetVisible(visible: false); if (num) { instance.CloseContainer(); } } internal static void OnContainerClosing() { SaveBound(); _boundItem = null; PouchCloseButton.SetVisible(visible: false); } internal static void SaveBound() { if (_boundItem != null && !((Object)(object)_container == (Object)null) && !_suppressSave) { SaveFrom(_container.GetInventory(), _boundItem); } } internal static void OnInventoryChanged() { if (!_suppressSave && IsOpen) { SaveBound(); } } private static void EnsureContainer(Player player, ItemData pouch) { //IL_000c: 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_0095: Unknown result type (might be due to invalid IL or missing references) //IL_009a: Unknown result type (might be due to invalid IL or missing references) //IL_00ac: Unknown result type (might be due to invalid IL or missing references) //IL_00b2: Unknown result type (might be due to invalid IL or missing references) //IL_00bc: Unknown result type (might be due to invalid IL or missing references) //IL_00c3: Unknown result type (might be due to invalid IL or missing references) //IL_00ca: Unknown result type (might be due to invalid IL or missing references) //IL_0100: Unknown result type (might be due to invalid IL or missing references) //IL_0203: Unknown result type (might be due to invalid IL or missing references) //IL_014d: Unknown result type (might be due to invalid IL or missing references) //IL_0153: Expected O, but got Unknown Vector2i size = PouchProgression.GetSize(pouch?.m_quality ?? 1); int x = size.x; int y = size.y; if ((Object)(object)_container != (Object)null && ((object)_container).Equals((object?)null)) { _container = null; } if ((Object)(object)_container != (Object)null) { Inventory inventory = _container.GetInventory(); if (inventory == null || inventory.GetWidth() != x || inventory.GetHeight() != y) { Object.Destroy((Object)(object)((Component)_container).gameObject); _container = null; } } if ((Object)(object)_container == (Object)null) { GameObject val = new GameObject("VO_EnchantingPouch_Container"); val.transform.SetParent(((Component)player).transform, false); val.transform.localPosition = Vector3.zero; val.SetActive(false); val.AddComponent<ZNetView>(); _container = val.AddComponent<Container>(); _container.m_name = "Enchanting Pouch"; _container.m_width = x; _container.m_height = y; _container.m_privacy = (PrivacySetting)2; _container.m_checkGuardStone = false; _container.m_autoDestroyEmpty = false; val.SetActive(true); Inventory val2 = _container.GetInventory(); if (val2 == null) { FieldInfo? field = typeof(Container).GetField("m_inventory", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); val2 = new Inventory("Enchanting Pouch", (Sprite)null, x, y); field?.SetValue(_container, val2); } Inventory obj = val2; obj.m_onChanged = (Action)Delegate.Remove(obj.m_onChanged, new Action(OnInventoryChanged)); Inventory obj2 = val2; obj2.m_onChanged = (Action)Delegate.Combine(obj2.m_onChanged, new Action(OnInventoryChanged)); } else { if ((Object)(object)((Component)_container).transform.parent != (Object)(object)((Component)player).transform) { ((Component)_container).transform.SetParent(((Component)player).transform, false); } ((Component)_container).transform.localPosition = Vector3.zero; } } internal static float GetContentsWeight(ItemData pouch) { if (pouch == null) { return 0f; } Inventory val = PeekInventory(pouch); float num = ((val != null) ? (val.GetTotalWeight() * 0.5f) : 0f); SetCachedWeight(pouch, num); return num; } internal static float GetCachedContentsWeight(ItemData pouch) { if (pouch?.m_customData != null && pouch.m_customData.TryGetValue("valheimoverhaul.enchantingpouch.weight", out var value) && float.TryParse(value, NumberStyles.Float, CultureInfo.InvariantCulture, out var result)) { return result; } return GetContentsWeight(pouch); } private static void SetCachedWeight(ItemData pouch, float weight) { if (pouch.m_customData == null) { pouch.m_customData = new Dictionary<string, string>(); } pouch.m_customData["valheimoverhaul.enchantingpouch.weight"] = weight.ToString(CultureInfo.InvariantCulture); } private static void SaveFrom(Inventory inv, ItemData pouch) { //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Expected O, but got Unknown if (inv != null && pouch != null) { if (pouch.m_customData == null) { pouch.m_customData = new Dictionary<string, string>(); } ZPackage val = new ZPackage(); inv.Save(val); pouch.m_customData["valheimoverhaul.enchantingpouch.inv"] = Convert.ToBase64String(val.GetArray()); SetCachedWeight(pouch, inv.GetTotalWeight() * 0.5f); } } private static void LoadInto(Inventory inv, ItemData pouch) { //IL_0036: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Expected O, but got Unknown if (inv == null || pouch?.m_customData == null || !pouch.m_customData.TryGetValue("valheimoverhaul.enchantingpouch.inv", out var value) || string.IsNullOrEmpty(value)) { return; } try { ZPackage val = new ZPackage(Convert.FromBase64String(value)); inv.Load(val); } catch (Exception ex) { Plugin.Log.LogWarning((object)("Failed to load pouch inventory: " + ex.Message)); } } internal static Inventory PeekInventory(ItemData pouch) { //IL_000c: 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_0018: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Expected O, but got Unknown //IL_0031: Expected O, but got Unknown Vector2i size = PouchProgression.GetSize(pouch?.m_quality ?? 1); Inventory val = new Inventory("Enchanting Pouch Temp", (Sprite)null, size.x, size.y); LoadInto(val, pouch); return val; } internal static void CommitPeek(ItemData pouch, Inventory inv) { SaveFrom(inv, pouch); if (IsOpen && _boundItem == pouch && (Object)(object)_container != (Object)null) { _suppressSave = true; try { _container.GetInventory().RemoveAll(); LoadInto(_container.GetInventory(), pouch); } finally { _suppressSave = false; } } } } internal static class PouchItem { internal static GameObject Prefab; internal static Recipe Recipe; private static readonly string[] MeshPrefabCandidates = new string[9] { "LeatherScraps", "DeerHide", "Coins", "SurtlingCore", "Wood", "Stone", "Flint", "Resin", "TrophyBoar" }; private static bool _loggedCloneFailure; internal static bool IsPouch(ItemData item) { if (item?.m_shared == null) { return false; } if ((Object)(object)item.m_dropPrefab != (Object)null && Utils.GetPrefabName(item.m_dropPrefab) == "VO_EnchantingPouch") { return true; } return item.m_shared.m_name == "$item_vo_enchantingpouch"; } internal static void FixDropPrefab(ItemData item) { if (item != null && IsPouch(item) && (Object)(object)Prefab != (Object)null && !((object)Prefab).Equals((object?)null)) { item.m_dropPrefab = Prefab; } } internal static void FixDropPrefabs(Inventory inventory) { if (inventory == null) { return; } foreach (ItemData allItem in inventory.GetAllItems()) { FixDropPrefab(allItem); } } internal static ItemData FindInInventory(Player player) { if ((Object)(object)player == (Object)null) { return null; } foreach (ItemData allItem in ((Humanoid)player).GetInventory().GetAllItems()) { if (IsPouch(allItem)) { return allItem; } } return null; } internal static ItemData FindEquipped(Player player) { if ((Object)(object)player == (Object)null) { return null; } foreach (ItemData allItem in ((Humanoid)player).GetInventory().GetAllItems()) { if (IsPouch(allItem) && allItem.m_equipped) { return allItem; } } return null; } internal static void ToggleEquip(Player player, ItemData pouch) { if ((Object)(object)player == (Object)null || pouch == null) { return; } if (pouch.m_equipped) { pouch.m_equipped = false; ((Character)player).Message((MessageType)2, "Enchanting Pouch unequipped", 0, (Sprite)null); return; } foreach (ItemData allItem in ((Humanoid)player).GetInventory().GetAllItems()) { if (IsPouch(allItem)) { allItem.m_equipped = false; } } pouch.m_equipped = true; ((Character)player).Message((MessageType)2, "Enchanting Pouch equipped", 0, (Sprite)null); } internal static void TryRegister(ObjectDB odb) { if ((Object)(object)odb == (Object)null) { return; } SanitizeObjectDb(odb); if (CreatePrefab(odb)) { RegisterInLookups(odb); EnsureRecipe(odb); Localization instance = Localization.instance; if (instance != null) { instance.AddWord("item_vo_enchantingpouch", "Enchanting Pouch"); } Localization instance2 = Localization.instance; if (instance2 != null) { instance2.AddWord("item_vo_enchantingpouch_desc", "EpicLoot enchanting pouch. Right-click to equip/unequip. Hover it and press E to open. Use the X on the pouch panel to close it; Esc closes inventory. While equipped, ground mats auto-store here (50% weight)."); } } } private static bool CreatePrefab(ObjectDB odb) { if ((Object)(object)Prefab != (Object)null && !((object)Prefab).Equals((object?)null) && (Object)(object)odb.GetItemPrefab("VO_EnchantingPouch") == (Object)(object)Prefab) { return true; } GameObject itemPrefab = odb.GetItemPrefab("VO_EnchantingPouch"); if ((Object)(object)itemPrefab != (Object)null) { Prefab = itemPrefab; ApplyStats(Prefab.GetComponent<ItemDrop>()); PouchVisuals.ApplyWorldVisual(Prefab, odb); return true; } GameObject val = null; string[] meshPrefabCandidates = MeshPrefabCandidates; foreach (string text in meshPrefabCandidates) { val = odb.GetItemPrefab(text); if ((Object)(object)val != (Object)null) { break; } } if ((Object)(object)val == (Object)null) { if (!_loggedCloneFailure) { _loggedCloneFailure = true; Plugin.Log.LogWarning((object)"Enchanting Pouch: ObjectDB not ready to clone yet (will retry)."); } return false; } _loggedCloneFailure = false; bool activeSelf = val.activeSelf; val.SetActive(false); Prefab = Object.Instantiate<GameObject>(val); val.SetActive(activeSelf); ((Object)Prefab).name = "VO_EnchantingPouch"; Prefab.SetActive(false); Object.DontDestroyOnLoad((Object)(object)Prefab); ItemDrop component = Prefab.GetComponent<ItemDrop>(); if ((Object)(object)component == (Object)null) { Object.Destroy((Object)(object)Prefab); Prefab = null; return false; } EnsureUniqueShared(component); ApplyStats(component); PouchVisuals.ApplyWorldVisual(Prefab, odb); component.m_itemData.m_dropPrefab = Prefab; component.m_autoPickup = true; ((Object)component).name = "VO_EnchantingPouch"; Piece component2 = Prefab.GetComponent<Piece>(); if ((Object)(object)component2 != (Object)null) { Object.Destroy((Object)(object)component2); } if (!odb.m_items.Contains(Prefab)) { odb.m_items.Add(Prefab); } Plugin.Log.LogInfo((object)"Enchanting Pouch prefab registered."); return true; } private static void ApplyStats(ItemDrop drop) { //IL_003f: Unknown result type (might be due to invalid IL or missing references) if (drop?.m_itemData?.m_shared != null) { SharedData shared = drop.m_itemData.m_shared; shared.m_name = "$item_vo_enchantingpouch"; shared.m_description = "$item_vo_enchantingpouch_desc"; shared.m_itemType = (ItemType)16; shared.m_maxStackSize = 1; shared.m_weight = 0.1f; shared.m_maxQuality = 7; shared.m_useDurability = false; shared.m_teleportable = true; shared.m_questItem = false; drop.m_itemData.m_stack = 1; drop.m_itemData.m_quality = 1; drop.m_itemData.m_equipped = false; PouchVisuals.ApplyIcon(shared); } } private static void EnsureUniqueShared(ItemDrop itemDrop) { object? obj = typeof(object).GetMethod("MemberwiseClone", BindingFlags.Instance | BindingFlags.NonPublic)?.Invoke(itemDrop.m_itemData.m_shared, null); SharedData val = (SharedData)((obj is SharedData) ? obj : null); if (val != null) { itemDrop.m_itemData.m_shared = val; } } private static void RegisterInLookups(ObjectDB odb) { if (!((Object)(object)Prefab == (Object)null)) { int stableHashCode = StringExtensionMethods.GetStableHashCode("VO_EnchantingPouch"); if (odb.m_itemByHash != null) { odb.m_itemByHash[stableHashCode] = Prefab; } ItemDrop component = Prefab.GetComponent<ItemDrop>(); if (component?.m_itemData?.m_shared != null && odb.m_itemByData != null) { odb.m_itemByData[component.m_itemData.m_shared] = Prefab; } } } private static void EnsureRecipe(ObjectDB odb) { GameObject prefab = Prefab; ItemDrop val = ((prefab != null) ? prefab.GetComponent<ItemDrop>() : null); if ((Object)(object)val == (Object)null) { return; } string text = "Recipe_VO_EnchantingPouch"; Recipe val2 = Recipe; if ((Object)(object)val2 == (Object)null) { foreach (Recipe recipe in odb.m_recipes) { if ((Object)(object)recipe != (Object)null && ((Object)recipe).name == text) { val2 = recipe; break; } } } if ((Object)(object)val2 == (Object)null) { val2 = ScriptableObject.CreateInstance<Recipe>(); ((Object)val2).name = text; } val2.m_item = val; val2.m_amount = 1; val2.m_enabled = true; val2.m_craftingStation = FindWorkbench(odb); val2.m_minStationLevel = 1; val2.m_resources = PouchProgression.GetCraftRequirements(); if (!odb.m_recipes.Contains(val2)) { odb.m_recipes.Add(val2); } Recipe = val2; } private static CraftingStation FindWorkbench(ObjectDB odb) { foreach (Recipe recipe in odb.m_recipes) { if ((Object)(object)recipe?.m_craftingStation != (Object)null && recipe.m_craftingStation.m_name.IndexOf("workbench", StringComparison.OrdinalIgnoreCase) >= 0) { return recipe.m_craftingStation; } } GameObject val = (((Object)(object)ZNetScene.instance != (Object)null) ? ZNetScene.instance.GetPrefab("piece_workbench") : null); if (!((Object)(object)val != (Object)null)) { return null; } return val.GetComponent<CraftingStation>(); } private static void SanitizeObjectDb(ObjectDB odb) { if (odb?.m_items != null) { odb.m_items.RemoveAll((GameObject x) => (Object)(object)x == (Object)null); } } internal static void UnlockKnownRecipe(Player player) { if (player?.m_knownRecipes != null && !player.m_knownRecipes.Contains("$item_vo_enchantingpouch")) { player.m_knownRecipes.Add("$item_vo_enchantingpouch"); } } internal static void EnsureAvailable(Player player, List<Recipe> available) { if ((Object)(object)player == (Object)null || available == null || (Object)(object)Recipe == (Object)null) { return; } UnlockKnownRecipe(player); if ((Object)(object)Recipe.m_craftingStation == (Object)null && (Object)(object)ObjectDB.instance != (Object)null) { EnsureRecipe(ObjectDB.instance); } for (int i = 0; i < available.Count; i++) { if ((Object)(object)available[i] == (Object)(object)Recipe) { return; } } available.Add(Recipe); } } [HarmonyPatch(typeof(ObjectDB), "Awake")] internal static class ObjectDB_Awake_Patch { private static void Postfix(ObjectDB __instance) { PouchItem.TryRegister(__instance); } } [HarmonyPatch(typeof(ObjectDB), "CopyOtherDB")] internal static class ObjectDB_CopyOtherDB_Patch { private static void Postfix(ObjectDB __instance) { PouchItem.TryRegister(__instance); } } [HarmonyPatch(typeof(ZNetScene), "Awake")] internal static class ZNetScene_Awake_Patch { private static void Postfix(ZNetScene __instance) { if ((Object)(object)ObjectDB.instance != (Object)null) { PouchItem.TryRegister(ObjectDB.instance); } if ((Object)(object)PouchItem.Prefab != (Object)null && !__instance.m_namedPrefabs.ContainsKey(StringExtensionMethods.GetStableHashCode("VO_EnchantingPouch"))) { __instance.m_prefabs.Add(PouchItem.Prefab); __instance.m_namedPrefabs[StringExtensionMethods.GetStableHashCode("VO_EnchantingPouch")] = PouchItem.Prefab; } } } [HarmonyPatch(typeof(Inventory), "Save")] internal static class Inventory_Save_Patch { private static void Prefix(Inventory __instance) { PouchItem.FixDropPrefabs(__instance); } } [HarmonyPatch(typeof(Inventory), "Load")] internal static class Inventory_Load_Patch { private static void Prefix() { if ((Object)(object)ObjectDB.instance != (Object)null) { PouchItem.TryRegister(ObjectDB.instance); } } private static void Postfix(Inventory __instance) { PouchItem.FixDropPrefabs(__instance); } } internal static class PouchProgression { internal const int MaxQuality = 7; internal const float WeightFactor = 0.5f; internal static Vector2i GetSize(int quality) { //IL_000b: Unknown result type (might be due to invalid IL or missing references) return new Vector2i(Mathf.Clamp(quality, 1, 7) + 1, 4); } internal static Requirement[] GetCraftRequirements() { return Build(("DustMagic", 5), ("ReagentMagic", 5), ("EssenceMagic", 5), ("ShardMagic", 1)); } internal static Requirement[] GetRequirementsForQualityLevel(int qualityLevel) { if (qualityLevel <= 1) { return GetCraftRequirements(); } return Mathf.Clamp(qualityLevel, 2, 7) switch { 2 => Build(("DustRare", 5), ("ReagentRare", 5), ("EssenceRare", 5), ("ShardRare", 1)), 3 => Build(("DustRare", 10), ("ReagentRare", 10), ("ShardRare", 5), ("RunestoneRare", 1)), 4 => Build(("DustEpic", 5), ("ReagentEpic", 5), ("EssenceEpic", 5), ("ShardEpic", 1)), 5 => Build(("DustEpic", 10), ("ReagentEpic", 10), ("ShardEpic", 5), ("RunestoneEpic", 1)), 6 => Build(("DustLegendary", 10), ("ReagentLegendary", 10), ("ShardLegendary", 5), ("RunestoneLegendary", 1)), _ => Build(("DustMythic", 10), ("ReagentMythic", 10), ("ShardMythic", 5), ("RunestoneMythic", 1)), }; } internal static void SyncRecipeResources(int qualityLevel) { if (!((Object)(object)PouchItem.Recipe == (Object)null)) { PouchItem.Recipe.m_resources = GetRequirementsForQualityLevel(qualityLevel); PouchItem.Recipe.m_minStationLevel = 1; } } private static Requirement[] Build(params (string prefab, int amount)[] entries) { //IL_007d: 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_008a: Unknown result type (might be due to invalid IL or missing references) //IL_0092: Unknown result type (might be due to invalid IL or missing references) //IL_0099: Unknown result type (might be due to invalid IL or missing references) //IL_00a5: Expected O, but got Unknown List<Requirement> list = new List<Requirement>(entries.Length); ObjectDB instance = ObjectDB.instance; for (int i = 0; i < entries.Length; i++) { (string prefab, int amount) tuple = entries[i]; string item = tuple.prefab; int item2 = tuple.amount; GameObject val = (((Object)(object)instance != (Object)null) ? instance.GetItemPrefab(item) : null); ItemDrop val2 = (((Object)(object)val != (Object)null) ? val.GetComponent<ItemDrop>() : null); if ((Object)(object)val2 == (Object)null) { Plugin.Log.LogWarning((object)("Missing upgrade/craft ingredient prefab: " + item)); continue; } list.Add(new Requirement { m_resItem = val2, m_amount = item2, m_amountPerLevel = 0, m_recover = true }); } return list.ToArray(); } internal static bool IsPouchRequirement(Requirement requirement) { if (requirement == null || PouchItem.Recipe?.m_resources == null) { return false; } Requirement[] resources = PouchItem.Recipe.m_resources; for (int i = 0; i < resources.Length; i++) { if (resources[i] == requirement) { return true; } } return false; } } internal static class PouchVisuals { private static Sprite _icon; private static MethodInfo _loadImage; private static readonly Color MagicBlue = new Color(0.25f, 0.55f, 1f, 1f); private static readonly string[] PreferredDonors = new string[5] { "DustMagic", "EssenceMagic", "ShardMagic", "ReagentMagic", "RunestoneMagic" }; private static readonly string[] FallbackMeshDonors = new string[5] { "Softtissue", "GreydwarfEye", "SurtlingCore", "CrystalFrag", "Ruby" }; internal static void ApplyIcon(SharedData shared) { Sprite icon = GetIcon(); if (shared != null && !((Object)(object)icon == (Object)null)) { shared.m_icons = (Sprite[])(object)new Sprite[1] { icon }; } } internal static void ApplyWorldVisual(GameObject pouch, ObjectDB odb) { if ((Object)(object)pouch == (Object)null) { return; } Transform val = pouch.transform.Find("VO_PouchGlow"); if ((Object)(object)val != (Object)null) { Object.Destroy((Object)(object)((Component)val).gameObject); } Renderer[] componentsInChildren = pouch.GetComponentsInChildren<Renderer>(true); foreach (Renderer val2 in componentsInChildren) { if ((Object)(object)val2 != (Object)null) { val2.enabled = false; } } GameObject val3 = FindDonor(odb); GameObject val4 = (((Object)(object)val3 != (Object)null) ? CloneDonorVisual(val3, pouch.transform) : null); if ((Object)(object)val4 == (Object)null) { val4 = CreateFallbackOrb(pouch.transform, odb); } if ((Object)(object)val4 != (Object)null) { EnsureBlueLight(val4); } } private static GameObject FindDonor(ObjectDB odb) { if (odb?.m_items == null) { return null; } string[] preferredDonors = PreferredDonors; foreach (string text in preferredDonors) { GameObject itemPrefab = odb.GetItemPrefab(text); if ((Object)(object)itemPrefab != (Object)null) { return itemPrefab; } } foreach (GameObject item in odb.m_items) { if (!((Object)(object)item == (Object)null)) { string prefabName = Utils.GetPrefabName(item); if (prefabName.IndexOf("_Unidentified", StringComparison.OrdinalIgnoreCase) >= 0 || prefabName.IndexOf("Unidentified", StringComparison.OrdinalIgnoreCase) >= 0) { return item; } } } preferredDonors = FallbackMeshDonors; foreach (string text2 in preferredDonors) { GameObject itemPrefab2 = odb.GetItemPrefab(text2); if ((Object)(object)itemPrefab2 != (Object)null) { return itemPrefab2; } } return null; } private static GameObject CloneDonorVisual(GameObject donor, Transform parent) { //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_004e: Unknown result type (might be due to invalid IL or missing references) //IL_0067: Unknown result type (might be due to invalid IL or missing references) //IL_00c6: Unknown result type (might be due to invalid IL or missing references) //IL_00d2: Unknown result type (might be due to invalid IL or missing references) //IL_00de: Unknown result type (might be due to invalid IL or missing references) //IL_00a9: Unknown result type (might be due to invalid IL or missing references) //IL_009b: Unknown result type (might be due to invalid IL or missing references) //IL_00a0: Unknown result type (might be due to invalid IL or missing references) //IL_010d: Unknown result type (might be due to invalid IL or missing references) //IL_0114: Unknown result type (might be due to invalid IL or missing references) bool activeSelf = donor.activeSelf; donor.SetActive(false); GameObject val = Object.Instantiate<GameObject>(donor, parent); donor.SetActive(activeSelf); ((Object)val).name = "VO_PouchGlow"; val.transform.localPosition = Vector3.zero; val.transform.localRotation = Quaternion.identity; val.transform.localScale = Vector3.one; val.SetActive(false); StripGameplayComponents(val); Bounds val2 = default(Bounds); bool flag = false; Renderer[] componentsInChildren = val.GetComponentsInChildren<Renderer>(true); foreach (Renderer val3 in componentsInChildren) { if (!((Object)(object)val3 == (Object)null)) { val3.enabled = true; if (!flag) { val2 = val3.bounds; flag = true; } else { ((Bounds)(ref val2)).Encapsulate(val3.bounds); } } } if (flag) { float num = Mathf.Max(((Bounds)(ref val2)).size.x, Mathf.Max(((Bounds)(ref val2)).size.y, ((Bounds)(ref val2)).size.z)); if (num > 0.6f) { float num2 = 0.35f / num; val.transform.localScale = Vector3.one * num2; } } TintRenderersBlue(val); val.SetActive(true); return val; } private static void StripGameplayComponents(GameObject root) { DestroyAllOfType(root, "ZNetView"); DestroyAllOfType(root, "ZSyncTransform"); DestroyAllOfType(root, "ItemDrop"); DestroyAllOfType(root, "Rigidbody"); DestroyAllOfType(root, "Floating"); DestroyAllOfType(root, "WearNTear"); DestroyAllOfType(root, "Piece"); DestroyAllOfType(root, "CraftingStation"); DestroyAllOfType(root, "Container"); DestroyAllOfType(root, "Character"); DestroyAllOfType(root, "Humanoid"); DestroyAllOfType(root, "MonsterAI"); DestroyAllOfType(root, "AnimalAI"); Collider[] componentsInChildren = root.GetComponentsInChildren<Collider>(true); for (int i = 0; i < componentsInChildren.Length; i++) { Object.DestroyImmediate((Object)(object)componentsInChildren[i]); } } private static void DestroyAllOfType(GameObject root, string typeName) { Component[] componentsInChildren = root.GetComponentsInChildren<Component>(true); foreach (Component val in componentsInChildren) { if ((Object)(object)val != (Object)null && ((object)val).GetType().Name == typeName) { Object.DestroyImmediate((Object)(object)val); } } } private static GameObject CreateFallbackOrb(Transform parent, ObjectDB odb) { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Expected O, but got Unknown //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Unknown result type (might be due to invalid IL or missing references) //IL_00c7: Unknown result type (might be due to invalid IL or missing references) //IL_00ce: Expected O, but got Unknown //IL_0148: Unknown result type (might be due to invalid IL or missing references) GameObject val = new GameObject("VO_PouchGlow"); val.transform.SetParent(parent, false); val.transform.localPosition = new Vector3(0f, 0.05f, 0f); val.transform.localScale = Vector3.one * 0.18f; GameObject val2 = null; string[] fallbackMeshDonors = FallbackMeshDonors; foreach (string text in fallbackMeshDonors) { val2 = (((Object)(object)odb != (Object)null) ? odb.GetItemPrefab(text) : null); if ((Object)(object)val2 != (Object)null) { break; } } if ((Object)(object)val2 != (Object)null) { MeshFilter componentInChildren = val2.GetComponentInChildren<MeshFilter>(true); MeshRenderer componentInChildren2 = val2.GetComponentInChildren<MeshRenderer>(true); if ((Object)(object)componentInChildren != (Object)null && (Object)(object)componentInChildren2 != (Object)null) { GameObject val3 = new GameObject("Mesh"); val3.transform.SetParent(val.transform, false); val3.AddComponent<MeshFilter>().sharedMesh = componentInChildren.sharedMesh; MeshRenderer val4 = val3.AddComponent<MeshRenderer>(); if (((Renderer)componentInChildren2).sharedMaterials != null && ((Renderer)componentInChildren2).sharedMaterials.Length != 0) { Material[] array = (Material[])(object)new Material[((Renderer)componentInChildren2).sharedMaterials.Length]; for (int j = 0; j < array.Length; j++) { array[j] = (((Object)(object)((Renderer)componentInChildren2).sharedMaterials[j] != (Object)null) ? new Material(((Renderer)componentInChildren2).sharedMaterials[j]) : ((Material)null)); } ((Renderer)val4).sharedMaterials = array; } TintRenderersBlue(val3); return val; } } GameObject obj = GameObject.CreatePrimitive((PrimitiveType)0); ((Object)obj).name = "Orb"; obj.transform.SetParent(val.transform, false); Object.DestroyImmediate((Object)(object)obj.GetComponent<Collider>()); TintRenderersBlue(obj); return val; } private static void TintRenderersBlue(GameObject root) { //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Unknown result type (might be due to invalid IL or missing references) //IL_005c: Unknown result type (might be due to invalid IL or missing references) //IL_0087: Unknown result type (might be due to invalid IL or missing references) //IL_0091: Unknown result type (might be due to invalid IL or missing references) Renderer[] componentsInChildren = root.GetComponentsInChildren<Renderer>(true); foreach (Renderer val in componentsInChildren) { if ((Object)(object)val == (Object)null) { continue; } Material[] materials = val.materials; foreach (Material val2 in materials) { if (!((Object)(object)val2 == (Object)null)) { if (val2.HasProperty("_Color")) { val2.color = Color.Lerp(val2.color, MagicBlue, 0.55f); } if (val2.HasProperty("_EmissionColor")) { val2.EnableKeyword("_EMISSION"); val2.SetColor("_EmissionColor", MagicBlue * 1.4f); } } } val.materials = materials; } } private static void EnsureBlueLight(GameObject glowRoot) { //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Unknown result type (might be due to invalid IL or missing references) Light val = glowRoot.GetComponentInChildren<Light>(true); if ((Object)(object)val == (Object)null) { GameObject val2 = new GameObject("MagicLight"); val2.transform.SetParent(glowRoot.transform, false); val = val2.AddComponent<Light>(); } val.type = (LightType)2; val.color = MagicBlue; val.range = 2.5f; val.intensity = 1.35f; val.shadows = (LightShadows)0; ((Behaviour)val).enabled = true; } internal static Sprite GetIcon() { //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Expected O, but got Unknown //IL_0087: Unknown result type (might be due to invalid IL or missing references) //IL_0096: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_icon != (Object)null) { return _icon; } byte[] array = LoadEmbeddedPng(); if (array == null || array.Length == 0) { Plugin.Log.LogWarning((object)"Enchanting Pouch icon resource missing."); return null; } Texture2D val = new Texture2D(2, 2, (TextureFormat)4, false); if (!TryLoadImage(val, array)) { Plugin.Log.LogWarning((object)"Failed to LoadImage Enchanting Pouch icon."); return null; } ((Texture)val).wrapMode = (TextureWrapMode)1; ((Texture)val).filterMode = (FilterMode)1; ((Object)val).name = "VO_EnchantingPouch_Icon"; _icon = Sprite.Create(val, new Rect(0f, 0f, (float)((Texture)val).width, (float)((Texture)val).height), new Vector2(0.5f, 0.5f), 100f); ((Object)_icon).name = "VO_EnchantingPouch_Icon"; return _icon; } private static bool TryLoadImage(Texture2D tex, byte[] bytes) { if (_loadImage == null) { Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies(); for (int i = 0; i < assemblies.Length; i++) { Type type = assemblies[i].GetType("UnityEngine.ImageConversion"); if (!(type == null)) { _loadImage = type.GetMethod("LoadImage", BindingFlags.Static | BindingFlags.Public, null, new Type[2] { typeof(Texture2D), typeof(byte[]) }, null); if (_loadImage != null) { break; } } } } if (_loadImage == null) { return false; } object obj = _loadImage.Invoke(null, new object[2] { tex, bytes }); bool flag = default(bool); int num; if (obj is bool) { flag = (bool)obj; num = 1; } else { num = 0; } return (byte)((uint)num & (flag ? 1u : 0u)) != 0; } private static byte[] LoadEmbeddedPng() { Assembly assembly = typeof(PouchVisuals).Assembly; string text = null; string[] manifestResourceNames = assembly.GetManifestResourceNames(); foreach (string text2 in manifestResourceNames) { if (text2.EndsWith("enchanting_pouch_icon.png", StringComparison.OrdinalIgnoreCase)) { text = text2; break; } } if (text == null) { return null; } using Stream stream = assembly.GetManifestResourceStream(text); if (stream == null) { return null; } using MemoryStream memoryStream = new MemoryStream(); stream.CopyTo(memoryStream); return memoryStream.ToArray(); } } internal static class ProgressionPatches { [HarmonyPatch(typeof(InventoryGui), "UpdateCraftingPanel")] private static class InventoryGui_UpdateCraftingPanel_Patch { private static void Prefix(InventoryGui __instance) { SyncFromGui(__instance); } } [HarmonyPatch(typeof(InventoryGui), "SetupRequirementList")] private static class InventoryGui_SetupRequirementList_Patch { private static void Prefix(InventoryGui __instance) { SyncFromGui(__instance); } } [HarmonyPatch(typeof(Player), "HaveRequirementItems")] private static class Player_HaveRequirementItems_Patch { private static bool Prefix(Player __instance, Recipe piece, bool discover, int qualityLevel, int amount, ref bool __result) { if ((Object)(object)piece == (Object)null || (Object)(object)piece != (Object)(object)PouchItem.Recipe) { return true; } Requirement[] requirementsForQualityLevel = PouchProgression.GetRequirementsForQualityLevel(qualityLevel); PouchItem.Recipe.m_resources = requirementsForQualityLevel; __result = HaveAll(__instance, requirementsForQualityLevel, discover, amount); return false; } } [HarmonyPatch(typeof(Player), "ConsumeResources")] private static class Player_ConsumeResources_Patch { private static bool Prefix(Player __instance, Requirement[] requirements, int qualityLevel, int itemQuality, int multiplier) { if ((Object)(object)PouchItem.Recipe == (Object)null || requirements == null) { return true; } if (!IsLikelyPouchRequirementList(requirements)) { return true; } Requirement[] requirementsForQualityLevel = PouchProgression.GetRequirementsForQualityLevel(qualityLevel); ConsumeAll(__instance, requirementsForQualityLevel, Mathf.Max(1, multiplier)); return false; } } private static readonly FieldInfo SelectedRecipeField = AccessTools.Field(typeof(InventoryGui), "m_selectedRecipe") ?? AccessTools.Field(typeof(InventoryGui), "m_craftRecipe"); private static readonly FieldInfo CraftUpgradeItemField = AccessTools.Field(typeof(InventoryGui), "m_craftUpgradeItem") ?? AccessTools.Field(typeof(InventoryGui), "craftUpgradeItem"); private static void SyncFromGui(InventoryGui gui) { if (!((Object)(object)gui == (Object)null) && !((Object)(object)PouchItem.Recipe == (Object)null) && (!((Object)/*isinst with value type is only supported in some contexts*/ != (Object)(object)PouchItem.Recipe) || IsOurRecipeSelected(gui))) { object? obj = CraftUpgradeItemField?.GetValue(gui); ItemData val = (ItemData)((obj is ItemData) ? obj : null); int qualityLevel = 1; if (val != null && PouchItem.IsPouch(val)) { qualityLevel = val.m_quality + 1; } PouchProgression.SyncRecipeResources(qualityLevel); } } private static bool IsOurRecipeSelected(InventoryGui gui) { if (SelectedRecipeField == null) { return false; } object value = SelectedRecipeField.GetValue(gui); if (value == null) { return false; } Recipe val = (Recipe)((value is Recipe) ? value : null); if (val != null) { return (Object)(object)val == (Object)(object)PouchItem.Recipe; } object? obj = value.GetType().GetProperty("Key")?.GetValue(value); Recipe val2 = (Recipe)((obj is Recipe) ? obj : null); if (val2 != null) { return (Object)(object)val2 == (Object)(object)PouchItem.Recipe; } object? obj2 = (value.GetType().GetField("m_recipe") ?? value.GetType().GetField("Recipe"))?.GetValue(value); Recipe val3 = (Recipe)((obj2 is Recipe) ? obj2 : null); if (val3 != null) { return (Object)(object)val3 == (Object)(object)PouchItem.Recipe; } return false; } private static bool IsLikelyPouchRequirementList(Requirement[] requirements) { if (requirements.Length == 0) { return false; } for (int i = 0; i < requirements.Length; i++) { ItemDrop val = requirements[i]?.m_resItem; string text = (((Object)(object)val != (Object)null) ? ((Object)val).name : null); if (!string.IsNullOrEmpty(text) && (text.StartsWith("Dust") || text.StartsWith("Essence") || text.StartsWith("Reagent") || text.StartsWith("Shard") || text.StartsWith("Runestone"))) { return true; } } return false; } private static bool HaveAll(Player player, Requirement[] reqs, bool discover, int amountMul) { if (reqs == null || reqs.Length == 0) { return false; } int num = Mathf.Max(1, amountMul); Inventory inventory = ((Humanoid)player).GetInventory(); bool result = false; foreach (Requirement val in reqs) { if (!((Object)(object)val?.m_resItem == (Object)null) && val.m_amount > 0) { result = true; int num2 = val.m_amount * num; int num3 = inventory.CountItems(val.m_resItem.m_itemData.m_shared.m_name, -1, true); if (discover) { player.AddKnownItem(val.m_resItem.m_itemData); } if (num3 < num2) { return false; } } } return result; } private static void ConsumeAll(Player player, Requirement[] reqs, int multiplier) { Inventory inventory = ((Humanoid)player).GetInventory(); foreach (Requirement val in reqs) { if (!((Object)(object)val?.m_resItem == (Object)null) && val.m_amount > 0) { inventory.RemoveItem(val.m_resItem.m_itemData.m_shared.m_name, val.m_amount * multiplier, -1, true); } } } } [HarmonyPatch(typeof(Inventory), "GetTotalWeight")] internal static class Inventory_GetTotalWeight_Patch { private static void Postfix(Inventory __instance, ref float __result) { Player localPlayer = Player.m_localPlayer; if ((Object)(object)localPlayer == (Object)null || __instance != ((Humanoid)localPlayer).GetInventory()) { return; } List<ItemData> allItems = __instance.GetAllItems(); for (int i = 0; i < allItems.Count; i++) { ItemData val = allItems[i]; if (PouchItem.IsPouch(val)) { __result += PouchContainer.GetCachedContentsWeight(val); } } } } [HarmonyPatch(typeof(Requirement), "GetAmount")] internal static class Piece_Requirement_GetAmount_Patch { private static void Postfix(Requirement __instance, int qualityLevel, ref int __result) { if (PouchProgression.IsPouchRequirement(__instance)) { __result = Mathf.Max(0, __instance.m_amount); } } } [HarmonyPatch(typeof(Recipe), "GetRequiredStationLevel")] internal static class Recipe_GetRequiredStationLevel_Patch { private static void Postfix(Recipe __instance, int quality, ref int __result) { if ((Object)(object)__instance == (Object)(object)PouchItem.Recipe) { __result = 1; } } } } namespace System.Runtime.CompilerServices { [AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)] internal sealed class IgnoresAccessChecksToAttribute : Attribute { public IgnoresAccessChecksToAttribute(string assemblyName) { } } }