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 Hutoheim v1.20.509
plugins/Hutoheim.dll
Decompiled 13 hours 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.Globalization; using System.IO; using System.IO.Compression; using System.Linq; using System.Linq.Expressions; using System.Reflection; using System.Reflection.Emit; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Versioning; using System.Text; using System.Threading; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; using Hutoheim.Combat; using Hutoheim.Convenience; using Hutoheim.Equip; using Hutoheim.Farm.Mining; using Hutoheim.Farm.Plant; using Hutoheim.Farm.Terrain; using Hutoheim.Portal; using Hutoheim.Storage; using TMPro; using UnityEngine; using UnityEngine.Events; using UnityEngine.UI; [assembly: AssemblyTitle("Hutoheim")] [assembly: AssemblyDescription("HutoChaWon 발헤임 모드: 상자, 포탈, 경험치, 전투, 농사·지형, 편의, 생산, 장비칸")] [assembly: AssemblyCompany("HutoChaWon")] [assembly: AssemblyProduct("Hutoheim")] [assembly: AssemblyCopyright("Copyright © 2026 HutoChaWon")] [assembly: AssemblyFileVersion("1.20.509.0")] [assembly: TargetFramework(".NETFramework,Version=v4.6.2", FrameworkDisplayName = ".NET Framework 4.6.2")] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: AssemblyVersion("1.20.509.0")] namespace Hutoheim.Storage { internal sealed class MaterialPool : CraftChests.IMaterialSource { private readonly List<Container> _chests; private readonly Dictionary<string, List<ItemData>> _inv = new Dictionary<string, List<ItemData>>(); private readonly Dictionary<string, List<KeyValuePair<Inventory, ItemData>>> _chest = new Dictionary<string, List<KeyValuePair<Inventory, ItemData>>>(); public static bool Strict; private readonly Dictionary<Inventory, Container> _containerOf = new Dictionary<Inventory, Container>(); public bool Dirty; private readonly HashSet<Inventory> _watched = new HashSet<Inventory>(); private Inventory _playerInv; public int ChestCount { get; private set; } public MaterialPool(List<Container> chests) { _chests = chests; if (_chests != null) { foreach (Container chest in _chests) { Inventory val = ((!((Object)(object)chest != (Object)null)) ? null : chest.GetInventory()); if (val != null) { _watched.Add(val); } } } Reindex(); } private bool Ok(Inventory inv) { if (!Strict) { return true; } Container value; return inv != null && _containerOf.TryGetValue(inv, out value) && ContainerAccess.StillOwned(value); } private void Fresh() { if (Dirty) { Reindex(); } } public bool Concerns(Inventory inv) { if (inv == null) { return false; } Player localPlayer = Player.m_localPlayer; if ((Object)(object)localPlayer != (Object)null && inv == ((Humanoid)localPlayer).GetInventory()) { return true; } if (inv == _playerInv) { return true; } return _watched.Contains(inv); } public static bool UsableInPlayer(ItemData it) { if (it == null || it.m_equipped) { return false; } if (SlotLocks.IsLocked(it)) { return false; } if (Api.IsSlotItem(it)) { return false; } return true; } public void Reindex() { Dirty = false; foreach (List<ItemData> value3 in _inv.Values) { value3.Clear(); } foreach (List<KeyValuePair<Inventory, ItemData>> value4 in _chest.Values) { value4.Clear(); } if (_inv.Count > 2000) { _inv.Clear(); } if (_chest.Count > 2000) { _chest.Clear(); } ChestCount = 0; Player localPlayer = Player.m_localPlayer; if ((Object)(object)localPlayer == (Object)null) { return; } _playerInv = ((Humanoid)localPlayer).GetInventory(); foreach (ItemData allItem in ((Humanoid)localPlayer).GetInventory().GetAllItems()) { if (UsableInPlayer(allItem)) { if (!_inv.TryGetValue(allItem.m_shared.m_name, out var value)) { value = (_inv[allItem.m_shared.m_name] = new List<ItemData>()); } value.Add(allItem); } } if (_chests == null) { return; } foreach (Container chest in _chests) { if (!ContainerAccess.IsValid(chest)) { continue; } Inventory inventory = chest.GetInventory(); if (inventory == null) { continue; } _watched.Add(inventory); _containerOf[inventory] = chest; ChestCount++; foreach (ItemData allItem2 in inventory.GetAllItems()) { if (!_chest.TryGetValue(allItem2.m_shared.m_name, out var value2)) { value2 = (_chest[allItem2.m_shared.m_name] = new List<KeyValuePair<Inventory, ItemData>>()); } value2.Add(new KeyValuePair<Inventory, ItemData>(inventory, allItem2)); } } } private static bool Match(ItemData it, int quality, bool matchWorldLevel) { if (quality >= 0 && it.m_quality != quality) { return false; } if (matchWorldLevel && it.m_worldLevel < Game.m_worldLevel) { return false; } return it.m_stack > 0; } public int InvCount(string name, int quality, bool mwl) { Fresh(); int num = 0; if (name != null && _inv.TryGetValue(name, out var value)) { foreach (ItemData item in value) { if (Match(item, quality, mwl)) { num += item.m_stack; } } } return num; } public int BoxCount(string name, int quality, bool mwl) { Fresh(); int num = 0; if (name != null && _chest.TryGetValue(name, out var value)) { foreach (KeyValuePair<Inventory, ItemData> item in value) { if (Ok(item.Key) && Match(item.Value, quality, mwl)) { num += item.Value.m_stack; } } } return num; } public int Count(string name, int quality, bool matchWorldLevel) { return InvCount(name, quality, matchWorldLevel) + BoxCount(name, quality, matchWorldLevel); } public bool Have(string name, bool matchWorldLevel) { return Count(name, -1, matchWorldLevel) > 0; } public ItemData Get(string name, int quality, bool isPrefabName) { Fresh(); if (name == null) { return null; } if (!isPrefabName) { if (_inv.TryGetValue(name, out var value)) { foreach (ItemData item in value) { if (Match(item, quality, matchWorldLevel: true)) { return item; } } } if (_chest.TryGetValue(name, out var value2)) { foreach (KeyValuePair<Inventory, ItemData> item2 in value2) { if (Ok(item2.Key) && Match(item2.Value, quality, matchWorldLevel: true)) { return item2.Value; } } } return null; } foreach (List<ItemData> value3 in _inv.Values) { foreach (ItemData item3 in value3) { if ((Object)(object)item3.m_dropPrefab != (Object)null && ((Object)item3.m_dropPrefab).name == name && Match(item3, quality, matchWorldLevel: true)) { return item3; } } } foreach (List<KeyValuePair<Inventory, ItemData>> value4 in _chest.Values) { foreach (KeyValuePair<Inventory, ItemData> item4 in value4) { if (Ok(item4.Key) && (Object)(object)item4.Value.m_dropPrefab != (Object)null && ((Object)item4.Value.m_dropPrefab).name == name && Match(item4.Value, quality, matchWorldLevel: true)) { return item4.Value; } } } return null; } public List<Container> ChestsToAcquire(Recipe r, int quality, int mult) { List<Container> list = new List<Container>(); if ((Object)(object)r == (Object)null || r.m_resources == null) { return list; } Fresh(); bool requireOnlyOneIngredient = r.m_requireOnlyOneIngredient; int mult2 = Math.Max(1, mult); if (requireOnlyOneIngredient) { Requirement[] resources = r.m_resources; foreach (Requirement val in resources) { int num = Amount(val, quality, mult2, onlyOne: true); if (num > 0 && OwnedCount(val.m_resItem.m_itemData.m_shared.m_name) >= num) { return list; } } Requirement[] resources2 = r.m_resources; foreach (Requirement val2 in resources2) { int num2 = Amount(val2, quality, mult2, onlyOne: true); if (num2 <= 0) { continue; } string name = val2.m_resItem.m_itemData.m_shared.m_name; int num3 = OwnedCount(name); int num4 = 0; foreach (Container chest in _chests) { if (!((Object)(object)chest == (Object)null) && !ContainerAccess.StillOwned(chest)) { Inventory inventory = chest.GetInventory(); if (inventory != null) { num4 += inventory.CountItems(name, -1, false); } } } if (num3 + num4 >= num2) { AddChestsFor(name, num2, num3, list); return list; } } return list; } Requirement[] resources3 = r.m_resources; foreach (Requirement val3 in resources3) { int num5 = Amount(val3, quality, mult2, onlyOne: false); if (num5 > 0) { string name2 = val3.m_resItem.m_itemData.m_shared.m_name; int num6 = OwnedCount(name2); if (num6 < num5) { AddChestsFor(name2, num5, num6, list); } } } return list; } private static int Amount(Requirement req, int quality, int mult, bool onlyOne) { if (req == null || (Object)(object)req.m_resItem == (Object)null) { return 0; } int num = req.GetAmount(quality); if (onlyOne) { num += Math.Max(0, req.m_extraAmountOnlyOneIngredient); } return num * mult; } private int OwnedCount(string name) { int num = 0; for (int i = 1; i <= 10; i++) { int num2 = InvCount(name, i, mwl: true); if (_chest.TryGetValue(name, out var value)) { foreach (KeyValuePair<Inventory, ItemData> item in value) { if (Match(item.Value, i, matchWorldLevel: true) && _containerOf.TryGetValue(item.Key, out var value2) && ContainerAccess.StillOwned(value2)) { num2 += item.Value.m_stack; } } } if (num2 > num) { num = num2; } } return num; } private void AddChestsFor(string name, int amount, int have, List<Container> need) { foreach (Container chest in _chests) { if (have >= amount) { break; } if ((Object)(object)chest == (Object)null || ContainerAccess.StillOwned(chest) || need.Contains(chest)) { continue; } Inventory inventory = chest.GetInventory(); if (inventory != null) { int num = inventory.CountItems(name, -1, false); if (num > 0) { need.Add(chest); have += num; } } } } public void Remove(string name, int amount, int quality, bool worldLevelBased) { Fresh(); if (amount <= 0 || name == null) { return; } int num = amount; Player localPlayer = Player.m_localPlayer; Inventory val = ((!((Object)(object)localPlayer != (Object)null)) ? null : ((Humanoid)localPlayer).GetInventory()); if (val != null && _inv.TryGetValue(name, out var value)) { foreach (ItemData item in new List<ItemData>(value)) { if (num <= 0) { break; } if (Match(item, quality, worldLevelBased) && val.ContainsItem(item)) { int num2 = Math.Min(item.m_stack, num); if (val.RemoveItem(item, num2)) { num -= num2; } } } } if (num > 0 && _chest.TryGetValue(name, out var value2)) { value2 = new List<KeyValuePair<Inventory, ItemData>>(value2); foreach (Container chest in _chests) { if (num <= 0) { break; } if (!ContainerAccess.StillOwned(chest)) { continue; } Inventory inventory = chest.GetInventory(); foreach (KeyValuePair<Inventory, ItemData> item2 in value2) { if (num <= 0) { break; } if (item2.Key != inventory) { continue; } ItemData value3 = item2.Value; if (Match(value3, quality, worldLevelBased) && inventory.ContainsItem(value3)) { int num3 = Math.Min(value3.m_stack, num); if (inventory.RemoveItem(value3, num3)) { num -= num3; } } } } } if (num > 0) { Plugin.Warn("제작: " + name + " " + num + "개를 찾지 못했습니다 (그사이 내용이 바뀜)."); } Reindex(); } } internal static class CraftBridge { private static readonly FieldInfo F_allStations = AccessTools.Field(typeof(CraftingStation), "m_allStations"); private static readonly FieldInfo F_stationNview = AccessTools.Field(typeof(CraftingStation), "m_nview"); private static readonly Func<CraftingStation, ZNetView> G_stationNview = Fast.Getter<CraftingStation, ZNetView>(F_stationNview); private static readonly FieldInfo F_haveFire = AccessTools.Field(typeof(CraftingStation), "m_haveFire"); public static IEnumerable<CraftingStation> AllStations() { IEnumerable list = ((!(F_allStations != null)) ? null : (F_allStations.GetValue(null) as IEnumerable)); if (list == null) { list = Object.FindObjectsByType<CraftingStation>((FindObjectsInactive)0, (FindObjectsSortMode)0); } IEnumerator enumerator = list.GetEnumerator(); try { while (enumerator.MoveNext()) { object o = enumerator.Current; CraftingStation s = (CraftingStation)((o is CraftingStation) ? o : null); if ((Object)(object)s != (Object)null) { yield return s; } } } finally { IDisposable disposable2; IDisposable disposable = (disposable2 = enumerator as IDisposable); if (disposable2 != null) { disposable.Dispose(); } } } public static bool IsValid(CraftingStation s) { if ((Object)(object)s == (Object)null || !((Behaviour)s).isActiveAndEnabled) { return false; } if (F_stationNview == null) { return true; } ZNetView val = (ZNetView)((G_stationNview == null) ? ((object)/*isinst with value type is only supported in some contexts*/) : ((object)G_stationNview(s))); return (Object)(object)val != (Object)null && val.IsValid(); } public static string WhyUnusable(CraftingStation s) { bool flag = false; try { flag = F_haveFire != null && (bool)F_haveFire.GetValue(s); } catch { } if (s.m_craftRequireFire && !flag) { return "불 필요"; } if (s.m_craftRequireRoof) { return "지붕 필요"; } return "사용 불가"; } } internal static class CraftSort { private sealed class IKey { public int Cat; public int Sub; public int G; public int Tab; public string Set; public float Tier; public float SetTier; public string Name; } private sealed class Key { public Recipe R; public ItemData Up; public GameObject El; public bool Can; public int Quality; public int Index; public int G; public int Tab; public int Part; public string Group; public float Tier; public string Name; public string St; public float StRank; public float Unit; } private sealed class RInfo { public int Cat; public int Sub; public int G; public int Tab; public int Part; public float Tier; public string Name; public string Group; } private static readonly Dictionary<string, float> MatTier = new Dictionary<string, float>(StringComparer.OrdinalIgnoreCase) { { "Wood", 10f }, { "Stone", 10f }, { "Flint", 10f }, { "LeatherScraps", 10f }, { "DeerHide", 10f }, { "Resin", 10f }, { "Feathers", 10f }, { "Raspberry", 10f }, { "Mushroom", 10f }, { "Honey", 10f }, { "BoneFragments", 10f }, { "NeckTail", 10f }, { "Dandelion", 10f }, { "RawMeat", 10f }, { "DeerMeat", 10f }, { "HardAntler", 15f }, { "TrophyDeer", 10f }, { "TrophyBoar", 10f }, { "GreydwarfEye", 20f }, { "Blueberries", 20f }, { "AncientSeed", 20f }, { "TrollHide", 21f }, { "Coal", 21f }, { "Thistle", 21f }, { "CarrotSeeds", 21f }, { "Carrot", 21f }, { "CopperOre", 21f }, { "TinOre", 21f }, { "Copper", 22f }, { "Tin", 22f }, { "Bronze", 23f }, { "BronzeNails", 23f }, { "FineWood", 24f }, { "CryptKey", 25f }, { "SurtlingCore", 24f }, { "BjornHide", 21f }, { "BjornMeat", 21f }, { "BjornPaw", 21f }, { "MushroomYellow", 21f }, { "RoundLog", 25f }, { "Guck", 31f }, { "Entrails", 31f }, { "Bloodbag", 31f }, { "Ooze", 31f }, { "Root", 31f }, { "TurnipSeeds", 31f }, { "Turnip", 31f }, { "WitheredBone", 31f }, { "IronScrap", 31f }, { "Iron", 32f }, { "IronNails", 32f }, { "Chain", 32f }, { "ElderBark", 33f }, { "Wishbone", 35f }, { "SerpentScale", 37f }, { "SerpentMeat", 37f }, { "Chitin", 37f }, { "SilverOre", 41f }, { "WolfPelt", 41f }, { "WolfFang", 41f }, { "Obsidian", 41f }, { "FreezeGland", 41f }, { "OnionSeeds", 41f }, { "Onion", 41f }, { "WolfMeat", 41f }, { "WolfClaw", 41f }, { "Silver", 42f }, { "Crystal", 42f }, { "JuteRed", 42f }, { "DragonEgg", 45f }, { "DragonTear", 45f }, { "TrophyHatchling", 41f }, { "Barley", 51f }, { "Flax", 51f }, { "BarleyFlour", 51f }, { "LoxPelt", 51f }, { "LoxMeat", 51f }, { "Needle", 51f }, { "Tar", 51f }, { "GoblinTotem", 51f }, { "Cloudberry", 51f }, { "BlackMetalScrap", 51f }, { "BlackMetal", 52f }, { "LinenThread", 52f }, { "YagluthDrop", 55f }, { "TrophyGoblin", 51f }, { "Carapace", 61f }, { "Sap", 61f }, { "YggdrasilWood", 61f }, { "BlackMarble", 61f }, { "ScaleHide", 61f }, { "BugMeat", 61f }, { "RoyalJelly", 61f }, { "Wisp", 61f }, { "GiantBloodSack", 61f }, { "Softtissue", 62f }, { "BlackCore", 62f }, { "JuteBlue", 62f }, { "Mandible", 62f }, { "Eitr", 63f }, { "QueenDrop", 65f }, { "MushroomJotunPuffs", 61f }, { "MushroomMagecap", 61f }, { "DvergrNeedle", 62f }, { "Bilebag", 61f }, { "FlametalOre", 71f }, { "FlametalOreNew", 71f }, { "CharredBone", 71f }, { "AskHide", 71f }, { "Blackwood", 71f }, { "Grausten", 71f }, { "Charredskull", 71f }, { "AsksvinMeat", 71f }, { "Vineberry", 71f }, { "VineberrySeeds", 71f }, { "Fiddleheadfern", 71f }, { "SulfurStone", 71f }, { "Flametal", 72f }, { "FlametalNew", 72f }, { "MoltenCore", 72f }, { "CelestialFeather", 72f }, { "ProustitePowder", 72f }, { "CeramicPlate", 72f }, { "MorgenSinew", 72f }, { "MorgenHeart", 72f }, { "BellFragment", 72f }, { "FaderDrop", 75f } }; private static readonly Dictionary<string, float> StationTier = new Dictionary<string, float>(StringComparer.OrdinalIgnoreCase) { { "piece_workbench", 10f }, { "piece_cauldron", 22f }, { "forge", 22f }, { "piece_stonecutter", 32f }, { "piece_artisanstation", 45f }, { "blackforge", 61f }, { "piece_magetable", 61f }, { "piece_preptable", 62f }, { "piece_MeadCauldron", 62f } }; private static readonly Dictionary<string, float> _tierCache = new Dictionary<string, float>(StringComparer.OrdinalIgnoreCase); private static readonly HashSet<string> _visiting = new HashSet<string>(StringComparer.OrdinalIgnoreCase); private static ObjectDB _cacheFor; private static readonly Dictionary<SharedData, IKey> _ikeys = new Dictionary<SharedData, IKey>(); private static readonly Dictionary<string, float> _setTier = new Dictionary<string, float>(); private static readonly Dictionary<Recipe, RInfo> _rinfo = new Dictionary<Recipe, RInfo>(); private static readonly FieldInfo F_list = AccessTools.Field(typeof(InventoryGui), "m_availableRecipes"); private static readonly List<Key> _keys = new List<Key>(); private static readonly List<Key> _keyPool = new List<Key>(); private static readonly Dictionary<string, float> _applySetTier = new Dictionary<string, float>(); private static readonly Comparison<Key> ByKey = delegate(Key a, Key b) { int num = Avail(a).CompareTo(Avail(b)); if (num != 0) { return num; } num = b.StRank.CompareTo(a.StRank); if (num != 0) { return num; } num = string.CompareOrdinal(a.St, b.St); if (num != 0) { return num; } num = b.Unit.CompareTo(a.Unit); if (num != 0) { return num; } num = string.CompareOrdinal(a.Group, b.Group); if (num != 0) { return num; } if (a.Group.Length > 0) { num = a.Part.CompareTo(b.Part); if (num != 0) { return num; } } num = a.G.CompareTo(b.G); if (num != 0) { return num; } if (a.G == int.MaxValue) { num = string.Compare(a.Name, b.Name, StringComparison.CurrentCulture); if (num != 0) { return num; } } num = a.Quality.CompareTo(b.Quality); return (num != 0) ? num : a.Index.CompareTo(b.Index); }; private static readonly Comparison<Key> ByCategory = delegate(Key a, Key b) { int num = Avail(a).CompareTo(Avail(b)); if (num != 0) { return num; } num = a.Tab.CompareTo(b.Tab); if (num != 0) { return num; } num = a.G.CompareTo(b.G); if (num != 0) { return num; } if (a.G == int.MaxValue) { num = b.Unit.CompareTo(a.Unit); if (num != 0) { return num; } num = string.CompareOrdinal(a.Group, b.Group); if (num != 0) { return num; } if (a.Group.Length > 0) { num = a.Part.CompareTo(b.Part); if (num != 0) { return num; } } num = string.Compare(a.Name, b.Name, StringComparison.CurrentCulture); if (num != 0) { return num; } } num = a.Quality.CompareTo(b.Quality); return (num != 0) ? num : a.Index.CompareTo(b.Index); }; private static float Tier(string prefab) { if (string.IsNullOrEmpty(prefab)) { return 0f; } if (MatTier.TryGetValue(prefab, out var value)) { return value; } if (_tierCache.TryGetValue(prefab, out value)) { return value; } if (!_visiting.Add(prefab)) { return 0f; } value = 0f; try { GameObject itemPrefab = ObjectDB.instance.GetItemPrefab(prefab); ItemDrop val = ((!((Object)(object)itemPrefab != (Object)null)) ? null : itemPrefab.GetComponent<ItemDrop>()); Recipe val2 = ((!((Object)(object)val != (Object)null)) ? null : ObjectDB.instance.GetRecipe(val.m_itemData)); if ((Object)(object)val2 != (Object)null) { value = RecipeTier(val2, 1); } } catch { } _visiting.Remove(prefab); _tierCache[prefab] = value; return value; } private static float RecipeTier(Recipe r, int quality) { float num = 0f; CraftingStation requiredStation = r.GetRequiredStation(quality); if ((Object)(object)requiredStation != (Object)null) { if (StationTier.TryGetValue(Utils.GetPrefabName(((Component)requiredStation).gameObject), out var value)) { num = value; } num += (float)Mathf.Max(0, r.GetRequiredStationLevel(quality) - 1) * 0.3f; } if (r.m_resources != null) { Requirement[] resources = r.m_resources; foreach (Requirement val in resources) { if (val == null || (Object)(object)val.m_resItem == (Object)null) { continue; } bool num2; if (quality > 1) { if (val.m_amountPerLevel > 0) { goto IL_00cb; } num2 = val.m_amount <= 0; } else { num2 = val.m_amount <= 0; } if (num2) { continue; } goto IL_00cb; IL_00cb: num = Mathf.Max(num, Tier(Utils.GetPrefabName(((Component)val.m_resItem).gameObject))); } } return num; } internal static int Category(SharedData sh, out int sub) { //IL_0004: 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) //IL_000a: 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_0072: Expected I4, but got Unknown //IL_0078: 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_007e: Unknown result type (might be due to invalid IL or missing references) //IL_0080: Unknown result type (might be due to invalid IL or missing references) //IL_00be: Expected I4, but got Unknown //IL_00be: Unknown result type (might be due to invalid IL or missing references) //IL_00c1: Invalid comparison between Unknown and I4 sub = 0; ItemType itemType = sh.m_itemType; switch (itemType - 1) { case 2: case 3: case 13: case 19: case 21: { SkillType skillType = sh.m_skillType; switch (skillType - 1) { default: if ((int)skillType == 104) { sub = 3; return 5; } sub = 30; return 0; case 0: sub = 1; return 0; case 1: sub = 2; return 0; case 6: sub = 3; return 0; case 2: sub = 4; return 0; case 4: sub = 5; return 0; case 3: sub = 6; return 0; case 10: sub = 7; return 0; case 7: sub = 10; return 0; case 13: sub = 11; return 0; case 8: sub = 20; return 0; case 9: sub = 21; return 0; case 11: sub = 1; return 5; case 12: sub = 2; return 5; } } case 4: return 1; case 5: sub = 1; return 2; case 6: sub = 2; return 2; case 10: sub = 3; return 2; case 11: sub = 4; return 2; case 16: sub = 5; return 2; case 17: sub = 1; return 3; case 23: sub = 2; return 3; case 8: case 22: return 4; case 14: case 18: return 5; case 1: return (!(sh.m_food > 0f) && !(sh.m_foodStamina > 0f) && !(sh.m_foodEitr > 0f)) ? 8 : 6; case 0: return 9; case 20: return 6; case 12: return 11; default: return 10; } } private static float ItemTier(ItemData it) { string text = ((!((Object)(object)it.m_dropPrefab != (Object)null)) ? null : ((Object)it.m_dropPrefab).name); if (!string.IsNullOrEmpty(text)) { return Tier(text); } try { Recipe recipe = ObjectDB.instance.GetRecipe(it); return (!((Object)(object)recipe != (Object)null)) ? 0f : RecipeTier(recipe, 1); } catch { return 0f; } } private static float SetTier(string set, float fallback) { if (_setTier.TryGetValue(set, out var value)) { return value; } value = fallback; try { foreach (GameObject item in ObjectDB.instance.m_items) { ItemDrop val = ((!((Object)(object)item != (Object)null)) ? null : item.GetComponent<ItemDrop>()); if (!((Object)(object)val == (Object)null) && !(val.m_itemData.m_shared.m_setName != set)) { float num = Tier(((Object)item).name); if (num > 0f && num < value) { value = num; } } } } catch { } _setTier[set] = value; return value; } private static IKey KeyOf(ItemData it) { EnsureCache(); if (_ikeys.TryGetValue(it.m_shared, out var value)) { return value; } value = new IKey(); value.Cat = Category(it.m_shared, out value.Sub); value.G = GuideOrder.Of((!((Object)(object)it.m_dropPrefab != (Object)null)) ? null : ((Object)it.m_dropPrefab).name); value.Tab = ((value.G == int.MaxValue) ? GuideOrder.TabOfCategory(value.Cat) : (value.G / 1000000)); value.Name = ContainerAccess.Localize(it.m_shared.m_name); value.Set = string.Empty; if (value.G == int.MaxValue) { value.Tier = ((!((Object)(object)ObjectDB.instance != (Object)null)) ? 0f : ItemTier(it)); value.Set = ((value.Cat != 2 || string.IsNullOrEmpty(it.m_shared.m_setName)) ? string.Empty : it.m_shared.m_setName); value.SetTier = ((value.Set.Length <= 0) ? value.Tier : SetTier(value.Set, value.Tier)); } _ikeys[it.m_shared] = value; return value; } public static int CompareItems(ItemData a, ItemData b) { IKey key = KeyOf(a); IKey key2 = KeyOf(b); int num = key.Tab.CompareTo(key2.Tab); if (num != 0) { return num; } num = key.G.CompareTo(key2.G); if (num != 0) { return num; } if (key.G != int.MaxValue) { return a.m_quality.CompareTo(b.m_quality); } num = key.Cat.CompareTo(key2.Cat); if (num != 0) { return num; } if (key.Cat == 2) { num = key2.SetTier.CompareTo(key.SetTier); if (num != 0) { return num; } num = string.CompareOrdinal(key.Set, key2.Set); if (num != 0) { return num; } num = key.Sub.CompareTo(key2.Sub); if (num != 0) { return num; } } else { num = key.Sub.CompareTo(key2.Sub); if (num != 0) { return num; } num = key2.Tier.CompareTo(key.Tier); if (num != 0) { return num; } } num = string.Compare(key.Name, key2.Name, StringComparison.CurrentCulture); if (num != 0) { return num; } return a.m_quality.CompareTo(b.m_quality); } private static void EnsureCache() { if (!((Object)(object)ObjectDB.instance == (Object)(object)_cacheFor)) { _cacheFor = ObjectDB.instance; _tierCache.Clear(); _ikeys.Clear(); _setTier.Clear(); _rinfo.Clear(); } } private static RInfo InfoOf(Recipe r) { if (_rinfo.TryGetValue(r, out var value)) { return value; } RInfo rInfo = new RInfo(); rInfo.Group = string.Empty; rInfo.Name = string.Empty; value = rInfo; SharedData shared = r.m_item.m_itemData.m_shared; value.Cat = Category(shared, out value.Sub); value.G = GuideOrder.Of(Utils.GetPrefabName(((Component)r.m_item).gameObject)); value.Tab = ((value.G == int.MaxValue) ? GuideOrder.TabOfCategory(value.Cat) : (value.G / 1000000)); value.Name = ContainerAccess.Localize(shared.m_name); string prefabName = Utils.GetPrefabName(((Component)r.m_item).gameObject); float num = GuideOrder.RankOf(prefabName); value.Tier = ((!(num >= 0f)) ? RecipeTier(r, 1) : num); if (GuideOrder.Set.TryGetValue(prefabName, out var value2)) { value.Group = value2.Key; value.Part = value2.Value; } else if (value.Cat == 2 && !string.IsNullOrEmpty(shared.m_setName)) { value.Group = shared.m_setName; value.Part = value.Sub; } _rinfo[r] = value; return value; } private static int Avail(Key k) { return CraftSearch.IsUnknown(k.R) ? 2 : ((!k.Can) ? 1 : 0); } private static float StationRank(string st) { if (GuideOrder.Station.TryGetValue(st, out var value)) { return value; } if (StationTier.TryGetValue(st, out value)) { return value; } return 0f; } public static void Apply(InventoryGui gui, bool byCategory) { //IL_03c7: Unknown result type (might be due to invalid IL or missing references) EnsureCache(); IList list = ((!(F_list != null)) ? null : (F_list.GetValue(gui) as IList)); if (list == null || list.Count < 2 || !RecipePairs.Init(list)) { return; } List<Key> keys = _keys; keys.Clear(); for (int i = 0; i < list.Count; i++) { if (_keyPool.Count <= i) { _keyPool.Add(new Key()); } Key key = _keyPool[i]; RecipePairs.Read(list, i, out key.R, out key.Up, out key.El, out key.Can); key.Index = i; key.Group = string.Empty; key.Name = string.Empty; key.Quality = 0; key.Tier = 0f; key.Part = 0; key.St = string.Empty; key.StRank = -1f; Recipe r = key.R; if ((Object)(object)r != (Object)null && (Object)(object)r.m_item != (Object)null) { RInfo rInfo = InfoOf(r); key.Tier = rInfo.Tier; key.Name = rInfo.Name; key.Group = rInfo.Group; key.G = rInfo.G; key.Tab = rInfo.Tab; key.Part = rInfo.Part; key.Quality = ((key.Up == null) ? 1 : (key.Up.m_quality + 1)); CraftingStation val = null; try { val = r.GetRequiredStation(key.Quality); } catch { } if ((Object)(object)val != (Object)null) { key.St = Utils.GetPrefabName(((Component)val).gameObject); key.StRank = StationRank(key.St); } } else { key.G = int.MaxValue; key.Tab = 99; } keys.Add(key); } Dictionary<string, float> applySetTier = _applySetTier; applySetTier.Clear(); for (int j = 0; j < keys.Count; j++) { Key key2 = keys[j]; if (key2.Group.Length != 0) { string key3 = key2.St + "\u0001" + key2.Group; applySetTier[key3] = ((!applySetTier.TryGetValue(key3, out var value)) ? key2.Tier : Mathf.Max(value, key2.Tier)); } } for (int k = 0; k < keys.Count; k++) { Key key4 = keys[k]; key4.Unit = ((key4.Group.Length <= 0) ? key4.Tier : applySetTier[key4.St + "\u0001" + key4.Group]); } keys.Sort((!byCategory) ? ByKey : ByCategory); float recipeListSpace = gui.m_recipeListSpace; for (int l = 0; l < keys.Count; l++) { Key key5 = keys[l]; if (key5.Index != l) { RecipePairs.Write(list, l, key5.R, key5.Up, key5.El, key5.Can); } RectTransform val2 = (RectTransform)((!((Object)(object)key5.El != (Object)null)) ? null : /*isinst with value type is only supported in some contexts*/); if ((Object)(object)val2 != (Object)null) { val2.anchoredPosition = new Vector2(0f, (float)l * (0f - recipeListSpace)); } key5.R = null; key5.Up = null; key5.El = null; } keys.Clear(); } } internal static class RecipePairs { public delegate void ReadFn(object list, int i, out Recipe r, out ItemData it, out GameObject el, out bool can); public delegate void WriteFn(object list, int i, Recipe r, ItemData it, GameObject el, bool can); public static ReadFn Read; public static WriteFn Write; private static Type _for; public static bool Init(IList list) { if (list == null) { return false; } Type type = list.GetType(); if (type == _for) { return Read != null && Write != null; } _for = type; Read = null; Write = null; Type type2 = (type.IsGenericType ? type.GetGenericArguments()[0] : ((list.Count <= 0 || list[0] == null) ? null : list[0].GetType())); if (type2 == null) { _for = null; return false; } PropertyInfo property = type2.GetProperty("Recipe"); PropertyInfo property2 = type2.GetProperty("ItemData"); PropertyInfo property3 = type2.GetProperty("InterfaceElement"); PropertyInfo property4 = type2.GetProperty("CanCraft"); ConstructorInfo constructor = type2.GetConstructor(new Type[4] { typeof(Recipe), typeof(ItemData), typeof(GameObject), typeof(bool) }); if (property == null || property3 == null || property4 == null || constructor == null) { return false; } try { Emit(type, type2, property, property2, property3, property4, constructor); } catch { Read = null; Write = null; } if (Read == null || Write == null) { Fallback(property, property2, property3, property4, constructor); } return Read != null && Write != null; } private static void Emit(Type lt, Type pt, PropertyInfo pR, PropertyInfo pI, PropertyInfo pE, PropertyInfo pC, ConstructorInfo ctor) { if (lt.IsGenericType && pt.IsValueType && !(pI == null)) { MethodInfo method = lt.GetMethod("get_Item", new Type[1] { typeof(int) }); MethodInfo method2 = lt.GetMethod("set_Item", new Type[2] { typeof(int), pt }); MethodInfo getMethod = pR.GetGetMethod(nonPublic: true); MethodInfo getMethod2 = pI.GetGetMethod(nonPublic: true); MethodInfo getMethod3 = pE.GetGetMethod(nonPublic: true); MethodInfo getMethod4 = pC.GetGetMethod(nonPublic: true); if (!(method == null) && !(method2 == null) && !(getMethod == null) && !(getMethod2 == null) && !(getMethod3 == null) && !(getMethod4 == null) && !(getMethod.ReturnType != typeof(Recipe)) && !(getMethod2.ReturnType != typeof(ItemData)) && !(getMethod3.ReturnType != typeof(GameObject)) && !(getMethod4.ReturnType != typeof(bool))) { DynamicMethod dynamicMethod = new DynamicMethod("HutoPairRead", null, new Type[6] { typeof(object), typeof(int), typeof(Recipe).MakeByRefType(), typeof(ItemData).MakeByRefType(), typeof(GameObject).MakeByRefType(), typeof(bool).MakeByRefType() }, typeof(RecipePairs).Module, skipVisibility: true); ILGenerator iLGenerator = dynamicMethod.GetILGenerator(); iLGenerator.DeclareLocal(pt); iLGenerator.Emit(OpCodes.Ldarg_0); iLGenerator.Emit(OpCodes.Castclass, lt); iLGenerator.Emit(OpCodes.Ldarg_1); iLGenerator.Emit(OpCodes.Callvirt, method); iLGenerator.Emit(OpCodes.Stloc_0); iLGenerator.Emit(OpCodes.Ldarg_2); iLGenerator.Emit(OpCodes.Ldloca_S, (byte)0); iLGenerator.Emit(OpCodes.Call, getMethod); iLGenerator.Emit(OpCodes.Stind_Ref); iLGenerator.Emit(OpCodes.Ldarg_3); iLGenerator.Emit(OpCodes.Ldloca_S, (byte)0); iLGenerator.Emit(OpCodes.Call, getMethod2); iLGenerator.Emit(OpCodes.Stind_Ref); iLGenerator.Emit(OpCodes.Ldarg_S, (byte)4); iLGenerator.Emit(OpCodes.Ldloca_S, (byte)0); iLGenerator.Emit(OpCodes.Call, getMethod3); iLGenerator.Emit(OpCodes.Stind_Ref); iLGenerator.Emit(OpCodes.Ldarg_S, (byte)5); iLGenerator.Emit(OpCodes.Ldloca_S, (byte)0); iLGenerator.Emit(OpCodes.Call, getMethod4); iLGenerator.Emit(OpCodes.Stind_I1); iLGenerator.Emit(OpCodes.Ret); ReadFn read = (ReadFn)dynamicMethod.CreateDelegate(typeof(ReadFn)); DynamicMethod dynamicMethod2 = new DynamicMethod("HutoPairWrite", null, new Type[6] { typeof(object), typeof(int), typeof(Recipe), typeof(ItemData), typeof(GameObject), typeof(bool) }, typeof(RecipePairs).Module, skipVisibility: true); iLGenerator = dynamicMethod2.GetILGenerator(); iLGenerator.Emit(OpCodes.Ldarg_0); iLGenerator.Emit(OpCodes.Castclass, lt); iLGenerator.Emit(OpCodes.Ldarg_1); iLGenerator.Emit(OpCodes.Ldarg_2); iLGenerator.Emit(OpCodes.Ldarg_3); iLGenerator.Emit(OpCodes.Ldarg_S, (byte)4); iLGenerator.Emit(OpCodes.Ldarg_S, (byte)5); iLGenerator.Emit(OpCodes.Newobj, ctor); iLGenerator.Emit(OpCodes.Callvirt, method2); iLGenerator.Emit(OpCodes.Ret); WriteFn write = (WriteFn)dynamicMethod2.CreateDelegate(typeof(WriteFn)); Read = read; Write = write; } } } private static void Fallback(PropertyInfo pR, PropertyInfo pI, PropertyInfo pE, PropertyInfo pC, ConstructorInfo ctor) { Read = delegate(object l, int i, out Recipe r, out ItemData it, out GameObject el, out bool can) { object obj = ((IList)l)[i]; object? value = pR.GetValue(obj, null); r = (Recipe)((value is Recipe) ? value : null); it = (ItemData)((!(pI != null)) ? null : /*isinst with value type is only supported in some contexts*/); object? value2 = pE.GetValue(obj, null); el = (GameObject)((value2 is GameObject) ? value2 : null); can = (bool)pC.GetValue(obj, null); }; Write = delegate(object l, int i, Recipe r, ItemData it, GameObject el, bool can) { ((IList)l)[i] = ctor.Invoke(new object[4] { r, it, el, can }); }; } } [HarmonyPatch(typeof(InventoryGui), "UpdateRecipeList")] internal static class P_CraftSort_UpdateRecipeList { private static void Postfix(InventoryGui __instance) { try { Player localPlayer = Player.m_localPlayer; if (!((Object)(object)localPlayer == (Object)null) && !RecipeReuse.Skipped) { StorageWindow window = Plugin.Window; if (window != null && window.CraftActive && NearbyCraft.Virtual(localPlayer)) { CraftSort.Apply(__instance, byCategory: false); } } } catch (Exception e) { StorageWindow.WarnOnce("제작 목록 정렬", e); } } } [HarmonyPatch(typeof(Inventory), "StackAll")] internal static class Patch_Inventory_StackAll { private static readonly FieldInfo F_items = AccessTools.Field(typeof(Inventory), "m_inventory"); private static void Prefix(Inventory fromInventory, out List<ItemData> __state) { __state = null; try { Player localPlayer = Player.m_localPlayer; if ((Object)(object)localPlayer == (Object)null || fromInventory == null || fromInventory != ((Humanoid)localPlayer).GetInventory() || SlotLocks.Count() == 0 || !(F_items.GetValue(fromInventory) is List<ItemData> list)) { return; } __state = list.FindAll(SlotLocks.IsLocked); if (__state.Count == 0) { __state = null; return; } foreach (ItemData item in __state) { list.Remove(item); } } catch { __state = null; } } private static void Finalizer(Inventory fromInventory, List<ItemData> __state) { if (__state == null) { return; } try { if (!(F_items.GetValue(fromInventory) is List<ItemData> list)) { return; } foreach (ItemData item in __state) { if (!list.Contains(item)) { list.Add(item); } } MethodInfo m_changed = InvBatch.M_changed; if (m_changed != null) { m_changed.Invoke(fromInventory, (m_changed.GetParameters().Length != 2) ? new object[0] : new object[2] { true, false }); } } catch { } } } internal static class CraftSearch { public static bool Focused; private static int _rectFrame = -1; private static bool _rectOk; private static Rect _cr; private static Rect _tr; private static string _q = string.Empty; private static string _applied = string.Empty; private static GUIStyle _field; private static GUIStyle _ph; private static readonly MethodInfo M_updatePanel = AccessTools.Method(typeof(InventoryGui), "UpdateCraftingPanel", new Type[1] { typeof(bool) }, (Type[])null); private static int _tipFrame = -1; private static bool _tipCovers; private static readonly Dictionary<string, string> _names = new Dictionary<string, string>(); private static readonly HashSet<Recipe> _unknown = new HashSet<Recipe>(); private static readonly FieldInfo F_avail = AccessTools.Field(typeof(InventoryGui), "m_availableRecipes"); private static readonly Color FrameColor = Color32.op_Implicit(new Color32((byte)110, (byte)82, (byte)50, byte.MaxValue)); private static bool Active => Plugin.Window?.IsOpen ?? false; public static string Query => (!Active) ? string.Empty : (_q ?? string.Empty).Trim(); private static string L(string t) { if (t == null) { return string.Empty; } if (_names.TryGetValue(t, out var value)) { return value; } value = ContainerAccess.Localize(t) ?? t; if (_names.Count > 4096) { _names.Clear(); } _names[t] = value; return value; } public static void Filter(List<Recipe> recipes) { string q = Query; _applied = q; _unknown.Clear(); if (q.Length == 0 || recipes == null) { return; } recipes.RemoveAll((Recipe r) => (Object)(object)r == (Object)null || (Object)(object)r.m_item == (Object)null || L(r.m_item.m_itemData.m_shared.m_name).IndexOf(q, StringComparison.OrdinalIgnoreCase) < 0); InventoryGui instance = InventoryGui.instance; Player localPlayer = Player.m_localPlayer; if ((Object)(object)instance == (Object)null || (Object)(object)localPlayer == (Object)null || (Object)(object)ObjectDB.instance == (Object)null || !instance.InCraftTab()) { return; } HashSet<Recipe> hashSet = new HashSet<Recipe>(recipes); foreach (Recipe recipe in ObjectDB.instance.m_recipes) { if ((Object)(object)recipe == (Object)null || !recipe.m_enabled || (Object)(object)recipe.m_item == (Object)null || hashSet.Contains(recipe)) { continue; } SharedData shared = recipe.m_item.m_itemData.m_shared; if (string.IsNullOrEmpty(shared.m_dlc) && !localPlayer.IsRecipeKnown(shared.m_name) && L(shared.m_name).IndexOf(q, StringComparison.OrdinalIgnoreCase) >= 0) { bool flag; try { flag = localPlayer.RequiredCraftingStation(recipe, 1, false); } catch { flag = false; } if (flag) { recipes.Add(recipe); _unknown.Add(recipe); } } } } public static bool IsUnknown(Recipe r) { return (Object)(object)r != (Object)null && _unknown.Count > 0 && _unknown.Contains(r); } public static void MarkUnknown(InventoryGui gui) { if (_unknown.Count == 0 || (Object)(object)gui == (Object)null || F_avail == null || !(F_avail.GetValue(gui) is IList list) || !RecipePairs.Init(list)) { return; } for (int i = 0; i < list.Count; i++) { RecipePairs.Read(list, i, out var r, out var _, out var el, out var _); if (!((Object)(object)r == (Object)null) && !((Object)(object)el == (Object)null) && _unknown.Contains(r)) { Transform val = el.transform.Find("name"); TMP_Text val2 = ((!((Object)(object)val != (Object)null)) ? null : ((Component)val).GetComponent<TMP_Text>()); if ((Object)(object)val2 != (Object)null && val2.text.IndexOf("(미습득)", StringComparison.Ordinal) < 0) { val2.text += " <color=#a08060>(미습득)</color>"; } } } } private static void DrawFrame(Rect r, float t) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0005: 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_0038: 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_0086: Unknown result type (might be due to invalid IL or missing references) //IL_00a7: Unknown result type (might be due to invalid IL or missing references) //IL_00b2: Unknown result type (might be due to invalid IL or missing references) Color color = GUI.color; GUI.color = FrameColor; Texture2D whiteTexture = Texture2D.whiteTexture; GUI.DrawTexture(new Rect(((Rect)(ref r)).x - t, ((Rect)(ref r)).y - t, ((Rect)(ref r)).width + 2f * t, t), (Texture)(object)whiteTexture); GUI.DrawTexture(new Rect(((Rect)(ref r)).x - t, ((Rect)(ref r)).yMax, ((Rect)(ref r)).width + 2f * t, t), (Texture)(object)whiteTexture); GUI.DrawTexture(new Rect(((Rect)(ref r)).x - t, ((Rect)(ref r)).y, t, ((Rect)(ref r)).height), (Texture)(object)whiteTexture); GUI.DrawTexture(new Rect(((Rect)(ref r)).xMax, ((Rect)(ref r)).y, t, ((Rect)(ref r)).height), (Texture)(object)whiteTexture); GUI.color = color; } public static void OnGUI() { //IL_03cc: Unknown result type (might be due to invalid IL or missing references) //IL_03d2: Invalid comparison between Unknown and I4 //IL_0120: Unknown result type (might be due to invalid IL or missing references) //IL_0125: Unknown result type (might be due to invalid IL or missing references) //IL_0126: Unknown result type (might be due to invalid IL or missing references) //IL_012b: Unknown result type (might be due to invalid IL or missing references) //IL_013f: Unknown result type (might be due to invalid IL or missing references) //IL_0144: Unknown result type (might be due to invalid IL or missing references) //IL_01fc: Unknown result type (might be due to invalid IL or missing references) //IL_028e: Unknown result type (might be due to invalid IL or missing references) //IL_0294: Invalid comparison between Unknown and I4 //IL_0231: Unknown result type (might be due to invalid IL or missing references) //IL_023b: Expected O, but got Unknown //IL_0240: Unknown result type (might be due to invalid IL or missing references) //IL_024a: Expected O, but got Unknown //IL_02af: 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) //IL_0314: Unknown result type (might be due to invalid IL or missing references) //IL_031a: Invalid comparison between Unknown and I4 //IL_02fa: Unknown result type (might be due to invalid IL or missing references) //IL_0373: Unknown result type (might be due to invalid IL or missing references) //IL_0321: Unknown result type (might be due to invalid IL or missing references) //IL_0328: Invalid comparison between Unknown and I4 //IL_0381: Unknown result type (might be due to invalid IL or missing references) //IL_032f: Unknown result type (might be due to invalid IL or missing references) //IL_0336: Invalid comparison between Unknown and I4 //IL_033d: Unknown result type (might be due to invalid IL or missing references) //IL_0347: Invalid comparison between Unknown and I4 //IL_034e: Unknown result type (might be due to invalid IL or missing references) //IL_0355: Invalid comparison between Unknown and I4 InventoryGui instance = InventoryGui.instance; if ((Object)(object)instance == (Object)null || !Active || !InventoryGui.IsVisible() || (Object)(object)instance.m_crafting == (Object)null || !((Component)instance.m_crafting).gameObject.activeInHierarchy) { if (Focused) { Focused = false; try { Input.imeCompositionMode = (IMECompositionMode)0; } catch { } } if ((Object)(object)instance == (Object)null || !Active || !InventoryGui.IsVisible()) { _q = string.Empty; _applied = string.Empty; } return; } int frameCount = Time.frameCount; if (frameCount != _rectFrame) { _rectFrame = frameCount; RectTransform val = (RectTransform)((!((Object)(object)instance.m_tabUpgrade != (Object)null)) ? null : /*isinst with value type is only supported in some contexts*/); _rectOk = StorageWindow.ScreenRect(instance.m_crafting, out _cr) && (Object)(object)val != (Object)null && StorageWindow.ScreenRect(val, out _tr); } if (!_rectOk) { return; } Rect cr = _cr; Rect tr = _tr; float width = ((Rect)(ref cr)).width; Rect rect = instance.m_crafting.rect; float num = width / Mathf.Max(1f, ((Rect)(ref rect)).width); float num2 = 8f * num; float num3 = ((Rect)(ref tr)).xMax + num2; float num4 = ((Rect)(ref cr)).xMax - 44f * num; if (num4 - num3 < 60f * num) { return; } float num5 = Mathf.Round(((Rect)(ref tr)).height * 0.7f); float num6 = ((Rect)(ref tr)).height * 0.47f; Rect val2 = default(Rect); ((Rect)(ref val2))..ctor(num3, Mathf.Round((float)Screen.height - ((Rect)(ref tr)).yMax + num6 - num5 * 0.5f), num4 - num3, num5); int frameCount2 = Time.frameCount; if (frameCount2 != _tipFrame) { _tipFrame = frameCount2; _tipCovers = StorageWindow.TooltipCoversCore(val2); } if (!Focused && _tipCovers) { return; } UiSkin.Ensure(); if (_field == null) { _field = new GUIStyle(UiSkin.FieldStyle); _ph = new GUIStyle(UiSkin.Placeholder); _ph.fontStyle = (FontStyle)0; } GUIStyle field = _field; int fontSize = Mathf.Clamp(Mathf.RoundToInt(num5 * 0.55f), 11, 22); _ph.fontSize = fontSize; field.fontSize = fontSize; Event current = Event.current; if ((int)current.type == 7) { DrawFrame(val2, 1f); } GUI.SetNextControlName("hutoheim_craftsearch"); _q = GUI.TextField(val2, _q ?? string.Empty, 40, _field); bool flag = GUI.GetNameOfFocusedControl() == "hutoheim_craftsearch"; if (string.IsNullOrEmpty(_q) && !flag) { GUI.Label(val2, "레시피 검색…", _ph); } if (flag && (int)current.type == 4 && ((int)current.keyCode == 27 || (int)current.keyCode == 13 || (int)current.keyCode == 271 || (int)current.keyCode == 9)) { GUI.FocusControl((string)null); current.Use(); flag = false; } if (flag && (int)current.type == 0 && !((Rect)(ref val2)).Contains(current.mousePosition)) { GUI.FocusControl((string)null); flag = false; } if (flag != Focused) { try { Input.imeCompositionMode = (IMECompositionMode)(flag ? 1 : 0); } catch { } } Focused = flag; if ((int)current.type != 7 || !(Query != _applied) || !(M_updatePanel != null)) { return; } _applied = Query; try { M_updatePanel.Invoke(instance, new object[1] { false }); } catch { } } } [HarmonyPatch(typeof(InventoryGui), "UpdateRecipeList")] internal static class P_CraftSearch_UpdateRecipeList { [HarmonyPriority(200)] private static void Prefix(List<Recipe> recipes) { try { CraftSearch.Filter(recipes); } catch { } } [HarmonyPriority(0)] private static void Postfix(InventoryGui __instance) { try { CraftSearch.MarkUnknown(__instance); } catch { } } } [HarmonyPatch(typeof(InventoryGui), "SetupRequirement")] internal static class P_Requirement_Unknown { private const string Child = "Hutoheim_unknown"; private static readonly FieldInfo F_known = AccessTools.Field(typeof(Player), "m_knownMaterial"); private static readonly Func<Player, HashSet<string>> G_known = Fast.Getter<Player, HashSet<string>>(F_known); private static void Postfix(Transform elementRoot, Requirement req, Player player) { //IL_01c8: Unknown result type (might be due to invalid IL or missing references) //IL_01cd: Unknown result type (might be due to invalid IL or missing references) //IL_013f: Unknown result type (might be due to invalid IL or missing references) //IL_0144: Unknown result type (might be due to invalid IL or missing references) //IL_0158: Unknown result type (might be due to invalid IL or missing references) //IL_016a: Unknown result type (might be due to invalid IL or missing references) //IL_016f: Unknown result type (might be due to invalid IL or missing references) try { if ((Object)(object)elementRoot == (Object)null) { return; } Transform val = elementRoot.Find("Hutoheim_unknown"); bool flag = false; if (req != null && (Object)(object)req.m_resItem != (Object)null && (Object)(object)player != (Object)null && ((Component)elementRoot).gameObject.activeSelf && G_known != null) { HashSet<string> hashSet = G_known(player); flag = hashSet != null && !hashSet.Contains(req.m_resItem.m_itemData.m_shared.m_name); } if (!flag) { if ((Object)(object)val != (Object)null && ((Component)val).gameObject.activeSelf) { ((Component)val).gameObject.SetActive(false); } return; } if ((Object)(object)val == (Object)null) { Transform val2 = elementRoot.Find("res_amount"); if ((Object)(object)val2 == (Object)null) { return; } GameObject val3 = Object.Instantiate<GameObject>(((Component)val2).gameObject, elementRoot); ((Object)val3).name = "Hutoheim_unknown"; val = val3.transform; RectTransform val4 = (RectTransform)(object)((val2 is RectTransform) ? val2 : null); RectTransform val5 = (RectTransform)(object)((val is RectTransform) ? val : null); if ((Object)(object)val4 != (Object)null && (Object)(object)val5 != (Object)null) { Rect rect = val4.rect; float num = Mathf.Max(10f, ((Rect)(ref rect)).height); val5.anchoredPosition = val4.anchoredPosition + new Vector2(0f, num * 0.8f); } TMP_Text component = val3.GetComponent<TMP_Text>(); if ((Object)(object)component != (Object)null) { component.enableAutoSizing = false; component.fontSize = Mathf.Max(9f, component.fontSize * 0.7f); ((Graphic)component).color = Color32.op_Implicit(new Color32(byte.MaxValue, (byte)170, (byte)90, byte.MaxValue)); ((Graphic)component).raycastTarget = false; } } TMP_Text component2 = ((Component)val).GetComponent<TMP_Text>(); if ((Object)(object)component2 != (Object)null && component2.text != "미습득") { component2.text = "미습득"; } if (!((Component)val).gameObject.activeSelf) { ((Component)val).gameObject.SetActive(true); } } catch { } } } [HarmonyPatch(typeof(InventoryGui), "HideRequirement")] internal static class P_Requirement_Unknown_Hide { private static void Postfix(Transform elementRoot) { try { Transform val = ((!((Object)(object)elementRoot != (Object)null)) ? null : elementRoot.Find("Hutoheim_unknown")); if ((Object)(object)val != (Object)null && ((Component)val).gameObject.activeSelf) { ((Component)val).gameObject.SetActive(false); } } catch { } } } internal static class SlotLocks { private const string StoreKey = "slotlocks"; private static HashSet<int> _set; private static string _setFor; public static int Version; private static int Pack(int x, int y) { return y * 1000 + x; } private static HashSet<int> Parse(string v) { HashSet<int> hashSet = new HashSet<int>(); if (string.IsNullOrEmpty(v)) { return hashSet; } string[] array = v.Split(new char[1] { ';' }); foreach (string text in array) { string[] array2 = text.Split(new char[1] { ',' }); if (array2.Length == 2 && int.TryParse(array2[0], out var result) && int.TryParse(array2[1], out var result2)) { hashSet.Add(Pack(result, result2)); } } return hashSet; } private static void Save() { if (_set == null || _setFor == null) { return; } List<string> list = new List<string>(); foreach (int item in _set) { list.Add(item % 1000 + "," + item / 1000); } CharStore.Set("slotlocks", string.Join(";", list.ToArray())); } private static HashSet<int> Current(bool create) { string text = CharStore.CharId(); if (text == null || (Object)(object)Player.m_localPlayer == (Object)null) { return null; } if (!CharStore.Readable) { return null; } if (_set == null || text != _setFor) { _set = Parse(CharStore.Get("slotlocks")); _setFor = text; Version++; } return _set; } public static bool IsLocked(int x, int y) { return Current(create: false)?.Contains(Pack(x, y)) ?? false; } public static bool IsLocked(ItemData it) { return it != null && IsLocked(it.m_gridPos.x, it.m_gridPos.y); } public static bool Toggle(int x, int y) { HashSet<int> hashSet = Current(create: true); if (hashSet == null) { return false; } int item = Pack(x, y); bool flag = !hashSet.Remove(item); if (flag) { hashSet.Add(item); } Version++; Save(); if (CraftChests.Override is MaterialPool materialPool) { materialPool.Dirty = true; } return flag; } public static int Count() { return Current(create: false)?.Count ?? 0; } } public class StorageWindow { private sealed class Deposited { public Container C; public string Key; public int Count; public Vector2i Pos; } private class PendingOp { public List<Container> Chests; public Action Act; public float Start; public float Deadline; public int Session; } private class CStation { public string Key; public string Name; public CraftingStation Best; public int Level; public int MaxLevel; public int Count; public string Why; public int WhyOrder = -1; } private struct Cand { public CStation Info; public CraftingStation S; public int Level; public float D2; public int Order; } private enum Mode { One, Stack, All } private class Entry { public string Key; public string Name; public ItemData Sample; public int Total; public int Chests; } private struct KeyCache { public string Name; public string Key; public int Q; public int V; public int W; } private class HeldItem { public string Key; public ItemData Sample; public int Amount; } private List<Deposited> _undo; private int _undoSig; private float _nextUndoCheck; internal static readonly FieldInfo F_containerGrid = AccessTools.Field(typeof(InventoryGui), "m_containerGrid"); internal static readonly FieldInfo F_dragGo = AccessTools.Field(typeof(InventoryGui), "m_dragGo"); internal static readonly FieldInfo F_dragItem = AccessTools.Field(typeof(InventoryGui), "m_dragItem"); internal static readonly FieldInfo F_dragInv = AccessTools.Field(typeof(InventoryGui), "m_dragInventory"); internal static readonly FieldInfo F_dragAmount = AccessTools.Field(typeof(InventoryGui), "m_dragAmount"); internal static readonly MethodInfo M_setupDrag = AccessTools.Method(typeof(InventoryGui), "SetupDragItem", new Type[3] { typeof(ItemData), typeof(Inventory), typeof(int) }, (Type[])null); private static readonly FieldInfo F_firstContainerUpdate = AccessTools.Field(typeof(InventoryGui), "m_firstContainerUpdate"); private static readonly FieldInfo F_invList = AccessTools.Field(typeof(Inventory), "m_inventory"); private static readonly FieldInfo F_elements = AccessTools.Field(typeof(InventoryGrid), "m_elements"); private static readonly Func<InventoryGrid, IList> G_elements = Fast.Getter<InventoryGrid, IList>(F_elements); private static readonly Func<InventoryGui, InventoryGrid> G_containerGrid = Fast.Getter<InventoryGui, InventoryGrid>(F_containerGrid); private static readonly Func<Inventory, List<ItemData>> G_invList = Fast.Getter<Inventory, List<ItemData>>(F_invList); private static readonly Func<InventoryGui, Inventory> G_dragInv = Fast.Getter<InventoryGui, Inventory>(F_dragInv); public const int VCols = 8; public const int VRows = 6; private static readonly FieldInfo F_invHeight = AccessTools.Field(typeof(Inventory), "m_height"); private Inventory _vinv; private readonly Dictionary<string, ItemData> _clones = new Dictionary<string, ItemData>(); private readonly Dictionary<ItemData, string> _cloneKey = new Dictionary<ItemData, string>(); private string _dragKey; private bool _showingSelf; public static bool SearchFocused; private static bool _warnedPanel; private int _scrollRow; private int _vinvVersion; private int _drawnVersion = -1; private bool _allowShrink; private ItemData _drawnDrag; private float _openedAt; private int _fitOk; private Vector2i _drawnSel; private bool _drawnSelValid; private InventoryElement _drawnHover; private static readonly MethodInfo M_hovered = AccessTools.Method(typeof(InventoryGrid), "GetHoveredElement", (Type[])null, (Type[])null); private static Func<InventoryGrid, InventoryElement> _hovered; private Vector3 _hovMouse; private Vector3 _hovRoot; private int _hovVersion = -1; private InventoryGrid _hovGrid; private InventoryElement _hovLast; private static readonly Func<InventoryGrid, Inventory> G_gridInv = Fast.Getter<InventoryGrid, Inventory>(AccessTools.Field(typeof(InventoryGrid), "m_inventory")); private static readonly Action<InventoryGrid> _gamepad = MakeGamepad(); private static readonly MethodInfo M_createTooltip = AccessTools.Method(typeof(InventoryGrid), "CreateItemTooltip", (Type[])null, (Type[])null); private static readonly FieldInfo F_elTooltip = AccessTools.Field(typeof(InventoryElement), "m_tooltip"); private readonly object[] _tipArgs = new object[2]; private static readonly Func<InventoryGui, ItemData> G_dragItem = Fast.Getter<InventoryGui, ItemData>(F_dragItem); private static readonly Func<InventoryGui, bool> G_firstContainerUpdate = Fast.Getter<InventoryGui, bool>(F_firstContainerUpdate); private static readonly Func<InventoryGrid, Vector2i> G_gridSelected = Fast.Getter<InventoryGrid, Vector2i>(AccessTools.Field(typeof(InventoryGrid), "m_selected")); private readonly Dictionary<ItemData, KeyValuePair<int, string>> _countText = new Dictionary<ItemData, KeyValuePair<int, string>>(); private static readonly Vector3[] _screenCorners = (Vector3[])(object)new Vector3[4]; private static readonly Dictionary<RectTransform, Canvas> _rootCanvas = new Dictionary<RectTransform, Canvas>(); private TMP_Text _stationLine; private readonly Button[] _barBtn = (Button[])(object)new Button[3]; private readonly TMP_Text[] _barTxt = (TMP_Text[])(object)new TMP_Text[3]; private InventoryGui _extrasFor; private bool _vanillaBtnHidden; private const float BarGap = 8f; private const float BarTop = 10f; private static readonly bool StationLineEnabled = false; private readonly List<KeyValuePair<RectTransform, Vector2>> _grown = new List<KeyValuePair<RectTransform, Vector2>>(); private static readonly FieldInfo F_gridWidth = AccessTools.Field(typeof(InventoryGrid), "m_width"); private InventoryGrid _swappedGrid; private GameObject _origPrefab; private float _origSpace; private bool _hasOrigBottom; private Vector2 _origBottom; private float _extra; private float _shrink; private Scrollbar _sbFor; private Vector2 _sbAMin; private Vector2 _sbAMax; private Vector2 _sbPivot; private Vector2 _sbPos; private Vector2 _sbSize; private ScrollRect _srFor; private Scrollbar _srBar; private bool _srVertical; private bool _sbSetting; private Scrollbar _sbHooked; private int _sbRow = -1; private int _sbMax = -1; private static GUIStyle _field; private static GUIStyle _ph; private static FieldInfo[] _tipFields; private static int _tipFrame = -1; private static Rect _tipRect; private static bool _tipResult; private static readonly List<CanvasGroup> _cgTmp = new List<CanvasGroup>(); private static int _alphaFrame = -1; private static float _alpha = 1f; private readonly List<ItemData> _wornTmp = new List<ItemData>(); private static readonly Dictionary<string, Recipe> _recipeOf = new Dictionary<string, Recipe>(); private static ObjectDB _recipeDb; private static int _recipeCount = -1; private const float SlideTime = 0.2f; private const float CloseTime = 0.15f; private bool _slideOn; private bool _hasRest; private Vector3 _restTL; private Vector3 _appliedLocal; private RectTransform _slideRt; private readonly Vector3[] _corners = (Vector3[])(object)new Vector3[4]; private readonly Vector3[] _bc = (Vector3[])(object)new Vector3[4]; private Vector3 _lastTL; private int _stable; private float _openT = -1f; private float _closeT = -1f; private bool _wasOpen; private const string PrefKey = "Hutoheim.ChestPanelRest"; private int _idleStable; private Vector3 _idleLast; private static readonly Vector3[] _canvasCorners = (Vector3[])(object)new Vector3[4]; private const float AcquireTimeout = 1.5f; private readonly List<PendingOp> _ops = new List<PendingOp>(); private static readonly FieldInfo F_gRecipe = AccessTools.Field(typeof(InventoryGui), "m_craftRecipe"); private static readonly FieldInfo F_gUpgrade = AccessTools.Field(typeof(InventoryGui), "m_craftUpgradeItem"); private static readonly FieldInfo F_gMulti = AccessTools.Field(typeof(InventoryGui), "m_multiCrafting"); private static readonly MethodInfo M_gDoCrafting = AccessTools.Method(typeof(InventoryGui), "DoCrafting", new Type[1] { typeof(Player) }, (Type[])null); private bool _craftWaiting; private bool _craftDeferred; private int _craftWaitSession; private int _craftToken; private readonly List<Cand> _cands = new List<Cand>(); private float _stationNext; private bool _craftPanelDirty; private bool _craftFullDirty = true; private float _nextCraftRefresh; private string _stationSig = string.Empty; private MaterialPool _pool; private readonly Dictionary<string, CStation> _stations = new Dictionary<string, CStation>(); private readonly List<CStation> _stationList = new List<CStation>(); private readonly List<string> _missingStations = new List<string>(); private static readonly MethodInfo M_updateCraftingPanel = AccessTools.Method(typeof(InventoryGui), "UpdateCraftingPanel", new Type[1] { typeof(bool) }, (Type[])null); private static readonly FieldInfo F_craftTimer = AccessTools.Field(typeof(InventoryGui), "m_craftTimer"); private static readonly Func<InventoryGui, float> G_craftTimer = Fast.Getter<InventoryGui, float>(F_craftTimer); private static readonly FieldInfo F_knownRecipes = AccessTools.Field(typeof(Player), "m_knownRecipes"); private static readonly Func<Player, HashSet<string>> G_knownRecipes = Fast.Getter<Player, HashSet<string>>(F_knownRecipes); private int _knownCount = -1; private const float UsableTtl = 5f; private static readonly Dictionary<int, KeyValuePair<float, bool>> _usable = new Dictionary<int, KeyValuePair<float, bool>>(); private long _poolSig; private readonly List<Container> _opened = new List<Container>(); private readonly List<Entry> _entries = new List<Entry>(); private readonly Queue<Action> _actions = new Queue<Action>(); private Vector3 _origin; private List<Vector3> _area = new List<Vector3>(); private int _session; private bool _dirty; private float _nextRebuild; private string _search = string.Empty; private string _lastSearch = string.Empty; private readonly Dictionary<string, Entry> _map = new Dictionary<string, Entry>(); private readonly HashSet<string> _seen = new HashSet<string>(); private readonly List<Entry> _nextEntries = new List<Entry>(); private long _contentSig = long.MinValue; private Vector3 _sortedAt = new Vector3(float.MaxValue, 0f, 0f); private static readonly Func<Container, uint> GetLastRevision = Fast.Getter<Container, uint>(AccessTools.Field(typeof(Container), "m_lastRevision")); private long _lastSig; private long _lastChestSig; private static readonly Comparison<Entry> ByEntry = delegate(Entry a, Entry b) { int num; try { num = CraftSort.CompareItems(a.Sample, b.Sample); } catch { num = string.Compare(a.Name, b.Name, StringComparison.CurrentCulture); } return (num == 0) ? string.CompareOrdinal(a.Key, b.Key) : num; }; private static readonly Dictionary<ItemData, KeyCache> _keyCache = new Dictionary<ItemData, KeyCache>(); private static readonly Dictionary<string, string> _nameCache = new Dictionary<string, string>(); private HeldItem _held; internal bool UndoReady => _undo != null; internal bool ShowingSelf => _showingSelf; internal Inventory Virtual => _vinv; private int TotalRows => Math.Max(6, (_entries.Count + 8 - 1) / 8); private int MaxScrollRow => Math.Max(0, TotalRows - 6); private bool SlideOpen => IsOpen || SpawnPicker.Active; internal bool Closing => _slideOn && !IsOpen && !SpawnPicker.Active; internal bool CraftActive => IsOpen && Plugin.CraftEnabled.Value; public bool IsOpen { get; private set; } public void DepositAllClicked() { _nextUndoCheck = 0f; CheckUndo(); if (_undo != null) { TakeBackCore(); } else { DepositAllCore(); } } private static bool AllDepositable(ItemData it) { if (it == null || it.m_equipped) { return false; } if (Api.IsSlotItem(it)) { return false; } if (Plugin.ExcludeHotbar.Value && it.m_gridPos.y == 0) { return false; } if (SlotLocks.IsLocked(it)) { return false; } return true; } private static int InvSig(Inventory inv) { int num = 17; if (inv == null) { return num; } foreach (ItemData allItem in inv.GetAllItems()) { num = num * 31 + ((allItem.m_shared.m_name != null) ? allItem.m_shared.m_name.GetHashCode() : 0); num = num * 31 + allItem.m_stack; num = num * 31 + allItem.m_gridPos.x * 97 + allItem.m_gridPos.y; num = num * 31 + allItem.m_quality; } return num; } private void CheckUndo() { if (_undo != null && !(Time.unscaledTime < _nextUndoCheck)) { _nextUndoCheck = Time.unscaledTime + 0.25f; Player localPlayer = Player.m_localPlayer; if ((Object)(object)localPlayer == (Object)null || InvSig(((Humanoid)localPlayer).GetInventory()) != _undoSig) { _undo = null; } } } private void DepositAllCore() { _actions.Enqueue(delegate { Player localPlayer = Player.m_localPlayer; if (!((Object)(object)localPlayer == (Object)null)) { bool flag = false; foreach (ItemData allItem in ((Humanoid)localPlayer).GetInventory().GetAllItems()) { if (AllDepositable(allItem)) { flag = true; break; } } if (flag) { HashSet<Container> hashSet = new HashSet<Container>(); foreach (ItemData allItem2 in ((Humanoid)localPlayer).GetInventory().GetAllItems()) { if (AllDepositable(allItem2)) { foreach (Container item in DepositTargets(allItem2)) { hashSet.Add(item); } } } WithChests(new List<Container>(hashSet), delegate { //IL_00a2: Unknown result type (might be due to invalid IL or missing references) //IL_00a7: Unknown result type (might be due to invalid IL or missing references) //IL_0191: Unknown result type (might be due to invalid IL or missing references) //IL_0193: Unknown result type (might be due to invalid IL or missing references) Inventory inventory = ((Humanoid)Player.m_localPlayer).GetInventory(); List<Container> list = Owned(_opened); List<Deposited> list2 = new List<Deposited>(); HashSet<Container> hashSet2 = new HashSet<Container>(); int num = 0; int num2 = 0; List<ItemData> list3 = new List<ItemData>(inventory.GetAllItems()); list3.Sort(delegate(ItemData a, ItemData b) { int num5 = a.m_gridPos.y.CompareTo(b.m_gridPos.y); return (num5 == 0) ? a.m_gridPos.x.CompareTo(b.m_gridPos.x) : num5; }); using (ContainerAccess.Batch()) { foreach (ItemData item2 in list3) { if (AllDepositable(item2)) { string key = ContainerAccess.KeyOf(item2); string name = item2.m_shared.m_name; Vector2i gridPos = item2.m_gridPos; for (int num3 = 0; num3 < 3; num3++) { if (!inventory.ContainsItem(item2)) { break; } if (item2.m_stack <= 0) { break; } foreach (Container item3 in list) { if (!inventory.ContainsItem(item2) || item2.m_stack <= 0) { break; } if (ContainerAccess.StillOwned(item3)) { Inventory inventory2 = item3.GetInventory(); if (inventory2 != null) { bool flag2 = ChestIndex.Has(inventory2, name); if ((num3 >= 2 || flag2) && (flag2 || !ContainerAccess.IsFull(inventory2))) { int num4 = ContainerAccess.Move(inventory, item2, inventory2, item2.m_stack, preferNonHotbar: false, num3 >= 1); if (num4 > 0) { list2.Add(new Deposited { C = item3, Key = key, Count = num4, Pos = gridPos }); num += num4; hashSet2.Add(item3); } } } } } } if (inventory.ContainsItem(item2) && item2.m_stack > 0) { num2++; } } } } if (num > 0) { _undo = list2; _undoSig = InvSig(inventory); } }); } } }); } private void TakeBackCore() { List<Deposited> log = _undo; _undo = null; if (log == null || log.Count == 0) { return; } _actions.Enqueue(delegate { List<Container> list = new List<Container>(); foreach (Deposited item in log) { if ((Object)(object)item.C != (Object)null && !list.Contains(item.C)) { list.Add(item.C); } } WithChests(list, delegate { Player localPlayer = Player.m_localPlayer; if ((Object)(object)localPlayer == (Object)null) { return; } Inventory inventory = ((Humanoid)localPlayer).GetInventory(); int num = 0; int num2 = 0; using (ContainerAccess.Batch()) { for (int num3 = log.Count - 1; num3 >= 0; num3--) { Deposited deposited = log[num3]; num2 += deposited.Count; if (ContainerAccess.StillOwned(deposited.C)) { Inventory inventory2 = deposited.C.GetInventory(); if (inventory2 != null) { int num4 = deposited.Count; List<ItemData> list2 = new List<ItemData>(inventory2.GetAllItems()); list2.Sort((ItemData a, ItemData b) => a.m_stack.CompareTo(b.m_stack)); foreach (ItemData item2 in list2) { if (num4 <= 0) { break; } if (ContainerAccess.HasKey(item2, deposited.Key) && inventory2.ContainsItem(item2)) { int num5 = Mathf.Min(num4, item2.m_stack); int num6 = 0; ItemData itemAt = inventory.GetItemAt(deposited.Pos.x, deposited.Pos.y); if (itemAt == null || (itemAt.IsSameType(item2) && itemAt.m_stack < itemAt.m_shared.m_maxStackSize)) { int num7 = ((itemAt != null) ? (itemAt.m_shared.m_maxStackSize - itemAt.m_stack) : item2.m_shared.m_maxStackSize); int num8 = Mathf.Min(num5, num7); int stack = item2.m_stack; bool flag = num8 >= item2.m_stack; if (num8 > 0 && inventory.MoveItemToThis(inventory2, item2, num8, deposited.Pos.x, deposited.Pos.y)) { num6 = ((!flag) ? (stack - item2.m_stack) : num8); } } if (num6 < num5 && inventory2.ContainsItem(item2)) { num6 += ContainerAccess.Move(inventory2, item2, inventory, num5 - num6, preferNonHotbar: true, allowEmpty: true); } num4 -= num6; num += num6; } } } } } } }); }); } internal static InventoryGrid ContainerGrid(InventoryGui gui) { return (InventoryGrid)(((Object)(object)gui == (Object)null) ? null : ((G_containerGrid == null) ? ((object)/*isinst with value type is only supported in some contexts*/) : ((object)G_containerGrid(gui)))); } private static List<ItemData> InvList(Inventory inv) { return (inv == null) ? null : ((G_invList == null) ? (F_invList.GetValue(inv) as List<ItemData>) : G_invList(inv)); } internal static Inventory DragInv(InventoryGui gui) { return (Inventory)(((Object)(object)gui == (Object)null) ? null : ((G_dragInv == null) ? ((object)/*isinst with value type is only supported in some contexts*/) : ((object)G_dragInv(gui)))); } internal void MarkCraftDirty() { _craftPanelDirty = true; } internal static void WarnOnce(string what, Exception e) { if (!_warnedPanel) { _warnedPanel = true; Plugin.Warn("통합 창(" + what + "): " + ((e == null) ? string.Empty : e.Message)); } } private bool ShowVanilla() { InventoryGui instance = InventoryGui.instance; if ((Object)(object)instance == (Object)null || F_containerGrid == null || F_invList == null || M_setupDrag == null) { return false; } _showingSelf = true; try { instance.Show((Container)null, 1); } catch (Exception e) { WarnOnce("열기", e); return false; } finally { _showingSelf = false; } return true; } private void RebuildVirtual() { //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Expected O, but got Unknown //IL_018c: Unknown result type (might be due to invalid IL or missing references) //IL_0191: Unknown result type (might be due to invalid IL or missing references) _vinvVersion++; if (_vinv == null) { _vinv = new Inventory("주변 보관함", (Sprite)null, 8, 6); } List<ItemData> list = InvList(_vinv); if (list == null) { return; } list.Clear(); if (_vinv.GetHeight() != 6 && F_invHeight != null) { F_invHeight.SetValue(_vinv, 6); } if (_allowShrink) { _scrollRow = 0; } _allowShrink = false; _scrollRow = Mathf.Clamp(_scrollRow, 0, MaxScrollRow); int num = 48; int num2 = _scrollRow * 8; for (int i = 0; i < _entries.Count; i++) { ChestKnowledge.LearnSample(_entries[i].Sample); } for (int j = 0; j < num && num2 + j < _entries.Count; j++) { Entry entry = _entries[num2 + j]; if (!_clones.TryGetValue(entry.Key, out var value)) { value = entry.Sample.Clone(); _clones[entry.Key] = value; _cloneKey[value] = entry.Key; } value.m_stack = Math.Max(1, entry.Total); value.m_equipped = false; value.m_durability = entry.Sample.m_durability; value.m_gridPos = new Vector2i(j % 8, j / 8); list.Add(value); } } private void ScrollTo(int row) { row = Mathf.Clamp(row, 0, MaxScrollRow); if (row != _scrollRow) { _scrollRow = row; RebuildVirtual(); } } private void HandleWheel(InventoryGui gui, InventoryGrid g) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Unknown result type (might be due to invalid IL or missing references) float y = Input.mouseScrollDelta.y; if (!(Mathf.Abs(y) < 0.01f) && MaxScrollRow != 0 && ScreenRect(gui.m_container, out var r) && ((Rect)(ref r)).Contains(Input.mousePosition)) { ScrollTo(_scrollRow + ((!(y > 0f)) ? 1 : (-1))); } } private string KeyOfVirtual(ItemData it) { string value; return (it == null || !_cloneKey.TryGetValue(it, out value)) ? null : value; } private string PanelTitle() { return "기지 상자 " + _opened.Count + "개"; } internal void UpdatePanel(InventoryGui gui) { //IL_00ed: 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_0266: Unknown result type (might be due to invalid IL or missing references) //IL_0268: Unknown result type (might be due to invalid IL or missing references) //IL_00f2: Unknown result type (might be due to invalid IL or missing references) UndoSlide(); InventoryGrid val = ContainerGrid(gui); if ((Object)(object)val == (Object)null) { return; } if (_vinv == null) { RebuildVirtual(); } if (!((Component)gui.m_container).gameObject.activeSelf) { ((Component)gui.m_container).gameObject.SetActive(true); } try { if (_gamepad != null && G_gridInv != null && object.ReferenceEquals(G_gridInv(val), _vinv)) { _gamepad(val); } } catch { } ItemData val2 = ((G_dragItem == null) ? null : G_dragItem(gui)); bool flag = G_firstContainerUpdate != null && G_firstContainerUpdate(gui); float unscaledTime = Time.unscaledTime; Vector2i drawnSel = (Vector2i)((G_gridSelected == null) ? new Vector2i(-1, -1) : G_gridSelected(val)); bool flag2 = unscaledTime - _openedAt < 1.5f && _fitOk < 5; try { HandleWheel(gui, val); } catch { } try { SyncScrollbar(val); } catch (Exception e) { WarnOnce("스크롤", e); } InventoryElement val3 = HoveredCached(val); bool flag3 = flag || _drawnVersion != _vinvVersion || val2 != _drawnDrag || !_drawnSelValid || drawnSel.x != _drawnSel.x || drawnSel.y != _drawnSel.y; if (!flag3 && (Object)(object)val3 != (Object)(object)_drawnHover) { _drawnHover = val3; if (!HoverTooltip(val, val3)) { flag3 = true; } } if ((Object)(object)_barTxt[1] != (Object)null) { SetText(_barTxt[1], (!UndoReady) ? "전부 넣기" : "다시 꺼내기"); } if (!flag3) { if (flag2) { try { EnsureExtras(gui); return; } catch (Exception e2) { WarnOnce("버튼", e2); return; } } return; } _drawnHover = val3; _drawnVersion = _vinvVersion; _drawnDrag = val2; _drawnSel = drawnSel; _drawnSelValid = true; val.UpdateInventory(_vinv, (Player)null, val2); FixAmounts(val); if (flag) { val.ResetView(); F_firstContainerUpdate.SetValue(gui, false); } if ((Object)(object)gui.m_containerName != (Object)null) { string text = PanelTitle(); if (gui.m_containerName.text != text) { gui.m_containerName.text = text; } } if ((Object)(object)gui.m_containerWeight != (Object)null && gui.m_containerWeight.text != string.Empty) { gui.m_containerWeight.text = string.Empty; } try { EnsureExtras(gui); } catch (Exception e3) { WarnOnce("버튼", e3); } } private InventoryElement HoveredCached(InventoryGrid g) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_001d: 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_008c: Unknown result type (might be due to invalid IL or missing references) //IL_008d: Unknown result type (might be due to invalid IL or missing references) //IL_0093: Unknown result type (might be due to invalid IL or missing references) //IL_0094: Unknown result type (might be due to invalid IL or missing references) //IL_004f: Unknown result type (might be due to invalid IL or missing references) //IL_0051: Unknown result type (might be due to invalid IL or missing references) //IL_0060: Unknown result type (might be due to invalid IL or missing references) //IL_0062: Unknown result type (might be due to invalid IL or missing references) Vector3 mousePosition = Input.mousePosition; Vector3 val = ((!((Object)(object)g.m_gridRoot != (Object)null)) ? Vector3.zero : ((Transform)g.m_gridRoot).position); if (object.ReferenceEquals(g, _hovGrid) && _hovVersion == _vinvVersion && mousePosition == _hovMouse && val == _hovRoot) { return _hovLast; } _hovGrid = g; _hovVersion = _vinvVersion; _hovMouse = mousePosition; _hovRoot = val; _hovLast = Hovered(g); return _hovLast; } private static Action<InventoryGrid> MakeGamepad() { try { MethodInfo methodInfo = AccessTools.Method(typeof(InventoryGrid), "UpdateGamepad", (Type[])null, (Type[])null); return (!(methodInfo != null)) ? null : ((Action<InventoryGrid>)Delegate.CreateDelegate(typeof(Action<InventoryGrid>), methodInfo)); } catch { return null; } } private bool HoverTooltip(InventoryGrid g, InventoryElement el) { //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) if ((Object)(object)el == (Object)null) { return true; } if (M_createTooltip == null || F_elTooltip == null || _vinv == null) { return false; } try { if (ZInput.IsTouchActive()) { return false; } Vector2i position = el.Position; ItemData itemAt = _vinv.GetItemAt(position.x, position.y); if (itemAt == null) { return true; } object value = F_elTooltip.GetValue(el); if (value == null) { return false; } _tipArgs[0] = itemAt; _tipArgs[1] = value; M_createTooltip.Invoke(g, _tipArgs); _tipArgs[0] = null; _tipArgs[1] = null; return true; } catch { return false; } } private static InventoryElement Hovered(InventoryGrid g) { try { if (_hovered == null && M_hovered != null) { _hovered = (Func<InventoryGrid, InventoryElement>)Delegate.CreateDelegate(typeof(Func<InventoryGrid, InventoryElement>), M_hovered); } return (_hovered == null) ? null : _hovered(g); } catch { return null; } } private void FixAmounts(InventoryGrid g) { IList list = ((G_elements == null) ? null : G_elements(g)); if (list == null) { return; } List<ItemData> list2 = InvList(_vinv); for (int i = 0; i < list.Count; i++) { object? obj = list[i]; InventoryElement val = (InventoryElement)((obj is InventoryElement) ? obj : null); if ((Object)(object)val == (Object)null || (Object)(object)val.m_amount == (Object)null) { continue; } ItemData val2 = null; if (list2 != null && i < list2.Count && list2[i] != null && list2[i].m_gridPos.x == i % 8 && list2[i].m_gridPos.y == i / 8) { val2 = list2[i]; } else if (list2 == null || i < list2.Count) { val2 = _vinv.GetItemAt(i % 8, i / 8); } if (val2 == null || (val2.m_shared.m_maxStackSize <= 1 && val2.m_stack <= 1)) { continue; } if (!_countText.TryGetValue(val2, out var value) || value.Key != val2.m_stack) { value = new KeyValuePair<int, string>(val2.m_stack, FormatCount(val2.m_stack)); if (_countText.Count > 4000) { _countText.Clear(); } _countText[val2] = value; } if (val.m_amount.text != value.Value) { val.m_amount.text = value.Value; } if (!((Component)val.m_amount).gameObject.activeSelf) { ((Component)val.m_amount).gameObject.SetActive(true); } } } internal static bool ScreenRect(RectTransform rt, out Rect r) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_00ac: Unknown result type (might be due to invalid IL or missing references) //IL_00b1: Unknown result type (might be due to invalid IL or missing references) //IL_00b6: Unknown result type (might be due to invalid IL or missing references) //IL_00bf: 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_00c9: Unknown result type (might be due to invalid IL or missing references) //IL_0118: Unknown result type (might be due to invalid IL or missing references) //IL_011d: Unknown result type (might be due to invalid IL or missing references) //IL_0086: Unknown result type (might be due to invalid IL or missing references) r = default(Rect); if ((Object)(object)rt == (Object)null) { return false; } if (!_rootCanvas.TryGetValue(rt, out var value) || (Object)(object)value == (Object)null) { value = ((Component)rt).GetComponentInParent<Canvas>(); if ((Object)(object)value != (Object)null) { value = value.rootCanvas; } if (_rootCanvas.Count > 256) { _rootCanvas.Clear(); } _rootCanvas[rt] = value; } Camera val = null; if ((Object)(object)value != (Object)null && (int)value.renderMode != 0) { val = value.worldCamera; } Vector3[] screenCorners = _screenCorners; rt.GetWorldCorners(screenCorners); Vector2 val2 = RectTransformUtility.WorldToScreenPoint(val, screenCorners[0]); Vector2 val3 = RectTransformUtility.WorldToScreenPoint(val, screenCorners[2]); r = Rect.MinMaxRect(Mathf.Min(val2.x, val3.x), Mathf.Min(val2.y, val3.y), Mathf.Max(val2.x, val3.x), Mathf.Max(val2.y, val3.y)); return ((Rect)(ref r)).width > 1f && ((Rect)(ref r)).height > 1f; } private Button MakeBarButton(InventoryGui gui, Button src, string name, UnityAction act, out TMP_Text txt) { GameObject val = Object.Instantiate<GameObject>(((Component)src).gameObject, (Transform)(object)gui.m_container); ((Object)val).name = name; Component[] componentsInChildren = val.GetComponentsInChildren<Component>(true); foreach (Component val2 in componentsInChildren) { if (!((Object)(object)val2 == (Object)null)) { string name2 = ((object)val2).GetType().Name; if (name2 == "UIGamePad" || name2 == "Localize") { Object.Destroy((Object)(object)val2); } } } Button component = val.GetComponent<Button>(); if ((Object)(object)component != (Object)null) { for (int j = 0; j < ((UnityEventBase)component.onClick).GetPersistentEventCount(); j++) { ((UnityEventBase)component.onClick).SetPersistentListenerState(j, (UnityEventCallState)0); } ((UnityEventBase)component.onClick).RemoveAllListeners(); ((UnityEvent)component.onClick).AddListener(act); } txt = val.GetComponentInChildren<TMP_Text>(true); if ((Object)(object)txt != (Object)null) { float num = ((!(txt.fontSize > 0f)) ? 18f : txt.fontSize); txt.enableAutoSizing = true; txt.fontSizeMax = num; txt.fontSizeMin = Mathf.Min(10f, num); txt.textWrappingMode = (TextWrappingModes)0; txt.overflowMode = (TextOverflowModes)1; txt.fontStyle = (FontStyles)0; } val.SetActive(true); return component; } private static void SetRt(RectTransform rt, Vector2 anchor, Vector2 pivot, Vector2 size, Vector2 pos) { //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_0019: 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_0012: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_0036: 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_0049: Unknown result type (might be due to invalid IL or missing references) //IL_004e: Unknown result type (might be due to invalid IL or missing references) //IL_0042: 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_0066: Unknown result type (might be due to invalid IL or missing references) //IL_005a: Unknown result type (might be due to invalid IL or missing references) //IL_0073: Unknown result type (might be due to invalid IL or missing references) if (rt.anchorMin != anchor) { rt.anchorMin = anchor; } if (rt.anchorMax != anchor) { rt.anchorMax = anchor; } if (rt.pivot != pivot) { rt.pivot = pivot; } if (rt.sizeDelta != size) { rt.sizeDelta = size; } if (rt.anchoredPosition != pos) { rt.anchoredPosition = pos; } } private void LayoutBar(InventoryGui gui) { //IL_0035: 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_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_0072: Unknown result type (might be due to invalid IL or missing references) //IL_0077: 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_00e7: 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_010d: Unknown result type (might be due to invalid IL or missing references) //IL_0119: Unknown result type (might be due to invalid IL or missing references) //IL_011e: 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_0176: 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_0181: Unknown result type (might be due to invalid IL or missing references) //IL_0194: Unknown result type (might be due to invalid IL or missing references) //IL_01ad: Unknown result type (might be due to invalid IL or missing references) //IL_01d8: Unknown result type (might be due to invalid IL or missing references) //IL_012f: Unknown result type (might be due to invalid IL or missing references) RectTransform val = (RectTransform)((!((Object)(object)gui.m_stackAllButton != (Object)null)) ? null : /*isinst with value type is only supported in some contexts*/); float num; if ((Object)(object)val != (Object)null) { Rect rect = val.rect; if (((Rect)(ref rect)).height > 10f) { Rect rect2 = val.rect; num = ((Rect)(ref rect2)).height; goto IL_0064; } } num = 34f; goto IL_0064; IL_0064: float num2 = num; float num3; if ((Object)(object)val != (Object)null) { Rect rect3 = val.rect; num3 = ((Rect)(ref rect3)).width; } else { num3 = 0f; } float num4 = Mathf.Max(num3, 150f); for (int i = 0; i < 3; i++) { if (!((Object)(object)_barBtn[i] == (Object)null)) { Transform transform = ((Component)_barBtn[i]).transform; RectTransform val2 = (RectTransform)(object)((transform is RectTransform) ? transform : null); SetRt(val2, new Vector2(1f, 1f), new Vector2(0f, 1f), new Vector2(num4, num2), new Vector2(8f, 0f - (10f + (float)(i + 1) * (num2 + 8f)))); if (((Transform)val2).localScale != Vector3.one) { ((Transform)val2).localScale = Vector3.one; } } } if ((Object)(object)_stationLine != (Object)null) { RectTransform rectTransform = _stationLine.rectTransform; Vector2 anchorMin = (rectTransform.anchorMax = new Vector2(1f, 1f)); rectTransform.anchorMin = anchorMin; rectTransform.pivot = new Vector2(0f, 1f); rectTransform.sizeDelta = new Vector2(num4 + 40f, 400f); rectTransform.anchoredPosition = new Vector2(8f, 0f - (10f + 4f * (num2 + 8f) + 6f)); } } private void GrowPanel(InventoryGui gui) { //IL_00e5: Unknown result type (might be due to invalid IL or missing references) //IL_00ea: 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_0115: 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_0124: 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_0163: Unknown result type (might be due to invalid IL or missing references) //IL_0168: Unknown result type (might be due to invalid IL or missing references) //IL_0173: Unknown result type (might be due to invalid IL or missing references) //IL_0178: 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_01a8: Unknown result type (might be due to invalid IL or missing references) //IL_01ad: 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_01bd: Unknown result type (might be due to invalid IL or missing references) //IL_01c8: Unknown result type (might be due to invalid IL or missing references) InventoryGrid val = ContainerGrid(gui); if ((Object)(object)val == (Object)null || (Object)(object)val.m_gridRoot == (Object)null) { return; } InventoryGrid playerGrid = gui.m_playerGrid; if ((Object)(object)_swappedGrid != (Object)(object)val && (Object)(object)playerGrid != (Object)null && (Object)(object)playerGrid.m_elementPrefab != (Object)null) { _swappedGrid = val; _origPrefab = val.m_elementPrefab; _origSpace = val.m_elementSpace; val.m_elementPrefab = playerGrid.m_elementPrefab; val.m_elementSpace = playerGrid.m_elementSpace; if (F_gridWidth != null) { F_gridWidth.SetValue(val, -1); } _drawnVersion = -1; } RectTransform container = gui.m_container; if (!_hasOrigBottom) { _hasOrigBottom = true; try { val.ResetView(); } catch { } _origBottom = container.offsetMin; float num = (_extra = 2f * val.m_elementSpace); _shrink = 0f; container.offsetMin = new Vector2(container.offsetMin.x, container.offsetMin.y - num); Transform parent = ((Transform)val.m_gridRoot).parent; while ((Object)(object)parent != (Object)null && (Object)(object)parent != (Object)(object)((Component)container).transform) { RectTransform val2 = (RectTransform)(object)((parent is RectTransform) ? parent : null); if ((Object)(object)val2 != (Object)null && Mathf.Approximately(val2.anchorMin.y, val2.anchorMax.y)) { _grown.Add(new KeyValuePair<RectTransform, Vector2>(val2, val2.offsetMin)); val2.offsetMin = new Vector2(val2.offsetMin.x, val2.offsetMin.y - num); } parent = parent.parent; } } FitBottom(val, container); try { FixScrollbar(gui, val); } catch (Exception e) { WarnOnce("스크롤바", e); } } private void FitBottom(InventoryGrid g, RectTransform c) { //IL_0168: Unknown result type (might be due to invalid IL or missing references) //IL_016d: Unknown result type (might be due to invalid IL or missing references) //IL_02d4: Unknown result type (might be due to invalid IL or missing references) //IL_02d9: Unknown result type (might be due to invalid IL or missing references) //IL_0317: Unknown result type (might be due to invalid IL