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 OdinStorage v0.9.1
OdinStorage.dll
Decompiled 2 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.Linq; 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 Jotunn.Configs; using Jotunn.Entities; using Jotunn.Managers; using Jotunn.Utils; using Microsoft.CodeAnalysis; using MultiUserChest; using UnityEngine; using UnityEngine.EventSystems; using UnityEngine.Events; using UnityEngine.Rendering; using UnityEngine.UI; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: IgnoresAccessChecksTo("assembly_valheim")] [assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")] [assembly: AssemblyCompany("OdinStorage")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("0.9.1.0")] [assembly: AssemblyInformationalVersion("0.9.1+edc40185618c27011aa3f32a774c917b660673b2")] [assembly: AssemblyProduct("OdinStorage")] [assembly: AssemblyTitle("OdinStorage")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("0.9.1.0")] [module: UnverifiableCode] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)] internal sealed class NullableAttribute : Attribute { public readonly byte[] NullableFlags; public NullableAttribute(byte P_0) { NullableFlags = new byte[1] { P_0 }; } public NullableAttribute(byte[] P_0) { NullableFlags = P_0; } } [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] internal sealed class NullableContextAttribute : Attribute { public readonly byte Flag; public NullableContextAttribute(byte P_0) { Flag = P_0; } } [CompilerGenerated] [Microsoft.CodeAnalysis.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 OdinStorage { public static class DevTools { private static readonly (string Prefab, int Amount)[] Loadout = new(string, int)[29] { ("Silver", 500), ("Obsidian", 200), ("Crystal", 100), ("FreezeGland", 100), ("WolfPelt", 200), ("WolfFang", 100), ("TrophyWolf", 20), ("Iron", 300), ("Bronze", 200), ("DragonTear", 50), ("DragonEgg", 3), ("ArrowFrost", 200), ("ArrowObsidian", 200), ("ArrowNeedle", 200), ("WolfMeatSkewer", 40), ("SerpentStew", 30), ("Eyescream", 40), ("Cloudberry", 100), ("Blueberries", 100), ("Onion", 80), ("MeadFrostResist", 30), ("MeadHealthMedium", 30), ("MeadStaminaMedium", 30), ("DustEpic", 500), ("EssenceEpic", 500), ("ReagentEpic", 500), ("ShardEpic", 999), ("RunestoneEpic", 200), ("Coins", 9999) }; private static readonly (string Prefab, string[] Effects)[] MagicGear = new(string, string[])[7] { ("AxeIron", new string[6] { "Executioner", "LifeSteal", "ChainLightning", "ModifyPhysicalDamage", "ModifyStaggerDamage", "ModifyAttackSpeed" }), ("BowDraugrFang", new string[6] { "Executioner", "TripleBowShot", "ChainLightning", "ModifyPhysicalDamage", "LifeSteal", "ExplosiveArrows" }), ("ShieldSerpentscale", new string[6] { "ModifyBlockPower", "ModifyBlockForce", "ModifyParry", "ModifyParryWindow", "Immovable", "AvoidDamageTaken" }), ("ArmorWolfChest", new string[6] { "ModifyArmor", "BulkUp", "IncreaseHealth", "ReflectDamage", "AvoidDamageTaken", "AddPhysicalResistancePercentage" }), ("ArmorWolfLegs", new string[6] { "ModifyArmor", "BulkUp", "ModifyMovementSpeed", "ModifySprintStaminaUse", "ModifyDodgeStaminaUse", "DoubleJump" }), ("HelmetDrake", new string[6] { "ModifyArmor", "ModifyHealthRegen", "AddElementalResistancePercentage", "AddPhysicalResistancePercentage", "QuickLearner", "ModifyDiscoveryRadius" }), ("CapeWolf", new string[6] { "ModifyArmor", "AddCarryWeight", "IncreaseHealth", "ModifyHealthRegen", "ModifyEitrRegen", "AddElementalResistancePercentage" }) }; private static readonly Vector2i AutoSlot = new Vector2i(-1, -1); private static readonly List<GameObject> Spawned = new List<GameObject>(); public static void SpawnTestStorage() { //IL_005b: Unknown result type (might be due to invalid IL or missing references) //IL_0060: Unknown result type (might be due to invalid IL or missing references) //IL_0084: Unknown result type (might be due to invalid IL or missing references) //IL_007b: Unknown result type (might be due to invalid IL or missing references) //IL_0089: 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_008f: Unknown result type (might be due to invalid IL or missing references) //IL_0090: 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_0099: 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) //IL_00a0: Unknown result type (might be due to invalid IL or missing references) //IL_00a5: Unknown result type (might be due to invalid IL or missing references) //IL_00ab: Unknown result type (might be due to invalid IL or missing references) //IL_00b0: Unknown result type (might be due to invalid IL or missing references) //IL_00b5: Unknown result type (might be due to invalid IL or missing references) //IL_00b7: Unknown result type (might be due to invalid IL or missing references) //IL_00b8: Unknown result type (might be due to invalid IL or missing references) //IL_00bd: Unknown result type (might be due to invalid IL or missing references) //IL_00d6: Unknown result type (might be due to invalid IL or missing references) //IL_00d8: Unknown result type (might be due to invalid IL or missing references) //IL_00e2: 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_00ec: Unknown result type (might be due to invalid IL or missing references) //IL_00fd: Unknown result type (might be due to invalid IL or missing references) //IL_0102: Unknown result type (might be due to invalid IL or missing references) //IL_0107: Unknown result type (might be due to invalid IL or missing references) //IL_010a: Unknown result type (might be due to invalid IL or missing references) //IL_010c: Unknown result type (might be due to invalid IL or missing references) Player localPlayer = Player.m_localPlayer; if ((Object)(object)localPlayer == (Object)null) { return; } ZNetScene instance = ZNetScene.instance; if ((Object)(object)instance == (Object)null) { Plugin.Log.LogWarning((object)"Dev: ZNetScene not ready yet."); return; } GameObject prefab = instance.GetPrefab("piece_chest_wood"); if ((Object)(object)prefab == (Object)null) { Plugin.Log.LogWarning((object)"Dev: prefab 'piece_chest_wood' not found."); return; } Transform transform = ((Component)localPlayer).transform; Vector3 val = transform.forward; val.y = 0f; val = ((((Vector3)(ref val)).sqrMagnitude > 0.001f) ? ((Vector3)(ref val)).normalized : Vector3.forward); Vector3 val2 = Vector3.Cross(Vector3.up, val); Vector3 normalized = ((Vector3)(ref val2)).normalized; Vector3 val3 = transform.position + val * 2f; Quaternion val4 = Quaternion.LookRotation(val); List<Container> list = new List<Container>(); int num = 0; for (int i = 0; i < 8; i++) { for (int j = 0; j < 2; j++) { Vector3 val5 = val3 + val * ((float)i * 1.2f) + normalized * (((float)j - 0.5f) * 1.2f); GameObject val6 = Object.Instantiate<GameObject>(prefab, val5, val4); Spawned.Add(val6); Container component = val6.GetComponent<Container>(); if ((Object)(object)component != (Object)null) { list.Add(component); } num++; } } int num2 = FillLoadout(list); int num3 = FillMagicGear(list); Plugin.Log.LogInfo((object)$"Dev: spawned {num} chests, filled with {num2} loadout item types, {num3} test gear pieces"); } private static int FillLoadout(List<Container> containers) { if ((Object)(object)ObjectDB.instance == (Object)null || containers.Count == 0) { return 0; } int num = 0; int num2 = 0; (string, int)[] loadout = Loadout; for (int i = 0; i < loadout.Length; i++) { (string, int) tuple = loadout[i]; string item = tuple.Item1; int item2 = tuple.Item2; GameObject itemPrefab = ObjectDB.instance.GetItemPrefab(item); ItemDrop val = (((Object)(object)itemPrefab != (Object)null) ? itemPrefab.GetComponent<ItemDrop>() : null); if ((Object)(object)val == (Object)null) { continue; } int num3 = Mathf.Max(1, item2); int maxStack = Mathf.Max(1, val.m_itemData.m_shared.m_maxStackSize); bool flag = false; while (num3 > 0 && num < containers.Count) { Inventory val2 = (((Object)(object)containers[num] != (Object)null) ? containers[num].GetInventory() : null); int num4 = ((val2 != null) ? FitAmount(val2, val, maxStack, num3) : 0); if (num4 <= 0) { num++; continue; } val2.AddItem(itemPrefab, num4); num3 -= num4; flag = true; } if (flag) { num2++; } if (num3 > 0) { Plugin.Log.LogWarning((object)$"Dev: ran out of chest space, {num3} of {item} not placed."); } } return num2; } private static int FitAmount(Inventory inv, ItemDrop drop, int maxStack, int want) { string name = drop.m_itemData.m_shared.m_name; List<ItemData> allItems = inv.GetAllItems(); int num = 0; foreach (ItemData item in allItems) { if (item?.m_shared != null && item.m_shared.m_name == name && item.m_stack < maxStack) { num += maxStack - item.m_stack; } } int num2 = inv.GetWidth() * inv.GetHeight(); int num3 = Mathf.Max(0, num2 - allItems.Count); num += num3 * maxStack; return Mathf.Min(want, num); } private static int FillMagicGear(List<Container> containers) { //IL_019f: Unknown result type (might be due to invalid IL or missing references) //IL_01a6: Expected O, but got Unknown //IL_01b6: Unknown result type (might be due to invalid IL or missing references) //IL_01bb: Unknown result type (might be due to invalid IL or missing references) if (!EpicLootMagic.Available) { Plugin.Log.LogInfo((object)"Dev: EpicLoot not present — skipping magic test gear."); return 0; } if ((Object)(object)ObjectDB.instance == (Object)null || containers.Count == 0) { return 0; } int num = 0; List<string> list = new List<string>(); (string, string[])[] magicGear = MagicGear; for (int i = 0; i < magicGear.Length; i++) { (string, string[]) tuple = magicGear[i]; string item = tuple.Item1; string[] item2 = tuple.Item2; GameObject itemPrefab = ObjectDB.instance.GetItemPrefab(item); ItemDrop val = (((Object)(object)itemPrefab != (Object)null) ? itemPrefab.GetComponent<ItemDrop>() : null); if ((Object)(object)val == (Object)null) { Plugin.Log.LogWarning((object)("Dev: gear prefab '" + item + "' unknown in this version — skipped.")); continue; } ItemData val2 = val.m_itemData.Clone(); val2.m_stack = 1; val2.m_quality = val2.m_shared.m_maxQuality; val2.m_durability = val2.GetMaxDurability(); val2.m_crafterName = "Dev"; if (!EpicLootMagic.TryForceEffects(val2, item2, out string rarityName, out List<string> skipped)) { Plugin.Log.LogWarning((object)("Dev: could not build test gear '" + item + "', skipped.")); continue; } foreach (string item3 in skipped) { list.Add(item + ": " + item3); } bool flag = false; foreach (Container container in containers) { Inventory val3 = (((Object)(object)container != (Object)null) ? container.GetInventory() : null); if (val3 != null && val3.CanAddItem(val2, 1)) { Inventory val4 = new Inventory("dev_gear", (Sprite)null, 1, 1); val4.AddItem(val2); ContainerHandler.AddItemToChest(container, val2, val4, AutoSlot, ZDOID.None, val2.m_stack); flag = true; num++; break; } } if (flag) { int num2 = item2.Length - skipped.Count; Plugin.Log.LogInfo((object)$"Dev: placed {rarityName} test gear '{item}' ({num2}/{item2.Length} effects)."); } else { Plugin.Log.LogWarning((object)("Dev: no chest space for test gear '" + item + "'.")); } } if (list.Count > 0) { Plugin.Log.LogWarning((object)string.Format("Dev: {0} effect(s) skipped (not allowed for slot): {1}", list.Count, string.Join(", ", list))); } return num; } public static void ClearTestStorage() { ZNetScene instance = ZNetScene.instance; int num = 0; foreach (GameObject item in Spawned) { if ((Object)(object)item == (Object)null) { continue; } ZNetView component = item.GetComponent<ZNetView>(); if ((Object)(object)component != (Object)null && component.IsValid()) { component.ClaimOwnership(); if ((Object)(object)instance != (Object)null) { instance.Destroy(item); num++; continue; } } Object.Destroy((Object)(object)item); num++; } Spawned.Clear(); Plugin.Log.LogInfo((object)$"Dev: removed {num} test chests"); } } public static class EpicLootMagic { private static bool _probed; private static bool _available; private static ConstructorInfo? _magicItemCtor; private static ConstructorInfo? _effectCtor; private static FieldInfo? _rarityField; private static FieldInfo? _effectsField; private static MethodInfo? _saveMagicItem; private static MethodInfo? _getDefinition; private static MethodInfo? _getAvailableEffects; private static FieldInfo? _valuesPerRarityField; private static Type? _valuesPerRarityType; private static FieldInfo? _valueDefMaxField; private static PropertyInfo? _definitionTypeProp; private static object? _rarityMythic; private static object? _rarityLegendary; private static bool _useMythicResolved; private static bool _useMythic; public static bool Available { get { Probe(); return _available; } } private static void Probe() { if (_probed) { return; } _probed = true; try { Type type = FindType("EpicLoot.MagicItem"); Type type2 = FindType("EpicLoot.MagicItemEffect"); Type type3 = FindType("EpicLoot.ItemRarity"); Type type4 = FindType("EpicLoot.ItemDataExtensions"); Type type5 = FindType("EpicLoot.MagicItemEffectDefinition"); Type type6 = FindType("EpicLoot.MagicItemEffectDefinitions"); if (type == null || type2 == null || type3 == null || type4 == null || type5 == null || type6 == null) { Plugin.Log.LogInfo((object)"EpicLoot not detected — magic test gear disabled."); return; } _magicItemCtor = type.GetConstructor(Type.EmptyTypes); _effectCtor = type2.GetConstructor(new Type[2] { typeof(string), typeof(float) }); _rarityField = type.GetField("Rarity", BindingFlags.Instance | BindingFlags.Public); _effectsField = type.GetField("Effects", BindingFlags.Instance | BindingFlags.Public); _saveMagicItem = type4.GetMethod("SaveMagicItem", BindingFlags.Static | BindingFlags.Public, null, new Type[2] { typeof(ItemData), type }, null); _getDefinition = type6.GetMethod("Get", BindingFlags.Static | BindingFlags.Public, null, new Type[1] { typeof(string) }, null); _getAvailableEffects = type6.GetMethod("GetAvailableEffects", BindingFlags.Static | BindingFlags.Public, null, new Type[6] { typeof(ItemData), type, typeof(int), typeof(bool), typeof(bool), typeof(bool) }, null); _valuesPerRarityField = type5.GetField("ValuesPerRarity", BindingFlags.Instance | BindingFlags.Public); _valuesPerRarityType = _valuesPerRarityField?.FieldType; _valueDefMaxField = (_valuesPerRarityType?.GetField("Mythic", BindingFlags.Instance | BindingFlags.Public)?.FieldType)?.GetField("MaxValue", BindingFlags.Instance | BindingFlags.Public); _definitionTypeProp = type5.GetProperty("Type", BindingFlags.Instance | BindingFlags.Public); _rarityMythic = Enum.ToObject(type3, 4); _rarityLegendary = Enum.ToObject(type3, 3); _available = _magicItemCtor != null && _effectCtor != null && _rarityField != null && _effectsField != null && _saveMagicItem != null && _getDefinition != null && _valuesPerRarityField != null && _valuesPerRarityType != null && _valueDefMaxField != null; if (!_available) { Plugin.Log.LogWarning((object)"EpicLoot present but API shape unexpected — magic test gear disabled."); } } catch (Exception ex) { _available = false; Plugin.Log.LogWarning((object)("EpicLoot probe failed — magic test gear disabled (" + ex.Message + ").")); } } public static bool TryForceEffects(ItemData item, IList<string> effectTypes, out string rarityName, out List<string> skipped) { rarityName = string.Empty; skipped = new List<string>(); Probe(); if (!_available || item == null || effectTypes == null) { return false; } try { bool flag = UseMythic(); object value = (flag ? _rarityMythic : _rarityLegendary); rarityName = (flag ? "Mythic" : "Legendary"); object obj = _magicItemCtor.Invoke(null); _rarityField.SetValue(obj, value); IList list = (IList)_effectsField.GetValue(obj); list.Clear(); HashSet<string> allowedEffectTypes = GetAllowedEffectTypes(item, obj); foreach (string effectType in effectTypes) { if (allowedEffectTypes.Count > 0 && !allowedEffectTypes.Contains(effectType)) { Plugin.Log.LogWarning((object)("Dev: effect '" + effectType + "' not allowed for this item slot — skipped.")); skipped.Add(effectType); continue; } float num = MaxValueFor(effectType, rarityName); object value2 = _effectCtor.Invoke(new object[2] { effectType, num }); list.Add(value2); } if (list.Count == 0) { rarityName = string.Empty; return false; } _saveMagicItem.Invoke(null, new object[2] { item, obj }); return true; } catch (Exception ex) { Plugin.Log.LogWarning((object)("EpicLoot force-effects failed (" + ex.Message + ").")); rarityName = string.Empty; return false; } } private static bool UseMythic() { if (_useMythicResolved) { return _useMythic; } _useMythicResolved = true; _useMythic = false; try { FieldInfo fieldInfo = _valuesPerRarityType?.GetField("Mythic", BindingFlags.Instance | BindingFlags.Public); string[] array = new string[3] { "ModifyArmor", "ModifyDurability", "ModifyPhysicalDamage" }; foreach (string text in array) { object obj = _getDefinition.Invoke(null, new object[1] { text }); if (obj != null) { object value = _valuesPerRarityField.GetValue(obj); if (value != null) { _useMythic = fieldInfo?.GetValue(value) != null; break; } } } } catch (Exception ex) { Plugin.Log.LogInfo((object)("EpicLoot mythic probe failed, using Legendary (" + ex.Message + ").")); _useMythic = false; } return _useMythic; } private static float MaxValueFor(string effectType, string rarityName) { try { object obj = _getDefinition.Invoke(null, new object[1] { effectType }); if (obj == null) { return 0f; } object value = _valuesPerRarityField.GetValue(obj); if (value == null) { return 0f; } object obj2 = _valuesPerRarityType.GetField(rarityName, BindingFlags.Instance | BindingFlags.Public)?.GetValue(value); if (obj2 == null) { obj2 = _valuesPerRarityType.GetField("Legendary", BindingFlags.Instance | BindingFlags.Public)?.GetValue(value); if (obj2 == null) { return 0f; } } return (_valueDefMaxField.GetValue(obj2) is float num) ? num : 0f; } catch (Exception ex) { Plugin.Log.LogInfo((object)("EpicLoot value lookup for '" + effectType + "' failed (" + ex.Message + ").")); return 0f; } } private static HashSet<string> GetAllowedEffectTypes(ItemData item, object magic) { HashSet<string> hashSet = new HashSet<string>(); if (_getAvailableEffects == null || _definitionTypeProp == null) { return hashSet; } try { if (_getAvailableEffects.Invoke(null, new object[6] { item, magic, -1, true, false, false }) is IEnumerable enumerable) { foreach (object item3 in enumerable) { if (_definitionTypeProp.GetValue(item3) is string item2) { hashSet.Add(item2); } } } } catch (Exception ex) { Plugin.Log.LogInfo((object)("EpicLoot availability check unavailable (" + ex.Message + "); no slot-filter applied.")); hashSet.Clear(); } return hashSet; } private static Type? FindType(string fullName) { Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies(); for (int i = 0; i < assemblies.Length; i++) { Type type = assemblies[i].GetType(fullName, throwOnError: false); if (type != null) { return type; } } return null; } } [BepInPlugin("com.nicolai.odinstorage", "OdinStorage", "0.9.1")] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] [NetworkCompatibility(/*Could not decode attribute arguments.*/)] public class Plugin : BaseUnityPlugin { [CompilerGenerated] private sealed class <RefreshSoonCo>d__20 : IEnumerator<object>, IDisposable, IEnumerator { private int <>1__state; private object <>2__current; object IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <RefreshSoonCo>d__20(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <>1__state = -2; } private bool MoveNext() { //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Expected O, but got Unknown switch (<>1__state) { default: return false; case 0: <>1__state = -1; <>2__current = (object)new WaitForSeconds(0.2f); <>1__state = 1; return true; case 1: <>1__state = -1; StorageTerminalUI.Refresh(); return false; } } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } public const string MucGuid = "com.maxsch.valheim.MultiUserChest"; public const string QssGuid = "goldenrevolver.quick_stack_store"; public const string PluginGuid = "com.nicolai.odinstorage"; public const string PluginName = "OdinStorage"; public const string PluginVersion = "0.9.1"; private readonly Harmony _harmony = new Harmony("com.nicolai.odinstorage"); internal static ManualLogSource Log; internal static Plugin Instance; internal static ConfigEntry<KeyboardShortcut> Hotkey; internal static ConfigEntry<float> Radius; internal static ConfigEntry<bool> VerboseLogging; internal static ConfigEntry<bool> DevTools; internal static ConfigEntry<KeyboardShortcut> SpawnKey; internal static ConfigEntry<KeyboardShortcut> ClearKey; internal static ConfigEntry<bool> MarkerEnabled; internal static ConfigEntry<float> MarkerDuration; private void Awake() { //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_00b7: Unknown result type (might be due to invalid IL or missing references) //IL_00e2: Unknown result type (might be due to invalid IL or missing references) Log = ((BaseUnityPlugin)this).Logger; Instance = this; Hotkey = ((BaseUnityPlugin)this).Config.Bind<KeyboardShortcut>("General", "Hotkey", new KeyboardShortcut((KeyCode)111, Array.Empty<KeyCode>()), "Key that triggers the chest scan."); Radius = ((BaseUnityPlugin)this).Config.Bind<float>("General", "Radius", 20f, "Range in meters."); VerboseLogging = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "VerboseLogging", false, "If enabled, logs every Container.Awake (very verbose)."); DevTools = ((BaseUnityPlugin)this).Config.Bind<bool>("Dev", "DevTools", false, "Enables the developer keys (spawn/clear test chests)."); SpawnKey = ((BaseUnityPlugin)this).Config.Bind<KeyboardShortcut>("Dev", "SpawnKey", new KeyboardShortcut((KeyCode)112, Array.Empty<KeyCode>()), "Spawn and fill test chests (only when DevTools is enabled)."); ClearKey = ((BaseUnityPlugin)this).Config.Bind<KeyboardShortcut>("Dev", "ClearKey", new KeyboardShortcut((KeyCode)108, Array.Empty<KeyCode>()), "Remove spawned test chests (only when DevTools is enabled)."); MarkerEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("Marker", "MarkerEnabled", true, "\"Find item\": marks chests in the world (local visual aid)."); MarkerDuration = ((BaseUnityPlugin)this).Config.Bind<float>("Marker", "MarkerDuration", 30f, "How long the find marker stays visible after closing the terminal (seconds)."); Log.LogInfo((object)"OdinStorage 0.9.1 loaded."); PrefabManager.OnVanillaPrefabsAvailable += TerminalPiece.Register; GUIManager.OnCustomGUIAvailable += StorageTerminalUI.Create; _harmony.PatchAll(); } private void Update() { //IL_0013: 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_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_0066: Unknown result type (might be due to invalid IL or missing references) //IL_006b: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)Player.m_localPlayer == (Object)null) { return; } KeyboardShortcut value = Hotkey.Value; if (((KeyboardShortcut)(ref value)).IsDown()) { StorageScanner.Scan(); } if (StorageTerminalUI.IsOpen && Input.GetKeyDown((KeyCode)27)) { StorageTerminalUI.Close(); } if (DevTools.Value) { value = SpawnKey.Value; if (((KeyboardShortcut)(ref value)).IsDown()) { OdinStorage.DevTools.SpawnTestStorage(); } value = ClearKey.Value; if (((KeyboardShortcut)(ref value)).IsDown()) { OdinStorage.DevTools.ClearTestStorage(); } } } internal void StartCleanup(Vector3 center) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) ((MonoBehaviour)this).StartCoroutine(StorageCleanup.Run(center, Radius.Value)); } internal void RefreshSoon() { ((MonoBehaviour)this).StartCoroutine(RefreshSoonCo()); } [IteratorStateMachine(typeof(<RefreshSoonCo>d__20))] private static IEnumerator RefreshSoonCo() { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <RefreshSoonCo>d__20(0); } } public static class QssFavorites { private static bool _resolved; private static bool _available; private static MethodInfo? _getPlayerConfig; private static MethodInfo? _isFavorited; public static bool Available { get { Resolve(); return _available; } } private static void Resolve() { if (_resolved) { return; } _resolved = true; try { Type type = AppDomain.CurrentDomain.GetAssemblies().Select(delegate(Assembly a) { try { return a.GetType("QuickStackStore.UserConfig", throwOnError: false); } catch { return null; } }).FirstOrDefault((Type t) => t != null); if (type == null) { Plugin.Log.LogInfo((object)"QSS not found — favorite protection uses fallback (equipment + hotbar)."); return; } _getPlayerConfig = type.GetMethod("GetPlayerConfig", BindingFlags.Static | BindingFlags.Public, null, new Type[1] { typeof(long) }, null); _isFavorited = type.GetMethod("IsItemNameOrSlotFavorited", BindingFlags.Instance | BindingFlags.Public, null, new Type[1] { typeof(ItemData) }, null); _available = _getPlayerConfig != null && _isFavorited != null; if (_available) { Plugin.Log.LogInfo((object)"QSS detected — favorites are protected when depositing."); } else { Plugin.Log.LogWarning((object)"QSS found, but favorites API not readable — fallback active."); } } catch (Exception ex) { Plugin.Log.LogWarning((object)("QSS reflection failed (" + ex.Message + ") — fallback active.")); _available = false; } } public static object? GetLocalConfig() { Resolve(); if (!_available) { return null; } Player localPlayer = Player.m_localPlayer; if ((Object)(object)localPlayer == (Object)null) { return null; } try { return _getPlayerConfig.Invoke(null, new object[1] { localPlayer.GetPlayerID() }); } catch (Exception ex) { Plugin.Log.LogWarning((object)("QSS GetPlayerConfig failed (" + ex.Message + ").")); return null; } } public static bool IsFavorited(object? config, ItemData item) { if (config == null || _isFavorited == null || item == null) { return false; } try { return (bool)_isFavorited.Invoke(config, new object[1] { item }); } catch { return false; } } } public static class StorageCleanup { [CompilerGenerated] private sealed class <>c__DisplayClass10_0 { public string token; public Func<Container, bool> <>9__0; public Func<Container, int> <>9__1; internal bool <Run>b__0(Container c) { if (IsValid(c)) { return CountInChest(c, token) > 0; } return false; } internal int <Run>b__1(Container c) { return CountInChest(c, token); } } [CompilerGenerated] private sealed class <>c__DisplayClass10_1 { public Container source; public ItemData item; internal bool <Run>b__2(Container h) { if ((Object)(object)h != (Object)(object)source) { return CapacityFor(h, item) > 0; } return false; } internal bool <Run>b__3(Container c) { if ((Object)(object)c != (Object)(object)source && IsValid(c)) { return CapacityFor(c, item) > 0; } return false; } } [CompilerGenerated] private sealed class <>c__DisplayClass11_0 { public string token; internal bool <MoveViaTransit>b__0(ItemData i) { if (i?.m_shared != null) { return i.m_shared.m_name == token; } return false; } } [CompilerGenerated] private sealed class <>c__DisplayClass12_0 { public ItemData item; internal bool <FlushTransit>b__0(Container c) { if (IsValid(c)) { return CapacityFor(c, item) > 0; } return false; } } [CompilerGenerated] private sealed class <FlushTransit>d__12 : IEnumerator<object>, IDisposable, IEnumerator { private int <>1__state; private object <>2__current; public Inventory transit; public List<Container> chests; private List<ItemData>.Enumerator <>7__wrap1; object IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <FlushTransit>d__12(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { int num = <>1__state; if (num == -3 || num == 1) { try { } finally { <>m__Finally1(); } } <>7__wrap1 = default(List<ItemData>.Enumerator); <>1__state = -2; } private bool MoveNext() { //IL_00a6: Unknown result type (might be due to invalid IL or missing references) //IL_00ab: Unknown result type (might be due to invalid IL or missing references) try { switch (<>1__state) { default: return false; case 0: <>1__state = -1; <>7__wrap1 = transit.GetAllItems().ToList().GetEnumerator(); <>1__state = -3; break; case 1: <>1__state = -3; break; } while (<>7__wrap1.MoveNext()) { <>c__DisplayClass12_0 CS$<>8__locals0 = new <>c__DisplayClass12_0 { item = <>7__wrap1.Current }; if (CS$<>8__locals0.item?.m_shared == null) { continue; } Container val = ((IEnumerable<Container>)chests).FirstOrDefault((Func<Container, bool>)((Container c) => IsValid(c) && CapacityFor(c, CS$<>8__locals0.item) > 0)); if ((Object)(object)val != (Object)null) { try { ContainerHandler.AddItemToChest(val, CS$<>8__locals0.item, transit, AutoSlot, ZDOID.None, CS$<>8__locals0.item.m_stack); } catch (Exception ex) { Plugin.Log.LogWarning((object)("Consolidate: flush to chest failed (" + ex.Message + ").")); } <>2__current = null; <>1__state = 1; return true; } } <>m__Finally1(); <>7__wrap1 = default(List<ItemData>.Enumerator); Inventory val2 = (((Object)(object)Player.m_localPlayer != (Object)null) ? ((Humanoid)Player.m_localPlayer).GetInventory() : null); foreach (ItemData item in transit.GetAllItems().ToList()) { if (item?.m_shared != null) { Plugin.Log.LogWarning((object)$"Consolidate: {item.m_stack}x {item.m_shared.m_name} found no chest space."); if (val2 != null) { val2.AddItem(item); } } } return false; } catch { //try-fault ((IDisposable)this).Dispose(); throw; } } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } private void <>m__Finally1() { <>1__state = -1; ((IDisposable)<>7__wrap1).Dispose(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } [CompilerGenerated] private sealed class <MoveViaTransit>d__11 : IEnumerator<object>, IDisposable, IEnumerator { private int <>1__state; private object <>2__current; public string token; public Container source; public Container sink; public Inventory transit; public ItemData item; public int amt; private <>c__DisplayClass11_0 <>8__1; private int <transitBefore>5__2; private int <waited>5__3; object IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <MoveViaTransit>d__11(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <>8__1 = null; <>1__state = -2; } private bool MoveNext() { //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_0141: 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) ItemData val; switch (<>1__state) { default: return false; case 0: <>1__state = -1; <>8__1 = new <>c__DisplayClass11_0(); <>8__1.token = token; if (!IsValid(source) || !IsValid(sink)) { return false; } <transitBefore>5__2 = TotalStacks(transit); try { ContainerHandler.RemoveItemFromChest(source, item, transit, AutoSlot, ZDOID.None, amt, (ItemData)null); } catch (Exception ex) { Plugin.Log.LogWarning((object)("Consolidate: removing from chest failed (" + ex.Message + ").")); return false; } <waited>5__3 = 0; goto IL_00ef; case 1: <>1__state = -1; goto IL_00ef; case 2: { <>1__state = -1; return false; } IL_00ef: if (TotalStacks(transit) <= <transitBefore>5__2 && <waited>5__3 < 60) { <waited>5__3++; <>2__current = null; <>1__state = 1; return true; } val = ((IEnumerable<ItemData>)transit.GetAllItems()).FirstOrDefault((Func<ItemData, bool>)((ItemData i) => i?.m_shared != null && i.m_shared.m_name == <>8__1.token)); if (val == null) { return false; } try { ContainerHandler.AddItemToChest(sink, val, transit, AutoSlot, ZDOID.None, val.m_stack); _moved = true; } catch (Exception ex2) { Plugin.Log.LogWarning((object)("Consolidate: adding to chest failed (" + ex2.Message + ").")); } <>2__current = null; <>1__state = 2; 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(); } } [CompilerGenerated] private sealed class <Run>d__10 : IEnumerator<object>, IDisposable, IEnumerator { private int <>1__state; private object <>2__current; public Vector3 center; public float radius; private <>c__DisplayClass10_0 <>8__1; private List<Container> <chests>5__2; private Dictionary<string, int> <before>5__3; private Inventory <transit>5__4; private int <moves>5__5; private List<string>.Enumerator <>7__wrap5; private int <guard>5__7; object IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <Run>d__10(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { int num = <>1__state; if (num == -3 || (uint)(num - 1) <= 1u) { try { } finally { <>m__Finally1(); } } <>8__1 = null; <chests>5__2 = null; <before>5__3 = null; <transit>5__4 = null; <>7__wrap5 = default(List<string>.Enumerator); <>1__state = -2; } private bool MoveNext() { //IL_0041: Unknown result type (might be due to invalid IL or missing references) //IL_00af: Unknown result type (might be due to invalid IL or missing references) //IL_00b9: Expected O, but got Unknown try { switch (<>1__state) { default: return false; case 0: <>1__state = -1; if (_busy) { return false; } _busy = true; <chests>5__2 = StorageScanner.NearbyChests(center, radius).ToList(); if (<chests>5__2.Count < 2) { Plugin.Log.LogInfo((object)"Consolidate: fewer than two chests within range — nothing to do."); _busy = false; StorageTerminalUI.Refresh(); return false; } <before>5__3 = CountByToken(<chests>5__2); LogSlotUsage(<chests>5__2); <transit>5__4 = new Inventory("odin_cleanup_transit", (Sprite)null, 8, 6); <moves>5__5 = 0; <>7__wrap5 = <before>5__3.Keys.ToList().GetEnumerator(); <>1__state = -3; goto IL_0320; case 1: <>1__state = -3; if (_moved) { <moves>5__5++; if (<moves>5__5 % 4 == 0) { <>2__current = null; <>1__state = 2; return true; } goto IL_02ee; } goto IL_0319; case 2: <>1__state = -3; goto IL_02ee; case 3: { <>1__state = -1; Dictionary<string, int> after = CountByToken(<chests>5__2); bool flag = Verify(<before>5__3, after, <transit>5__4, <moves>5__5); _busy = false; Player localPlayer = Player.m_localPlayer; if ((Object)(object)localPlayer != (Object)null) { ((Character)localPlayer).Message((MessageType)2, flag ? $"Storage consolidated ({<moves>5__5} moves)" : "Consolidate: WARNING — item count mismatch!", 0, (Sprite)null); } StorageTerminalUI.Refresh(); return false; } IL_02ee: if (<moves>5__5 < 5000 && <guard>5__7++ < 1000) { <>c__DisplayClass10_1 CS$<>8__locals0 = new <>c__DisplayClass10_1(); List<Container> list = (from c in <chests>5__2 where IsValid(c) && CountInChest(c, <>8__1.token) > 0 orderby CountInChest(c, <>8__1.token) descending select c).ToList(); if (list.Count > 1) { CS$<>8__locals0.source = list[list.Count - 1]; CS$<>8__locals0.item = FirstItemOfToken(CS$<>8__locals0.source, <>8__1.token); if (CS$<>8__locals0.item != null) { Container val = ((IEnumerable<Container>)list).FirstOrDefault((Func<Container, bool>)((Container h) => (Object)(object)h != (Object)(object)CS$<>8__locals0.source && CapacityFor(h, CS$<>8__locals0.item) > 0)); if ((Object)(object)val == (Object)null) { val = ((IEnumerable<Container>)<chests>5__2).FirstOrDefault((Func<Container, bool>)((Container c) => (Object)(object)c != (Object)(object)CS$<>8__locals0.source && IsValid(c) && CapacityFor(c, CS$<>8__locals0.item) > 0)); } if (!((Object)(object)val == (Object)null) && !((Object)(object)val == (Object)(object)CS$<>8__locals0.source)) { int num = Mathf.Min(CS$<>8__locals0.item.m_stack, CapacityFor(val, CS$<>8__locals0.item)); if (num > 0) { _moved = false; <>2__current = MoveViaTransit(CS$<>8__locals0.source, val, <>8__1.token, CS$<>8__locals0.item, num, <transit>5__4); <>1__state = 1; return true; } } } } } goto IL_0319; IL_0320: if (<>7__wrap5.MoveNext()) { <>8__1 = new <>c__DisplayClass10_0(); <>8__1.token = <>7__wrap5.Current; <guard>5__7 = 0; goto IL_02ee; } <>m__Finally1(); <>7__wrap5 = default(List<string>.Enumerator); <>2__current = FlushTransit(<transit>5__4, <chests>5__2); <>1__state = 3; return true; IL_0319: <>8__1 = null; goto IL_0320; } } catch { //try-fault ((IDisposable)this).Dispose(); throw; } } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } private void <>m__Finally1() { <>1__state = -1; ((IDisposable)<>7__wrap5).Dispose(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } private static readonly Vector2i AutoSlot = new Vector2i(-1, -1); private const int MoveCap = 5000; private const int PerTokenGuard = 1000; private const int BatchYield = 4; private const int ArriveWaitFrames = 60; private static bool _busy; private static bool _moved; public static bool Busy => _busy; public static int EstimateMoves(Vector3 center, float radius) { //IL_000c: Unknown result type (might be due to invalid IL or missing references) Dictionary<string, int> dictionary = new Dictionary<string, int>(); Dictionary<string, int> dictionary2 = new Dictionary<string, int>(); foreach (Container item in StorageScanner.NearbyChests(center, radius)) { Inventory inventory = item.GetInventory(); List<ItemData> list = ((inventory != null) ? inventory.GetAllItems() : null); if (list == null) { continue; } Dictionary<string, int> dictionary3 = new Dictionary<string, int>(); foreach (ItemData item2 in list) { if (item2?.m_shared != null) { string name = item2.m_shared.m_name; dictionary3.TryGetValue(name, out var value); dictionary3[name] = value + item2.m_stack; dictionary.TryGetValue(name, out var value2); dictionary[name] = value2 + item2.m_stack; } } foreach (KeyValuePair<string, int> item3 in dictionary3) { dictionary2.TryGetValue(item3.Key, out var value3); if (item3.Value > value3) { dictionary2[item3.Key] = item3.Value; } } } int num = 0; foreach (KeyValuePair<string, int> item4 in dictionary) { dictionary2.TryGetValue(item4.Key, out var value4); num += item4.Value - value4; } return num; } [IteratorStateMachine(typeof(<Run>d__10))] public static IEnumerator Run(Vector3 center, float radius) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <Run>d__10(0) { center = center, radius = radius }; } [IteratorStateMachine(typeof(<MoveViaTransit>d__11))] private static IEnumerator MoveViaTransit(Container source, Container sink, string token, ItemData item, int amt, Inventory transit) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <MoveViaTransit>d__11(0) { source = source, sink = sink, token = token, item = item, amt = amt, transit = transit }; } [IteratorStateMachine(typeof(<FlushTransit>d__12))] private static IEnumerator FlushTransit(Inventory transit, List<Container> chests) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <FlushTransit>d__12(0) { transit = transit, chests = chests }; } private static bool Verify(Dictionary<string, int> before, Dictionary<string, int> after, Inventory transit, int moves) { bool flag = true; foreach (string item in before.Keys.Union(after.Keys)) { before.TryGetValue(item, out var value); after.TryGetValue(item, out var value2); if (value2 != value) { flag = false; Plugin.Log.LogError((object)$"CONSOLIDATE SAFETY NET: '{item}' before {value}, after {value2} (diff {value2 - value})!"); } } int num = TotalStacks(transit); if (num > 0) { flag = false; Plugin.Log.LogError((object)$"CONSOLIDATE SAFETY NET: {num} item(s) stuck in transit!"); } if (flag) { Plugin.Log.LogInfo((object)$"Consolidate done: {moves} moves, item counts match."); } else { Plugin.Log.LogError((object)"Consolidate: item counts differ — please check storage! (diffs above)"); } return flag; } private static bool IsValid(Container c) { if ((Object)(object)c != (Object)null && (Object)(object)c.m_nview != (Object)null) { return c.m_nview.IsValid(); } return false; } private static void LogSlotUsage(List<Container> chests) { int num = 0; int num2 = 0; foreach (Container chest in chests) { if (IsValid(chest)) { Inventory inventory = chest.GetInventory(); if (inventory != null) { int num3 = inventory.GetWidth() * inventory.GetHeight(); num += num3; num2 += num3 - inventory.GetEmptySlots(); } } } Plugin.Log.LogInfo((object)$"Storage: {num2} / {num} slots used"); } private static Dictionary<string, int> CountByToken(List<Container> chests) { Dictionary<string, int> dictionary = new Dictionary<string, int>(); foreach (Container chest in chests) { if (!IsValid(chest)) { continue; } Inventory inventory = chest.GetInventory(); List<ItemData> list = ((inventory != null) ? inventory.GetAllItems() : null); if (list == null) { continue; } foreach (ItemData item in list) { if (item?.m_shared != null) { dictionary.TryGetValue(item.m_shared.m_name, out var value); dictionary[item.m_shared.m_name] = value + item.m_stack; } } } return dictionary; } private static int CountInChest(Container chest, string token) { Inventory inventory = chest.GetInventory(); List<ItemData> list = ((inventory != null) ? inventory.GetAllItems() : null); if (list == null) { return 0; } int num = 0; foreach (ItemData item in list) { if (item?.m_shared != null && item.m_shared.m_name == token) { num += item.m_stack; } } return num; } private static ItemData? FirstItemOfToken(Container chest, string token) { string token2 = token; Inventory inventory = chest.GetInventory(); return ((inventory != null) ? inventory.GetAllItems() : null)?.FirstOrDefault((Func<ItemData, bool>)((ItemData it) => it?.m_shared != null && it.m_shared.m_name == token2 && it.m_stack > 0)); } private static bool IsMergeable(ItemData item) { if (item?.m_shared != null && item.m_shared.m_maxStackSize > 1) { if (item.m_customData != null) { return item.m_customData.Count == 0; } return true; } return false; } private static bool CanMerge(ItemData a, ItemData b) { if (IsMergeable(a) && IsMergeable(b) && a.m_shared.m_name == b.m_shared.m_name && a.m_quality == b.m_quality) { return a.m_variant == b.m_variant; } return false; } private static int CapacityFor(Container chest, ItemData sample) { Inventory inventory = chest.GetInventory(); if (inventory == null) { return 0; } int emptySlots = inventory.GetEmptySlots(); if (!IsMergeable(sample)) { return emptySlots; } int num = Mathf.Max(1, sample.m_shared.m_maxStackSize); int num2 = 0; foreach (ItemData allItem in inventory.GetAllItems()) { if (allItem != null && CanMerge(allItem, sample)) { num2 += num - allItem.m_stack; } } return num2 + emptySlots * num; } private static int TotalStacks(Inventory inv) { int num = 0; foreach (ItemData allItem in inv.GetAllItems()) { if (allItem != null) { num += allItem.m_stack; } } return num; } } public static class StorageDeposit { private class ChestModel { public Container Chest; public HashSet<string> Tokens = new HashSet<string>(); public int EmptySlots; public Dictionary<string, int> PartialFree = new Dictionary<string, int>(); public int CapacityFor(string token, int maxStack) { PartialFree.TryGetValue(token, out var value); return value + EmptySlots * maxStack; } public void Reserve(string token, int amount, int maxStack) { PartialFree.TryGetValue(token, out var value); int num = Mathf.Min(amount, value); value -= num; int num2 = amount - num; if (num2 > 0 && EmptySlots > 0) { EmptySlots--; value += maxStack - num2; } PartialFree[token] = value; Tokens.Add(token); } } private static readonly Vector2i AutoSlot = new Vector2i(-1, -1); public static int Deposit(Vector3 center, float radius, out bool leftover) { //IL_0032: Unknown result type (might be due to invalid IL or missing references) leftover = false; Player localPlayer = Player.m_localPlayer; if ((Object)(object)localPlayer == (Object)null) { return 0; } Inventory inventory = ((Humanoid)localPlayer).GetInventory(); if (inventory == null) { return 0; } object localConfig = QssFavorites.GetLocalConfig(); bool flag = localConfig != null; List<ChestModel> list = new List<ChestModel>(); foreach (Container item in StorageScanner.NearbyChests(center, radius)) { Inventory inventory2 = item.GetInventory(); if (inventory2 == null) { continue; } ChestModel chestModel = new ChestModel { Chest = item, EmptySlots = inventory2.GetEmptySlots() }; List<ItemData> allItems = inventory2.GetAllItems(); if (allItems != null) { foreach (ItemData item2 in allItems) { if (item2?.m_shared != null) { string name = item2.m_shared.m_name; chestModel.Tokens.Add(name); int num = Mathf.Max(1, item2.m_shared.m_maxStackSize) - item2.m_stack; if (num > 0) { chestModel.PartialFree.TryGetValue(name, out var value); chestModel.PartialFree[name] = value + num; } } } } list.Add(chestModel); } if (list.Count == 0) { return 0; } int deposited = 0; foreach (ItemData item3 in new List<ItemData>(inventory.GetAllItems())) { if (item3?.m_shared == null || item3.m_equipped) { continue; } if (flag) { if (QssFavorites.IsFavorited(localConfig, item3)) { continue; } } else if (item3.m_gridPos.y == 0) { continue; } string name2 = item3.m_shared.m_name; int maxStack = Mathf.Max(1, item3.m_shared.m_maxStackSize); int stack = item3.m_stack; stack -= DepositIntoChests(item3, name2, maxStack, stack, inventory, list, requireToken: true, ref deposited); if (stack > 0) { stack -= DepositIntoChests(item3, name2, maxStack, stack, inventory, list, requireToken: false, ref deposited); } if (stack > 0) { leftover = true; } } return deposited; } private static int DepositIntoChests(ItemData item, string token, int maxStack, int remaining, Inventory playerInv, List<ChestModel> models, bool requireToken, ref int deposited) { //IL_008d: 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) int num = 0; foreach (ChestModel model in models) { if (remaining - num <= 0) { break; } if (requireToken && !model.Tokens.Contains(token)) { continue; } Container chest = model.Chest; if ((Object)(object)chest == (Object)null || (Object)(object)chest.m_nview == (Object)null || !chest.m_nview.IsValid()) { continue; } int num2 = model.CapacityFor(token, maxStack); if (num2 <= 0) { continue; } int num3 = Mathf.Min(remaining - num, num2); if (num3 > 0) { try { ContainerHandler.AddItemToChest(chest, item, playerInv, AutoSlot, ZDOID.None, num3); model.Reserve(token, num3, maxStack); num += num3; deposited += num3; } catch (Exception ex) { Plugin.Log.LogWarning((object)("Deposit: adding to chest failed (" + ex.Message + ").")); } } } return num; } } public static class StorageMarkers { private const float BeamHeight = 40f; private static readonly List<GameObject> _active = new List<GameObject>(); private static Material? _beamMat; private static readonly Color CyanCore = new Color(0.45f, 0.85f, 1f, 0.95f); private static readonly Color CyanTop = new Color(0.45f, 0.85f, 1f, 0.1f); public static void Show(List<Vector3> chestPositions, Sprite? icon, float duration) { //IL_002f: 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_0034: Unknown result type (might be due to invalid IL or missing references) //IL_0040: Unknown result type (might be due to invalid IL or missing references) //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Unknown result type (might be due to invalid IL or missing references) //IL_0051: Expected O, but got Unknown //IL_0057: Unknown result type (might be due to invalid IL or missing references) //IL_005e: Unknown result type (might be due to invalid IL or missing references) //IL_0065: Unknown result type (might be due to invalid IL or missing references) //IL_0066: Unknown result type (might be due to invalid IL or missing references) Clear(); if (chestPositions == null || chestPositions.Count == 0) { return; } Vector3 viewer = (((Object)(object)Player.m_localPlayer != (Object)null) ? ((Component)Player.m_localPlayer).transform.position : Vector3.zero); foreach (Vector3 chestPosition in chestPositions) { GameObject val = new GameObject("OdinFindMarker"); val.transform.position = chestPosition; BuildBeam(val, chestPosition); BuildIcon(val, chestPosition, viewer, icon); val.AddComponent<MarkerLifetime>().Init(duration); _active.Add(val); } } public static void Clear() { foreach (GameObject item in _active) { if ((Object)(object)item != (Object)null) { Object.Destroy((Object)(object)item); } } _active.Clear(); } public static void StartTimers() { foreach (GameObject item in _active) { if ((Object)(object)item != (Object)null) { item.GetComponent<MarkerLifetime>()?.Begin(); } } } internal static void Forget(GameObject go) { _active.Remove(go); } private static Material BeamMaterial() { //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Expected O, but got Unknown if ((Object)(object)_beamMat == (Object)null) { _beamMat = new Material(Shader.Find("Sprites/Default") ?? Shader.Find("Unlit/Color") ?? Shader.Find("Standard")) { renderQueue = 4000 }; } return _beamMat; } private static void BuildBeam(GameObject root, Vector3 pos) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0015: 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_0017: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_0061: Unknown result type (might be due to invalid IL or missing references) //IL_0089: 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_009a: Unknown result type (might be due to invalid IL or missing references) //IL_00a5: Unknown result type (might be due to invalid IL or missing references) //IL_00aa: Unknown result type (might be due to invalid IL or missing references) Vector3 a = pos + Vector3.up * 0.4f; Vector3 b = pos + Vector3.up * 40.4f; AddLine(root, "Halo", a, b, 1.4f, 0.5f, new Color(CyanCore.r, CyanCore.g, CyanCore.b, 0.22f), new Color(CyanTop.r, CyanTop.g, CyanTop.b, 0.03f)); AddLine(root, "Core", a, b, 0.55f, 0.12f, CyanCore, CyanTop); } private static void AddLine(GameObject parent, string name, Vector3 a, Vector3 b, float wBottom, float wTop, Color cBottom, Color cTop) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_0065: Unknown result type (might be due to invalid IL or missing references) //IL_006d: Unknown result type (might be due to invalid IL or missing references) GameObject val = new GameObject(name); val.transform.SetParent(parent.transform, false); LineRenderer obj = val.AddComponent<LineRenderer>(); obj.useWorldSpace = true; obj.positionCount = 2; obj.SetPosition(0, a); obj.SetPosition(1, b); obj.startWidth = wBottom; obj.endWidth = wTop; obj.numCapVertices = 4; obj.alignment = (LineAlignment)0; ((Renderer)obj).sharedMaterial = BeamMaterial(); obj.startColor = cBottom; obj.endColor = cTop; ((Renderer)obj).shadowCastingMode = (ShadowCastingMode)0; ((Renderer)obj).receiveShadows = false; ((Renderer)obj).lightProbeUsage = (LightProbeUsage)0; } private static void BuildIcon(GameObject root, Vector3 chestPos, Vector3 viewer, Sprite? icon) { //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_000b: 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_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Unknown result type (might be due to invalid IL or missing references) //IL_004c: Unknown result type (might be due to invalid IL or missing references) //IL_0056: Unknown result type (might be due to invalid IL or missing references) //IL_005b: Unknown result type (might be due to invalid IL or missing references) //IL_0060: Unknown result type (might be due to invalid IL or missing references) //IL_0066: Unknown result type (might be due to invalid IL or missing references) //IL_006b: Unknown result type (might be due to invalid IL or missing references) //IL_007d: Unknown result type (might be due to invalid IL or missing references) //IL_0083: Unknown result type (might be due to invalid IL or missing references) //IL_0089: 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_00c8: Unknown result type (might be due to invalid IL or missing references) //IL_00cd: Unknown result type (might be due to invalid IL or missing references) //IL_00d1: Unknown result type (might be due to invalid IL or missing references) //IL_00e1: Unknown result type (might be due to invalid IL or missing references) //IL_00e7: Unknown result type (might be due to invalid IL or missing references) //IL_00f3: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)icon == (Object)null)) { Vector3 val = viewer - chestPos; val.y = 0f; val = ((((Vector3)(ref val)).sqrMagnitude > 0.01f) ? ((Vector3)(ref val)).normalized : Vector3.forward); Vector3 position = chestPos + val * 0.6f + Vector3.up * 0.35f; GameObject val2 = new GameObject("Icon"); val2.transform.SetParent(root.transform, false); val2.transform.position = position; SpriteRenderer val3 = val2.AddComponent<SpriteRenderer>(); val3.sprite = icon; val3.color = new Color(0.6f, 0.9f, 1f, 1f); ((Renderer)val3).shadowCastingMode = (ShadowCastingMode)0; Bounds bounds = val3.sprite.bounds; float num = Mathf.Max(0.01f, ((Bounds)(ref bounds)).size.x); val2.transform.localScale = Vector3.one * (0.7f / num); val2.AddComponent<MarkerBillboard>(); } } } public class MarkerLifetime : MonoBehaviour { private float _duration = 30f; private float _remaining; private bool _running; public void Init(float seconds) { _duration = Mathf.Max(0.5f, seconds); } public void Begin() { _remaining = _duration; _running = true; } private void Update() { if (_running) { _remaining -= Time.deltaTime; if (_remaining <= 0f) { Object.Destroy((Object)(object)((Component)this).gameObject); } } } private void OnDestroy() { StorageMarkers.Forget(((Component)this).gameObject); } } public class MarkerBillboard : MonoBehaviour { private float _baseScale = 1f; private SpriteRenderer? _sr; private void Start() { //IL_0007: Unknown result type (might be due to invalid IL or missing references) _baseScale = ((Component)this).transform.localScale.x; _sr = ((Component)this).GetComponent<SpriteRenderer>(); } private void LateUpdate() { //IL_0057: Unknown result type (might be due to invalid IL or missing references) //IL_0070: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_008e: Unknown result type (might be due to invalid IL or missing references) //IL_0093: Unknown result type (might be due to invalid IL or missing references) //IL_00ae: Unknown result type (might be due to invalid IL or missing references) Camera val = Utils.GetMainCamera(); if ((Object)(object)val == (Object)null) { val = Camera.main; } if ((Object)(object)val != (Object)null) { ((Component)this).transform.rotation = ((Component)val).transform.rotation; } float num = 0.5f + 0.5f * Mathf.Sin(Time.time * 5f); ((Component)this).transform.localScale = Vector3.one * (_baseScale * (0.9f + 0.15f * num)); if ((Object)(object)_sr != (Object)null) { Color color = _sr.color; color.a = 0.7f + 0.3f * num; _sr.color = color; } } } public class StorageRowHover : MonoBehaviour, IPointerEnterHandler, IEventSystemHandler, IPointerExitHandler { private Image? _bg; private static readonly Color Normal = new Color(1f, 1f, 1f, 0f); private static readonly Color Hover = new Color(1f, 1f, 1f, 0.12f); private void Awake() { //IL_0020: Unknown result type (might be due to invalid IL or missing references) _bg = ((Component)this).GetComponent<Image>(); if ((Object)(object)_bg != (Object)null) { ((Graphic)_bg).color = Normal; } } public void OnPointerEnter(PointerEventData eventData) { //IL_0014: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_bg != (Object)null) { ((Graphic)_bg).color = Hover; } } public void OnPointerExit(PointerEventData eventData) { //IL_0014: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_bg != (Object)null) { ((Graphic)_bg).color = Normal; } } } public class StorageEntry { public string Token = string.Empty; public string Name = string.Empty; public int Count; public Sprite? Icon; } public class StorageSnapshot { public List<StorageEntry> Entries = new List<StorageEntry>(); public int ChestCount; public int TotalItems; public int TotalSlots; public int UsedSlots; public int AlmostFullChests; } public static class StorageScanner { [CompilerGenerated] private sealed class <NearbyChests>d__0 : IEnumerable<Container>, IEnumerable, IEnumerator<Container>, IDisposable, IEnumerator { private int <>1__state; private Container <>2__current; private int <>l__initialThreadId; private float radius; public float <>3__radius; private Vector3 center; public Vector3 <>3__center; private float <radiusSqr>5__2; private Container[] <>7__wrap2; private int <>7__wrap3; Container IEnumerator<Container>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <NearbyChests>d__0(int <>1__state) { this.<>1__state = <>1__state; <>l__initialThreadId = Environment.CurrentManagedThreadId; } [DebuggerHidden] void IDisposable.Dispose() { <>7__wrap2 = null; <>1__state = -2; } private bool MoveNext() { //IL_009a: 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_00a5: Unknown result type (might be due to invalid IL or missing references) //IL_00aa: Unknown result type (might be due to invalid IL or missing references) int num = <>1__state; if (num != 0) { if (num != 1) { return false; } <>1__state = -1; goto IL_00d1; } <>1__state = -1; <radiusSqr>5__2 = radius * radius; Container[] array = Object.FindObjectsByType<Container>((FindObjectsSortMode)0); <>7__wrap2 = array; <>7__wrap3 = 0; goto IL_00df; IL_00d1: <>7__wrap3++; goto IL_00df; IL_00df: if (<>7__wrap3 < <>7__wrap2.Length) { Container val = <>7__wrap2[<>7__wrap3]; if (!((Object)(object)val == (Object)null) && !((Object)(object)val.m_nview == (Object)null) && val.m_nview.IsValid() && !(((Object)val).name ?? string.Empty).StartsWith("TreasureChest")) { Vector3 val2 = ((Component)val).transform.position - center; if (!(((Vector3)(ref val2)).sqrMagnitude > <radiusSqr>5__2)) { <>2__current = val; <>1__state = 1; return true; } } goto IL_00d1; } <>7__wrap2 = null; return false; } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } [DebuggerHidden] IEnumerator<Container> IEnumerable<Container>.GetEnumerator() { //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Unknown result type (might be due to invalid IL or missing references) <NearbyChests>d__0 <NearbyChests>d__; if (<>1__state == -2 && <>l__initialThreadId == Environment.CurrentManagedThreadId) { <>1__state = 0; <NearbyChests>d__ = this; } else { <NearbyChests>d__ = new <NearbyChests>d__0(0); } <NearbyChests>d__.center = <>3__center; <NearbyChests>d__.radius = <>3__radius; return <NearbyChests>d__; } [DebuggerHidden] IEnumerator IEnumerable.GetEnumerator() { return ((IEnumerable<Container>)this).GetEnumerator(); } } [IteratorStateMachine(typeof(<NearbyChests>d__0))] public static IEnumerable<Container> NearbyChests(Vector3 center, float radius) { //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_0009: Unknown result type (might be due to invalid IL or missing references) //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <NearbyChests>d__0(-2) { <>3__center = center, <>3__radius = radius }; } public static StorageSnapshot AggregateNearby(Vector3 center, float radius) { //IL_000f: Unknown result type (might be due to invalid IL or missing references) Dictionary<string, StorageEntry> dictionary = new Dictionary<string, StorageEntry>(); int num = 0; int num2 = 0; int num3 = 0; int num4 = 0; foreach (Container item in NearbyChests(center, radius)) { Inventory inventory = item.GetInventory(); if (inventory == null) { continue; } List<ItemData> allItems = inventory.GetAllItems(); num++; int num5 = inventory.GetWidth() * inventory.GetHeight(); int emptySlots = inventory.GetEmptySlots(); num2 += num5; num3 += num5 - emptySlots; if (emptySlots <= 1) { num4++; } foreach (ItemData item2 in allItems) { if (item2?.m_shared == null) { continue; } string name = item2.m_shared.m_name; if (!dictionary.TryGetValue(name, out var value)) { string text = ((Localization.instance != null) ? Localization.instance.Localize(name) : name); if (string.IsNullOrEmpty(text)) { text = name; } Sprite icon = ((item2.m_shared.m_icons != null && item2.m_shared.m_icons.Length != 0) ? item2.m_shared.m_icons[0] : null); value = (dictionary[name] = new StorageEntry { Token = name, Name = text, Icon = icon }); } value.Count += item2.m_stack; } } List<StorageEntry> list = dictionary.Values.OrderByDescending((StorageEntry e) => e.Count).ToList(); int totalItems = list.Sum((StorageEntry e) => e.Count); return new StorageSnapshot { Entries = list, ChestCount = num, TotalItems = totalItems, TotalSlots = num2, UsedSlots = num3, AlmostFullChests = num4 }; } public static void Scan() { //IL_0021: Unknown result type (might be due to invalid IL or missing references) Player localPlayer = Player.m_localPlayer; if ((Object)(object)localPlayer == (Object)null) { return; } float value = Plugin.Radius.Value; StorageSnapshot storageSnapshot = AggregateNearby(((Component)localPlayer).transform.position, value); Plugin.Log.LogInfo((object)$"=== Storage scan within {value:0.#} m ==="); foreach (StorageEntry entry in storageSnapshot.Entries) { Plugin.Log.LogInfo((object)$"{entry.Name}: {entry.Count}"); } Plugin.Log.LogInfo((object)$"=== {storageSnapshot.ChestCount} chests, {storageSnapshot.Entries.Count} item types, {storageSnapshot.TotalItems} items total ==="); } } public class StorageTerminal : MonoBehaviour, Interactable, Hoverable { public string GetHoverName() { return "Odin Terminal"; } public string GetHoverText() { if (Localization.instance == null) { return "[E] Open Storage"; } return Localization.instance.Localize("[<color=yellow><b>$KEY_Use</b></color>] Open Storage"); } public bool Interact(Humanoid user, bool hold, bool alt) { //IL_000b: Unknown result type (might be due to invalid IL or missing references) if (hold) { return false; } StorageTerminalUI.Open(((Component)this).transform.position); return true; } public bool UseItem(Humanoid user, ItemData item) { return false; } } public static class StorageTerminalUI { [CompilerGenerated] private static class <>O { public static UnityAction <0>__Close; public static UnityAction <1>__DoDeposit; public static UnityAction <2>__OnCleanupClicked; public static UnityAction<string> <3>__OnSearchChanged; public static UnityAction <4>__ConfirmCleanup; public static UnityAction <5>__CancelCleanup; } private const string CatAll = "all"; private const string CatOre = "ore"; private const string CatFood = "food"; private const string CatMaterial = "material"; private const float NameMinWidth = 40f; private const float CountColWidth = 52f; private const float NameCountGap = 10f; private static readonly List<(Text Label, string Full)> _nameLabels = new List<(Text, string)>(); private static GameObject? _panel; private static InputField? _search; private static Text? _header; private static Transform? _content; private static GameObject? _confirmPanel; private static Text? _confirmText; private static RectTransform? _fillRt; private static Image? _fillImg; private static readonly List<GameObject> _rows = new List<GameObject>(); private static readonly List<string> _order = new List<string>(); private static readonly Dictionary<string, StorageEntry> _entries = new Dictionary<string, StorageEntry>(); private static string _query = string.Empty; private static string _category = "all"; private static Vector3 _center; private static readonly string[] OreWords = new string[8] { "copper", "tin", "bronze", "iron", "silver", "blackmetal", "flametal", "ore" }; private static readonly string[] FoodWords = new string[18] { "carrot", "mushroom", "raspberr", "blueberr", "cloudberr", "honey", "meat", "fish", "cooked", "bread", "mead", "sausage", "stew", "soup", "turnip", "onion", "jam", "pie" }; public static bool IsOpen { get { if ((Object)(object)_panel != (Object)null) { return _panel.activeSelf; } return false; } } public static void Create() { //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_0053: 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) //IL_00a5: Unknown result type (might be due to invalid IL or missing references) //IL_00b4: Unknown result type (might be due to invalid IL or missing references) //IL_00ca: Unknown result type (might be due to invalid IL or missing references) //IL_00d0: Unknown result type (might be due to invalid IL or missing references) //IL_0120: Unknown result type (might be due to invalid IL or missing references) //IL_012f: Unknown result type (might be due to invalid IL or missing references) //IL_013e: Unknown result type (might be due to invalid IL or missing references) //IL_019a: Unknown result type (might be due to invalid IL or missing references) //IL_01a9: Unknown result type (might be due to invalid IL or missing references) //IL_01b8: Unknown result type (might be due to invalid IL or missing references) //IL_016c: Unknown result type (might be due to invalid IL or missing references) //IL_0171: Unknown result type (might be due to invalid IL or missing references) //IL_0177: Expected O, but got Unknown //IL_022c: Unknown result type (might be due to invalid IL or missing references) //IL_023b: Unknown result type (might be due to invalid IL or missing references) //IL_024a: Unknown result type (might be due to invalid IL or missing references) //IL_01fe: Unknown result type (might be due to invalid IL or missing references) //IL_0203: Unknown result type (might be due to invalid IL or missing references) //IL_0209: Expected O, but got Unknown //IL_02cd: Unknown result type (might be due to invalid IL or missing references) //IL_02dc: Unknown result type (might be due to invalid IL or missing references) //IL_02eb: Unknown result type (might be due to invalid IL or missing references) //IL_0301: Unknown result type (might be due to invalid IL or missing references) //IL_0307: Unknown result type (might be due to invalid IL or missing references) //IL_0290: Unknown result type (might be due to invalid IL or missing references) //IL_0295: Unknown result type (might be due to invalid IL or missing references) //IL_029b: Expected O, but got Unknown //IL_0366: Unknown result type (might be due to invalid IL or missing references) //IL_0375: Unknown result type (might be due to invalid IL or missing references) //IL_0384: Unknown result type (might be due to invalid IL or missing references) //IL_0403: Unknown result type (might be due to invalid IL or missing references) //IL_041c: Unknown result type (might be due to invalid IL or missing references) //IL_0441: Unknown result type (might be due to invalid IL or missing references) //IL_0456: Unknown result type (might be due to invalid IL or missing references) //IL_046b: Unknown result type (might be due to invalid IL or missing references) //IL_047f: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)_panel != (Object)null) && GUIManager.Instance != null && !GUIManager.IsHeadless()) { _panel = GUIManager.Instance.CreateWoodpanel(GUIManager.CustomGUIFront.transform, new Vector2(0.5f, 0.5f), new Vector2(0.5f, 0.5f), new Vector2(0f, 0f), 500f, 600f, true); _panel.SetActive(false); Text component = GUIManager.Instance.CreateText("Storage", _panel.transform, new Vector2(0.5f, 1f), new Vector2(0.5f, 1f), new Vector2(0f, -28f), GUIManager.Instance.AveriaSerifBold, 26, GUIManager.Instance.ValheimOrange, true, Color.black, 140f, 36f, false).GetComponent<Text>(); if ((Object)(object)component != (Object)null) { component.alignment = (TextAnchor)4; component.horizontalOverflow = (HorizontalWrapMode)1; } ButtonClickedEvent onClick = GUIManager.Instance.CreateButton("X", _panel.transform, new Vector2(1f, 1f), new Vector2(1f, 1f), new Vector2(-30f, -28f), 40f, 40f).GetComponent<Button>().onClick; object obj = <>O.<0>__Close; if (obj == null) { UnityAction val = Close; <>O.<0>__Close = val; obj = (object)val; } ((UnityEvent)onClick).AddListener((UnityAction)obj); GameObject obj2 = GUIManager.Instance.CreateButton("Deposit", _panel.transform, new Vector2(0f, 1f), new Vector2(0f, 1f), new Vector2(65f, -28f), 110f, 32f); Text componentInChildren = obj2.GetComponentInChildren<Text>(); if ((Object)(object)componentInChildren != (Object)null) { componentInChildren.fontSize = 15; } ButtonClickedEvent onClick2 = obj2.GetComponent<Button>().onClick; object obj3 = <>O.<1>__DoDeposit; if (obj3 == null) { UnityAction val2 = DoDeposit; <>O.<1>__DoDeposit = val2; obj3 = (object)val2; } ((UnityEvent)onClick2).AddListener((UnityAction)obj3); GameObject obj4 = GUIManager.Instance.CreateButton("Consolidate", _panel.transform, new Vector2(1f, 1f), new Vector2(1f, 1f), new Vector2(-145f, -28f), 110f, 32f); Text componentInChildren2 = obj4.GetComponentInChildren<Text>(); if ((Object)(object)componentInChildren2 != (Object)null) { componentInChildren2.fontSize = 13; } ButtonClickedEvent onClick3 = obj4.GetComponent<Button>().onClick; object obj5 = <>O.<2>__OnCleanupClicked; if (obj5 == null) { UnityAction val3 = OnCleanupClicked; <>O.<2>__OnCleanupClicked = val3; obj5 = (object)val3; } ((UnityEvent)onClick3).AddListener((UnityAction)obj5); BuildConfirmDialog(_panel.transform); _header = GUIManager.Instance.CreateText(string.Empty, _panel.transform, new Vector2(0.5f, 1f), new Vector2(0.5f, 1f), new Vector2(0f, -70f), GUIManager.Instance.AveriaSerifBold, 14, GUIManager.Instance.ValheimBeige, true, Color.black, 460f, 38f, false).GetComponent<Text>(); if ((Object)(object)_header != (Object)null) { _header.alignment = (TextAnchor)1; } BuildFillBar(_panel.transform); _search = GUIManager.Instance.CreateInputField(_panel.transform, new Vector2(0.5f, 1f), new Vector2(0.5f, 1f), new Vector2(0f, -120f), (ContentType)0, "Search…", 16, 440f, 32f).GetComponent<InputField>(); ((UnityEvent<string>)(object)_search.onValueChanged).AddListener((UnityAction<string>)OnSearchChanged); BuildFilterBar(_panel.transform); GameObject obj6 = GUIManager.Instance.CreateScrollView(_panel.transform, false, true, 0.6f, 0f, GUIManager.Instance.ValheimScrollbarHandleColorBlock, new Color(0f, 0f, 0f, 0.2f), 460f, 395f); RectTransform component2 = obj6.GetComponent<RectTransform>(); component2.anchorMin = new Vector2(0.5f, 0f); component2.anchorMax = new Vector2(0.5f, 0f); component2.pivot = new Vector2(0.5f, 0f); component2.anchoredPosition = new Vector2(0f, 20f); _content = (Transform?)(object)obj6.GetComponentInChildren<ScrollRect>().content; VerticalLayoutGroup val4 = ((Component)_content).gameObject.GetComponent<VerticalLayoutGroup>(); if ((Object)(object)val4 == (Object)null) { val4 = ((Component)_content).gameObject.AddComponent<VerticalLayoutGroup>(); } ((HorizontalOrVerticalLayoutGroup)val4).spacing = 4f; ((HorizontalOrVerticalLayoutGroup)val4).childControlWidth = true; ((HorizontalOrVerticalLayoutGroup)val4).childControlHeight = true; ((HorizontalOrVerticalLayoutGroup)val4).childForceExpandWidth = true; ((HorizontalOrVerticalLayoutGroup)val4).childForceExpandHeight = false; ContentSizeFitter val5 = ((Component)_content).gameObject.GetComponent<ContentSizeFitter>(); if ((Object)(object)val5 == (Object)null) { val5 = ((Component)_content).gameObject.AddComponent<ContentSizeFitter>(); } val5.verticalFit = (FitMode)2; ApplyUiScale(); } } private static void ApplyUiScale() { //IL_003b: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)_panel == (Object)null)) { float num = Mathf.Clamp((float)Screen.height / 1080f, 0.8f, 2.5f); _panel.transform.localScale = new Vector3(num, num, 1f); } } private static void BuildFilterBar(Transform parent) { //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_0050: Unknown result type (might be due to invalid IL or missing references) //IL_0065: Unknown result type (might be due to invalid IL or missing references) //IL_007a: Unknown result type (might be due to invalid IL or missing references) //IL_008e: Unknown result type (might be due to invalid IL or missing references) //IL_0098: Unknown result type (might be due to invalid IL or missing references) //IL_00c4: Unknown result type (might be due to invalid IL or missing references) //IL_00d9: Unknown result type (might be due to invalid IL or missing references) //IL_00ee: Unknown result type (might be due to invalid IL or missing references) GameObject val = new GameObject("OdinFilterBar", new Type[1] { typeof(RectTransform) }); val.transform.SetParent(parent, false); RectTransform component = val.GetComponent<RectTransform>(); component.anchorMin = new Vector2(0.5f, 1f); component.anchorMax = new Vector2(0.5f, 1f); component.pivot = new Vector2(0.5f, 1f); component.anchoredPosition = new Vector2(0f, -156f); component.sizeDelta = new Vector2(460f, 30f); HorizontalLayoutGroup obj = val.AddComponent<HorizontalLayoutGroup>(); ((HorizontalOrVerticalLayoutGroup)obj).spacing = 6f; ((HorizontalOrVerticalLayoutGroup)obj).childControlWidth = true; ((HorizontalOrVerticalLayoutGroup)obj).childControlHeight = true; ((HorizontalOrVerticalLayoutGroup)obj).childForceExpandWidth = true; ((HorizontalOrVerticalLayoutGroup)obj).childForceExpandHeight = true; AddFilterButton(val.transform, "All", "all"); AddFilterButton(val.transform, "Ore/Metal", "ore"); AddFilterButton(val.transform, "Food", "food"); AddFilterButton(val.transform, "Materials", "material"); } private static void AddFilterButton(Transform parent, string label, string category) { //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_0093: Unknown result type (might be due to invalid IL or missing references) //IL_009d: Expected O, but got Unknown string category2 = category; GameObject val = GUIManager.Instance.CreateButton(label, parent, new Vector2(0.5f, 0.5f), new Vector2(0.5f, 0.5f), Vector2.zero, 100f, 28f); Text componentInChildren = val.GetComponentInChildren<Text>(); if ((Object)(object)componentInChildren != (Object)null) { componentInChildren.fontSize = 14; } LayoutElement val2 = val.GetComponent<LayoutElement>(); if ((Object)(object)val2 == (Object)null) { val2 = val.AddComponent<LayoutElement>(); } val2.flexibleWidth = 1f; ((UnityEvent)val.GetComponent<Button>().onClick).AddListener((UnityAction)delegate { SetCategory(category2); }); } public static void Open(Vector3 center) { //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_0049: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_panel == (Object)null) { return; } _center = center; StorageMarkers.Clear(); _query = string.Empty; _category = "all"; if ((Object)(object)_search != (Object)null) { _search.text = string.Empty; } StorageSnapshot storageSnapshot = StorageScanner.AggregateNearby(_center, Plugin.Radius.Value); _order.Clear(); _entries.Clear(); foreach (StorageEntry entry in storageSnapshot.Entries) { _order.Add(entry.Token); _entries[entry.Token] = entry; } UpdateHeader(storageSnapshot); ApplyUiScale(); _panel.SetActive(true); GUIManager.BlockInput(true); ApplyFilters(); } public static void Refresh() { //IL_0008: Unknown result type (might be due to invalid IL or missing references) if (!IsOpen) { return; } StorageSnapshot storageSnapshot = StorageScanner.AggregateNearby(_center, Plugin.Radius.Value); Dictionary<string, StorageEntry> dictionary = new Dictionary<string, StorageEntry>(); foreach (StorageEntry entry in storageSnapshot.Entries) { dictionary[entry.Token] = entry; } foreach (string item in _order) { StorageEntry value2; if (dictionary.TryGetValue(item, out var value)) { _entries[item] = value; } else if (_entries.TryGetValue(item, out value2)) { value2.Count = 0; } } foreach (StorageEntry entry2 in storageSnapshot.Entries) { if (!_entries.ContainsKey(entry2.Token)) { _order.Add(entry2.Token); _entries[entry2.Token] = entry2; } } UpdateHeader(storageSnapshot); ApplyFilters(); } private static void BuildFillBar(Transform parent) { //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Expected O, but got Unknown //IL_0049: Unknown result type (might be due to invalid IL or missing references) //IL_005e: Unknown result type (might be due to invalid IL or missing references) //IL_0073: 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) //IL_009c: Unknown result type (might be due to invalid IL or missing references) //IL_00c0: Unknown result type (might be due to invalid IL or missing references) //IL_00ef: Unknown result type (might be due to invalid IL or missing references) //IL_00f4: Unknown result type (might be due to invalid IL or missing references) //IL_0106: Unknown result type (might be due to invalid IL or missing references) //IL_0120: Unknown result type (might be due to invalid IL or missing references) //IL_0139: Unknown result type (might be due to invalid IL or missing references) //IL_0152: Unknown result type (might be due to invalid IL or missing references) //IL_0161: Unknown result type (might be due to invalid IL or missing references) //IL_0170: Unknown result type (might be due to invalid IL or missing references) //IL_019d: Unknown result type (might be due to invalid IL or missing references) GameObject val = new GameObject("OdinFillBarBg", new Type[2] { typeof(RectTransform), typeof(Image) }); val.transform.SetParent(parent, false); RectTransform component = val.GetComponent<RectTransform>(); component.anchorMin = new Vector2(0.5f, 1f); component.anchorMax = new Vector2(0.5f, 1f); component.pivot = new Vector2(0.5f, 1f); component.anchoredPosition = new Vector2(0f, -96f); component.sizeDelta = new Vector2(440f, 6f); ((Graphic)val.GetComponent<Image>()).color = new Color(0f, 0f, 0f, 0.5f); GameObject val2 = new GameObject("OdinFillBarFill", new Type[2] { typeof(RectTransform), typeof(Image) }); val2.transform.SetParent(val.transform, false); _fillRt = val2.GetComponent<RectTransform>(); _fillRt.anchorMin = new Vector2(0f, 0f); _fillRt.anchorMax = new Vector2(0f, 1f); _fillRt.pivot = new Vector2(0f, 0.5f); _fillRt.offsetMin = Vector2.zero; _fillRt.offsetMax = Vector2.zero; _fillImg = val2.GetComponent<Image>(); ((Graphic)_fillImg).color = new Color(0.3f, 0.8f, 0.3f, 1f); } private static void UpdateHeader(StorageSnapshot snap) { //IL_0101: Unknown result type (might be due to invalid IL or missing references) //IL_0110: Unknown result type (might be due to invalid IL or missing references) //IL_011f: Unknown result type (might be due to invalid IL or missing references) //IL_0195: Unknown result type (might be due to invalid IL or missing references) //IL_017a: Unknown result type (might be due to invalid IL or missing references) //IL_015f: Unknown result type (might be due to invalid IL or missing references) int totalSlots = snap.TotalSlots; int usedSlots = snap.UsedSlots; float num = ((totalSlots > 0) ? ((float)usedSlots / (float)totalSlots) : 0f); int num2 = Mathf.RoundToInt(num * 100f); if ((Object)(object)_header != (Object)null) { string text = $"{snap.ChestCount} chests · {snap.Entries.Count} types · {snap.TotalItems} items"; string text2 = $"{usedSlots} / {totalSlots} slots · {num2}%"; if (snap.AlmostFullChests == 1) { text2 += " · 1 chest nearly full"; } else if (snap.AlmostFullChests > 1) { text2 += $" · {snap.AlmostFullChests} chests nearly full"; } _header.text = text + "\n" + text2; } if ((Object)(object)_fillRt != (Object)null) { _fillRt.anchorMax = new Vector2(Mathf.Clamp01(num), 1f); _fillRt.offsetMin = Vector2.zero; _fillRt.offsetMax = Vector2.zero; } if ((Object)(object)_fillImg != (Object)null) { ((Graphic)_fillImg).color = ((num >= 0.9f) ? new Color(0.85f, 0.25f, 0.2f, 1f) : ((num >= 0.75f) ? new Color(0.9f, 0.8f, 0.2f, 1f) : new Color(0.3f, 0.8f, 0.3f, 1f))); } } public static void Close() { if (!((Object)(object)_panel == (Object)null)) { _panel.SetActive(false); GUIManager.BlockInput(false); StorageMarkers.StartTimers(); } } private static void OnSearchChanged(string query) { _query = query ?? string.Empty; ApplyFilters(); } private static void SetCategory(string category) { _category = category; ApplyFilters(); } private static void ApplyFilters() { List<StorageEntry> list = new List<StorageEntry>(); foreach (string item in _order) { if (_entries.TryGetValue(item, out StorageEntry value) && value.Count > 0) { list.Add(value); } } IEnumerable<StorageEntry> source = list; if (_category != "all") { source = source.Where((StorageEntry e) => Classify(e.Token) == _category); } if (!string.IsNullOrEmpty(_query)) { string q = _query.ToLowerInvariant(); source = source.Where((StorageEntry e) => e.Name.ToLowerInvariant().Contains(q)); } RebuildRows(source.ToList()); } private static string Classify(string token) { string t = token.ToLowerInvariant(); if (OreWords.Any((string w) => t.Contains(w))) { return "ore"; } if (FoodWords.Any((string w) => t.Contains(w))) { return "food"; } return "material"; } private static void RebuildRows(List<StorageEntry> entries) { if ((Object)(object)_content == (Object)null) { return; } foreach (GameObject row in _rows) { Object.Destroy((Object)(object)row); } _rows.Clear(); _nameLabels.Clear(); foreach (StorageEntry entry in entries) { _rows.Add(CreateRow(entry)); } FitNameLabels(); } private static void FitNameLabels() { //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Expected O, but got Unknown //IL_005e: Unknown result type (might be due to invalid IL or missing references) //IL_0063: Unknown result type (might be due to invalid IL or missing references) //IL_0068: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_content == (Object)null || _nameLabels.Count == 0) { return; } Canvas.ForceUpdateCanvases(); LayoutRebuilder.ForceRebuildLayoutImmediate((RectTransform)_content); foreach (var (val, s) in _nameLabels) { if (!((Object)(object)val == (Object)null)) { Rect rect = ((RectTransform)((Component)val).transform).rect; float num = ((Rect)(ref rect)).width - 10f; if (!(num <= 1f)) { val.horizontalOverflow = (HorizontalWrapMode)1; val.text = TruncateToWidth(val, s, num); } } } } private static GameObject CreateRow(StorageEntry e) { //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Expected O, but got Unknown //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_00cd: Unknown result type (might be due to invalid IL or missing references) //IL_00d2: Unknown result type (might be due to invalid IL or missing references) //IL_00e4: Unknown result type (might be due to invalid IL or missing references) //IL_017c: Unknown result type (might be due to invalid IL or missing references) //IL_018b: Unknown result type (might be due to invalid IL or missing references) //IL_0190: Unknown result type (might be due to invalid IL or missing references) //IL_01a1: Unknown result type (might be due to invalid IL or missing references) //IL_01a7: Unknown result type (might be due to invalid IL or missing references) //IL_026e: Unknown result type (might be due to invalid IL or missing references) //IL_027d: Unknown result type (might be due to invalid IL or missing references) //IL_0282: Unknown result type (might be due to invalid IL or missing references) //IL_0293: Unknown result type (might be due to invalid IL or missing references) //IL_0299: Unknown result type (might be due to invalid IL or missing references) GameObject val = new GameObject("OdinRow", new Type[1] { typeof(RectTransform) }); val.transform.SetParent(_content, false); Image obj = val.AddComponent<Image>(); ((Graphic)obj).color = new Color(1f, 1f, 1f, 0f); ((Graphic)obj).raycastTarget = true; HorizontalLayoutGroup obj2 = val.AddComponent<HorizontalLayoutGroup>(); ((HorizontalOrVerticalLayoutGroup)obj2).spacing = 8f; ((LayoutGroup)obj2).childAlignment = (TextAnchor)3; ((HorizontalOrVerticalLayoutGroup)obj2).childControlWidth = true; ((HorizontalOrVerticalLayoutGroup)obj2).childControlHeight = true; ((HorizontalOrVerticalLayoutGroup)obj2).childForceExpandWidth = false; ((HorizontalOrVerticalLayoutGroup)obj2).childForceExpandHeight = false; LayoutElement obj3 = val.AddComponent<LayoutElement>(); obj3.minHeight = 34f; obj3.preferredHeight = 34f; GameObject val2 = new GameObject("Icon", new Type[2] { typeof(RectTransform), typeof(Image) }); val2.transform.SetParent(val.transform, false); Image component = val2.GetComponent<Image>(); if ((Object)(object)e.Icon != (Object)null) { component.sprite = e.Icon; component.preserveAspect = true; } else { ((Behaviour)component).enabled = false; } LayoutElement obj4 = val2.AddComponent<LayoutElement>(); obj4.minWidth = 32f; obj4.preferredWidth = 32f; obj4.minHeight = 32f; obj4.preferredHeight = 32f; AddFindButton(val.transform, 56f, e.Token, e.Icon); GameObject val3 = GUIManager.Instance.CreateText(e.Name, val.transform, new Vector2(0f, 0.5f), new Vector2(1f, 0.5f), Vector2.zero, GUIManager.Instance.AveriaSerifBold, 18, Color.white, true, Color.black, 40f, 30f, false); Text component2 = val3.GetComponent<Text>(); if ((Object)(object)component2 != (Object)null) { component2.alignment = (TextAnchor)3; component2.horizontalOverflow = (HorizontalWrapMode)0; component2.verticalOverflow = (VerticalWrapMode)0; _nameLabels.Add((component2, e.Name)); } LayoutElement val4 = val3.GetComponent<LayoutElement>(); if ((Object)(object)val4 == (Object)null) {