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 PackPanel v0.1.0
plugins\PackPanel.dll
Decompiled 16 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.Concurrent; using System.Collections.Generic; using System.Collections.ObjectModel; using System.ComponentModel; using System.Diagnostics; using System.Diagnostics.CodeAnalysis; using System.Globalization; using System.IO; using System.IO.Compression; using System.Linq; using System.Linq.Expressions; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Serialization; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using System.Text; using System.Text.RegularExpressions; using System.Threading; using BepInEx; using BepInEx.Bootstrap; using BepInEx.Configuration; using BepInEx.Logging; using BundlePrefabs; using Charter; using ConfigReload; using HarmonyLib; using Hotkeys; using ItemCopies; using Microsoft.CodeAnalysis; using PackPanel.Backpacks; using PackPanel.Consume; using PackPanel.Core; using PackPanel.Crafting; using PackPanel.Layout; using PackPanel.Look; using PackPanel.Panels; using PackPanel.Ring; using PackPanel.Slots; using PackPanel.Tackle; using PackPanel.Worn; using PatchGuard; using PlateColumn; using SyncedConfig; using TMPro; using UnityEngine; using UnityEngine.EventSystems; using UnityEngine.Events; using UnityEngine.SceneManagement; using UnityEngine.UI; using YamlConfig; using YamlDotNet.Core; using YamlDotNet.Core.Events; using YamlDotNet.Core.Tokens; using YamlDotNet.Helpers; using YamlDotNet.Serialization; using YamlDotNet.Serialization.BufferedDeserialization; using YamlDotNet.Serialization.BufferedDeserialization.TypeDiscriminators; using YamlDotNet.Serialization.Callbacks; using YamlDotNet.Serialization.Converters; using YamlDotNet.Serialization.EventEmitters; using YamlDotNet.Serialization.NamingConventions; using YamlDotNet.Serialization.NodeDeserializers; using YamlDotNet.Serialization.NodeTypeResolvers; using YamlDotNet.Serialization.ObjectFactories; using YamlDotNet.Serialization.ObjectGraphTraversalStrategies; using YamlDotNet.Serialization.ObjectGraphVisitors; using YamlDotNet.Serialization.Schemas; using YamlDotNet.Serialization.TypeInspectors; using YamlDotNet.Serialization.TypeResolvers; using YamlDotNet.Serialization.Utilities; using YamlDotNet.Serialization.ValueDeserializers; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: IgnoresAccessChecksTo("assembly_guiutils")] [assembly: IgnoresAccessChecksTo("assembly_utils")] [assembly: IgnoresAccessChecksTo("assembly_valheim")] [assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")] [assembly: AssemblyCompany("PackPanel")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyDescription("PackPanel: a bigger inventory, labelled slots, backpacks and a new look for Valheim")] [assembly: AssemblyFileVersion("0.1.0.0")] [assembly: AssemblyInformationalVersion("0.1.0+9a329d5c191afce69442cfc563644a5560c4fc74")] [assembly: AssemblyProduct("PackPanel")] [assembly: AssemblyTitle("PackPanel")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("0.1.0.0")] [module: UnverifiableCode] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.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] [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] [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 PackPanel { [BepInPlugin("milkyteam.packpanel", "PackPanel", "0.1.0")] public class Plugin : BaseUnityPlugin { public const string PluginGuid = "milkyteam.packpanel"; public const string PluginName = "PackPanel"; public const string PluginVersion = "0.1.0"; public static ManualLogSource Log { get; private set; } public static SyncedConfiguration Synced { get; private set; } public static ConfigEntry<bool> LockConfiguration { get; private set; } public static Plugin Instance { get; private set; } private void Awake() { //IL_005c: Unknown result type (might be due to invalid IL or missing references) //IL_0062: Expected O, but got Unknown Instance = this; Log = ((BaseUnityPlugin)this).Logger; Synced = new SyncedConfiguration((BaseUnityPlugin)(object)this, ((BaseUnityPlugin)this).Logger, "PackPanel", "0.1.0"); LockConfiguration = Synced.BindLocking("General", "Lock Configuration", defaultValue: true, "[Server Only] Clients cannot change synced settings while connected to a server that has this on."); InventoryModule.Initialize(Synced); Harmony harmony = new Harmony("milkyteam.packpanel"); int num = PatchEverything(harmony); BackpackPrefab.Install(harmony); TackleboxPrefab.Install(harmony); Synced.Finish(harmony); Log.LogInfo((object)("Loading [PackPanel 0.1.0]" + ((num > 0) ? $" with {num} failed patches, see above" : ""))); Guard.Install(harmony, ((BaseUnityPlugin)this).Logger, Assembly.GetExecutingAssembly()); } private void Update() { Synced.YamlEditor.Update(); GamePanelTheme.Update(); } private void OnGUI() { Synced.YamlEditor.OnGUI(); } private static int PatchEverything(Harmony harmony) { int num = 0; Type[] typesFromAssembly = AccessTools.GetTypesFromAssembly(Assembly.GetExecutingAssembly()); foreach (Type type in typesFromAssembly) { if (type.GetCustomAttributes(typeof(HarmonyPatch), inherit: true).Length != 0) { try { harmony.CreateClassProcessor(type).Patch(); } catch (Exception ex) { num++; Log.LogError((object)("Patch " + type.FullName + " failed to apply: " + ex.Message)); } } } return num; } } } namespace PackPanel.Worn { public static class EquipPatches { [HarmonyPatch(typeof(Humanoid), "EquipItem")] public static class Equip { [HarmonyPrefix] public static bool Prefix(Humanoid __instance, ItemData item, bool triggerEquipEffects, ref bool __result) { WornPlacement.BeginEquip(); if (!ExtraUtilities.Takes(__instance, item)) { return true; } __result = ExtraUtilities.Wear(__instance, item, triggerEquipEffects); return false; } [HarmonyPostfix] public static void Postfix(Humanoid __instance, ItemData item, bool __result) { if (__result) { WornPlacement.OnWorn(__instance, item); } } [HarmonyFinalizer] public static void Finalizer() { WornPlacement.EndEquip(); } } [HarmonyPatch(typeof(Humanoid), "UnequipItem")] public static class Unequip { [HarmonyPostfix] public static void Postfix(Humanoid __instance, ItemData item) { if (item != null && !item.m_equipped) { ExtraUtilities.Forget(item); WornPlacement.OnTakenOff(__instance, item); } } } [HarmonyPatch(typeof(Humanoid), "IsItemEquiped")] public static class IsEquipped { [HarmonyPostfix] public static void Postfix(Humanoid __instance, ItemData item, ref bool __result) { if (!__result && ExtraUtilities.IsWorn(item) && InventoryState.IsLocal(__instance)) { __result = true; } } } [HarmonyPatch(typeof(Humanoid), "IsItemTypeEquiped")] public static class IsTypeEquipped { [HarmonyPostfix] public static void Postfix(Humanoid __instance, ItemData item, ref bool __result) { if (__result || item == null || !InventoryState.IsLocal(__instance)) { return; } foreach (ItemData item2 in ExtraUtilities.Worn) { if (item2.m_shared.m_name == item.m_shared.m_name) { __result = true; } } } } [HarmonyPatch(typeof(Humanoid), "UnequipAllItems")] public static class UnequipAll { [HarmonyPostfix] public static void Postfix(Humanoid __instance) { if (InventoryState.IsLocal(__instance)) { ExtraUtilities.TakeOffAll(__instance); } } } [HarmonyPatch(typeof(Player), "UnequipDeathDropItems")] public static class DeathDrop { [HarmonyPostfix] public static void Postfix(Player __instance) { if (InventoryState.IsLocal((Humanoid)(object)__instance)) { ExtraUtilities.TakeOffAll((Humanoid)(object)__instance); } } } } public static class ExtraEffects { private static readonly HashSet<StatusEffect> added = new HashSet<StatusEffect>(); public static void Reset() { added.Clear(); } public static void Sync(Humanoid humanoid) { if (!InventoryState.IsLocal(humanoid)) { return; } HashSet<StatusEffect> hashSet = Wanted(humanoid); SEMan sEMan = ((Character)humanoid).GetSEMan(); foreach (StatusEffect item in added) { if (!hashSet.Contains(item) && !humanoid.m_equipmentStatusEffects.Contains(item)) { sEMan.RemoveStatusEffect(item.NameHash(), false); } } foreach (StatusEffect item2 in hashSet) { if (!sEMan.HaveStatusEffect(item2.NameHash())) { sEMan.AddStatusEffect(item2, false, 0, 0f, (short)(-1)); } } added.Clear(); added.UnionWith(hashSet); } private static HashSet<StatusEffect> Wanted(Humanoid humanoid) { HashSet<StatusEffect> hashSet = new HashSet<StatusEffect>(); foreach (ItemData item in ExtraUtilities.Worn) { if ((Object)(object)item.m_shared.m_equipStatusEffect != (Object)null) { hashSet.Add(item.m_shared.m_equipStatusEffect); } if (humanoid.HaveSetEffect(item)) { hashSet.Add(item.m_shared.m_setStatusEffect); } } return hashSet; } } public static class ExtraUtilities { private static readonly List<ItemData> worn = new List<ItemData>(); public static IReadOnlyList<ItemData> Worn => worn; public static bool IsWorn(ItemData item) { if (item != null) { return worn.Contains(item); } return false; } public static void Reset() { worn.Clear(); ExtraEffects.Reset(); } public static bool Takes(Humanoid humanoid, ItemData item) { //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Invalid comparison between Unknown and I4 if (!InventoryState.IsLocal(humanoid) || !InventoryState.Active || item == null) { return false; } if ((int)item.m_shared.m_itemType != 18 || worn.Contains(item)) { return false; } ItemData utilityItem = humanoid.m_utilityItem; if (utilityItem == null || utilityItem == item || 1 + worn.Count >= SlotCounts.Utility) { return false; } return !NameWorn(utilityItem, item); } public static bool Wear(Humanoid humanoid, ItemData item, bool triggerEquipEffects) { //IL_0030: 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_003a: 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_004d: Unknown result type (might be due to invalid IL or missing references) if (!CanWear(humanoid, item)) { return false; } worn.Add(item); item.m_equipped = true; Transform transform = ((Component)humanoid).transform; item.m_shared.m_equipEffect.Create(transform.position + Vector3.up, transform.rotation, (Transform)null, 1f, -1, ((Character)humanoid).GetZDOID()); humanoid.SetupEquipment(); if (triggerEquipEffects) { humanoid.TriggerEquipEffect(item); } return true; } public static void Forget(ItemData item) { worn.Remove(item); } public static void TakeOffAll(Humanoid humanoid) { foreach (ItemData item in new List<ItemData>(worn)) { humanoid.UnequipItem(item, false); } worn.Clear(); } public static void Prune(Humanoid humanoid) { Inventory inventory = humanoid.GetInventory(); if (worn.RemoveAll((ItemData item) => !item.m_equipped || !inventory.ContainsItem(item)) > 0) { humanoid.SetupEquipment(); } } private static bool NameWorn(ItemData first, ItemData item) { if (first.m_shared.m_name == item.m_shared.m_name) { return true; } return worn.Exists((ItemData other) => other.m_shared.m_name == item.m_shared.m_name); } private static bool CanWear(Humanoid humanoid, ItemData item) { if (!humanoid.GetInventory().ContainsItem(item) || ((Character)humanoid).InAttack() || ((Character)humanoid).InDodge()) { return false; } if (((Character)humanoid).IsSwimming() && !((Character)humanoid).IsOnGround() && !((Character)humanoid).IsDead()) { return false; } if (item.m_shared.m_useDurability && item.m_durability <= 0f) { return false; } if (Game.m_worldLevel > 0 && item.m_worldLevel < Game.m_worldLevel) { ((Character)humanoid).Message((MessageType)2, "$msg_ng_item_too_low", 0, (Sprite)null, false); return false; } return true; } } public static class UtilityEffectPatches { [HarmonyPatch(typeof(Humanoid), "UpdateEquipmentStatusEffects")] public static class StatusEffects { [HarmonyPostfix] public static void Postfix(Humanoid __instance) { ExtraEffects.Sync(__instance); } } [HarmonyPatch(typeof(Humanoid), "GetSetCount")] public static class SetCount { [HarmonyPostfix] public static void Postfix(Humanoid __instance, string setName, ref int __result) { if (!InventoryState.IsLocal(__instance)) { return; } foreach (ItemData item in ExtraUtilities.Worn) { if (item.m_shared.m_setName == setName) { __result++; } } } } [HarmonyPatch(typeof(Player), "GetEquipmentEitrRegenModifier")] public static class EitrRegen { [HarmonyPostfix] public static void Postfix(Player __instance, ref float __result) { if (!InventoryState.IsLocal((Humanoid)(object)__instance)) { return; } foreach (ItemData item in ExtraUtilities.Worn) { __result += item.m_shared.m_eitrRegenModifier; } } } [HarmonyPatch(typeof(Player), "UpdateModifiers")] public static class Modifiers { [HarmonyPostfix] public static void Postfix(Player __instance) { if (!InventoryState.IsLocal((Humanoid)(object)__instance) || ExtraUtilities.Worn.Count == 0 || Player.s_equipmentModifierSourceFields == null) { return; } float[] equipmentModifierValues = __instance.m_equipmentModifierValues; for (int i = 0; i < equipmentModifierValues.Length; i++) { foreach (ItemData item in ExtraUtilities.Worn) { equipmentModifierValues[i] += (float)Player.s_equipmentModifierSourceFields[i].GetValue(item.m_shared); } } } } [HarmonyPatch(typeof(Humanoid), "GetEquipmentWeight")] public static class Weight { [HarmonyPostfix] public static void Postfix(Humanoid __instance, ref float __result) { if (!InventoryState.IsLocal(__instance)) { return; } foreach (ItemData item in ExtraUtilities.Worn) { __result += item.m_shared.m_weight; } } } [HarmonyPatch(typeof(Humanoid), "UpdateEquipment")] public static class Durability { [HarmonyPostfix] public static void Postfix(Humanoid __instance, float dt) { if (!InventoryState.IsLocal(__instance)) { return; } for (int num = ExtraUtilities.Worn.Count - 1; num >= 0; num--) { ItemData val = ExtraUtilities.Worn[num]; if (val.m_shared.m_useDurability) { __instance.DrainEquipedItemDurability(val, dt); } } } } } public static class WornPlacement { private static int suspended; private static int equipping; public static bool Suspended => suspended > 0; public static void BeginEquip() { equipping++; } public static void EndEquip() { equipping = ((equipping > 0) ? (equipping - 1) : 0); } public static void Suspend() { suspended++; } public static void Resume() { suspended = ((suspended > 0) ? (suspended - 1) : 0); } public static void OnWorn(Humanoid humanoid, ItemData item) { if (!Suspended && item != null && InventoryState.IsLocal(humanoid) && InventoryState.Manages(humanoid.GetInventory())) { Place(humanoid.GetInventory(), item); } } public static void OnTakenOff(Humanoid humanoid, ItemData item) { //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_0064: Unknown result type (might be due to invalid IL or missing references) //IL_0069: Unknown result type (might be due to invalid IL or missing references) //IL_006a: Unknown result type (might be due to invalid IL or missing references) //IL_0075: Unknown result type (might be due to invalid IL or missing references) //IL_0076: Unknown result type (might be due to invalid IL or missing references) Inventory inventory = humanoid.GetInventory(); if (Suspended || equipping > 0 || item == null || item.m_equipped || !InventoryState.IsLocal(humanoid) || !InventoryState.Manages(inventory)) { return; } Slot slot = InventoryState.Layout.SlotAt(item.m_gridPos); if (slot != null && SlotRules.IsWorn(slot.Kind) && inventory.ContainsItem(item)) { Vector2i val = MainCells.FindEmpty(inventory, InventoryState.Layout, topFirst: false); if (val.x >= 0) { item.m_gridPos = val; inventory.Changed(false, false); } } } public static void SettleAll(Humanoid humanoid) { //IL_006a: Unknown result type (might be due to invalid IL or missing references) Inventory inventory = humanoid.GetInventory(); foreach (ItemData item in new List<ItemData>(inventory.GetAllItems())) { if (item.m_equipped) { Place(inventory, item); } } foreach (ItemData item2 in new List<ItemData>(ExtraUtilities.Worn)) { Slot slot = InventoryState.Layout.SlotAt(item2.m_gridPos); if (slot == null || slot.Kind != SlotKind.Utility) { humanoid.UnequipItem(item2, false); } } } private static void Place(Inventory inventory, ItemData item) { //IL_000d: 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_005b: 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_0082: 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_0075: Unknown result type (might be due to invalid IL or missing references) SlotKind? slotKind = SlotRules.WornKindOf(item); Slot slot = InventoryState.Layout.SlotAt(item.m_gridPos); if (!slotKind.HasValue || (slot != null && slot.Kind == slotKind.Value)) { return; } Vector2i? val = CellFor(inventory, slotKind.Value); if (val.HasValue) { ItemData itemAt = inventory.GetItemAt(val.Value.x, val.Value.y); if (itemAt != null) { itemAt.m_gridPos = item.m_gridPos; } item.m_gridPos = val.Value; inventory.Changed(false, false); } } private static Vector2i? CellFor(Inventory inventory, SlotKind kind) { //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_0033: 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) Vector2i? result = null; foreach (Vector2i item in InventoryState.CellsOf(kind)) { ItemData itemAt = inventory.GetItemAt(item.x, item.y); if (itemAt == null) { return item; } if (!result.HasValue && !itemAt.m_equipped) { result = item; } } return result; } } } namespace PackPanel.Tackle { public static class Tacklebox { public static bool Active { get { if (InventoryState.Active) { return InventoryState.CellsOf(SlotKind.Tackle).Count > 0; } return false; } } public static TackleboxKind InSlot(Inventory inventory, InventoryLayout layout) { //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Unknown result type (might be due to invalid IL or missing references) IReadOnlyList<Vector2i> readOnlyList = layout.CellsOf(SlotKind.Tacklebox); if (readOnlyList.Count <= 0) { return null; } return TackleboxCatalog.Of(inventory.GetItemAt(readOnlyList[0].x, readOnlyList[0].y)); } public static int CellsFor(Player player) { return TackleboxSettings.Cells(InSlot(((Humanoid)player).GetInventory(), LayoutRecord.Read(player))); } } public static class TackleboxCatalog { private static readonly Dictionary<string, TackleboxKind> byName = new Dictionary<string, TackleboxKind>(); private static readonly Dictionary<string, TackleboxKind> byId = new Dictionary<string, TackleboxKind>(StringComparer.OrdinalIgnoreCase); public static IReadOnlyList<TackleboxKind> All { get; } = new List<TackleboxKind> { new TackleboxKind("PackPanel_DriftwoodTacklebox", "driftwood", "Driftwood Tacklebox", "A plain wooden box covered in furs.", 2f, new TackleboxStats("piece_workbench", 2, "Wood:10, LeatherScraps:10, DeerHide:5", 1)), new TackleboxKind("PackPanel_FinewoodTacklebox", "finewood", "Finewood Tacklebox", "A fine wood box wrapped in troll leather, with bronze corners and clasp.", 3f, new TackleboxStats("piece_workbench", 3, "PackPanel_DriftwoodTacklebox:1, FineWood:10, TrollHide:10, Bronze:2", 2)), new TackleboxKind("PackPanel_CarapaceTacklebox", "carapace", "Carapace Tacklebox", "A Yggdrasil wood box coated in carapace plates.", 3f, new TackleboxStats("blackforge", 1, "PackPanel_FinewoodTacklebox:1, Carapace:10, YggdrasilWood:10", 6)), new TackleboxKind("PackPanel_FlametalTacklebox", "flametal", "Flametal Tacklebox", "A flametal box covered in asksvin hide.", 4f, new TackleboxStats("blackforge", 3, "PackPanel_CarapaceTacklebox:1, FlametalNew:5, AskHide:10", 8)) }; public static TackleboxKind Of(ItemData item) { if (item == null || !Tables().TryGetValue(item.m_shared.m_name, out var value)) { return null; } return value; } public static TackleboxKind ById(string id) { Tables(); if (id == null || !byId.TryGetValue(id.Trim(), out var value)) { return null; } return value; } private static Dictionary<string, TackleboxKind> Tables() { if (byName.Count == 0) { foreach (TackleboxKind item in All) { byName[item.Token] = item; byId[item.Id] = item; } } return byName; } } public static class TackleboxesFile { public const string DefaultResource = "PackPanel.config.PackPanel.Tackleboxes.yml"; public static YamlFileSet Set { get; private set; } public static void Initialize(SyncedConfiguration synced) { Set = synced.AddYaml(new YamlFileSet("PackPanel.Tackleboxes*.yml", "packpanel_tackleboxes", () => new TackleboxesModel(), Apply) { DefaultContent = SyncedConfiguration.EmbeddedResource(typeof(TackleboxesFile).Assembly, "PackPanel.config.PackPanel.Tackleboxes.yml"), EditorLabel = () => "Edit tackleboxes" }); } private static void Apply(YamlModel model) { TackleboxesModel tackleboxesModel = (TackleboxesModel)model; foreach (TackleboxKind item in TackleboxCatalog.All) { item.Stats = (tackleboxesModel.Stats.TryGetValue(item.Id, out var value) ? value : item.Defaults); } CraftRecipes.RefreshAll(); TackleboxWords.DescribeAll(); Plugin.Log.LogInfo((object)$"PackPanel: tackleboxes applied, {tackleboxesModel.Stats.Count} set in the file."); } } public sealed class TackleboxesModel : YamlModel { public const int MaxCells = 20; public Dictionary<string, TackleboxStats> Stats { get; } = new Dictionary<string, TackleboxStats>(StringComparer.OrdinalIgnoreCase); protected override void Read(YamlNode root) { YamlNode yamlNode = root.Get("tackleboxes"); if (yamlNode.Kind == YamlNodeKind.Map) { foreach (KeyValuePair<string, YamlNode> entry in yamlNode.Entries) { ReadBox(entry.Key, entry.Value); } return; } if (yamlNode.Kind != YamlNodeKind.Missing && yamlNode.Kind != YamlNodeKind.Null) { yamlNode.Error("expected one entry per tacklebox prefab, as in 'PackPanel_FinewoodTacklebox: { cells: 3 }'"); } } private void ReadBox(string id, YamlNode node) { TackleboxKind tackleboxKind = TackleboxCatalog.ById(id); if (tackleboxKind == null) { node.Warn("no tacklebox of that name; PackPanel's are PackPanel_DriftwoodTacklebox, PackPanel_FinewoodTacklebox, PackPanel_CarapaceTacklebox and PackPanel_FlametalTacklebox"); } else if (node.Kind != YamlNodeKind.Map) { if (node.Kind != YamlNodeKind.Null) { node.Error("a tacklebox takes station:, level:, cost: and cells:, as in { cells: 3 }"); } } else { TackleboxStats defaults = tackleboxKind.Defaults; int cells = RecipeYaml.Whole(node.Get("cells"), 0, 20, defaults.Cells); Stats[tackleboxKind.Id] = new TackleboxStats(RecipeYaml.Station(node, defaults), RecipeYaml.Level(node, defaults), RecipeYaml.Cost(node, defaults), cells); } } } public static class TackleboxGrave { [HarmonyPatch(typeof(TombStone), "EasyFitInInventory")] public static class EasyFit { [HarmonyPrefix] public static void Prefix(TombStone __instance, Player player) { Container component = ((Component)__instance).GetComponent<Container>(); ExtraRoom = TackleboxSettings.Cells(TackleboxCatalog.Of((InventoryState.IsLocal((Humanoid)(object)player) && (Object)(object)component != (Object)null) ? Waiting(component.GetInventory()) : null)); } [HarmonyFinalizer] public static void Finalizer() { ExtraRoom = 0; } } public static int ExtraRoom { get; private set; } public static void PutBackFirst(Inventory inventory, Inventory grave) { //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_0045: 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) ItemData val = Waiting(grave); IReadOnlyList<Vector2i> readOnlyList = InventoryState.CellsOf(SlotKind.Tacklebox); if (val != null && readOnlyList.Count != 0 && inventory.GetItemAt(readOnlyList[0].x, readOnlyList[0].y) == null && inventory.AddItem(val, val.m_stack, readOnlyList[0].x, readOnlyList[0].y, false)) { grave.RemoveItem(val); LayoutApply.Apply(InventoryState.Player, dropOverflow: true); } } private static ItemData Waiting(Inventory grave) { //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_0040: Unknown result type (might be due to invalid IL or missing references) //IL_0045: Unknown result type (might be due to invalid IL or missing references) if (grave == null || !InventoryState.Active || InventoryState.CellsOf(SlotKind.Tackle).Count > 0 || !TackleboxSettings.Active) { return null; } Vector2i val = SlotCellInGrave(grave); foreach (ItemData allItem in grave.GetAllItems()) { if (allItem.m_gridPos == val && TackleboxCatalog.Of(allItem) != null) { return allItem; } } return null; } private static Vector2i SlotCellInGrave(Inventory grave) { //IL_0028: 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_002e: 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_0041: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Unknown result type (might be due to invalid IL or missing references) InventoryLayout layout = InventoryState.Layout; int num = layout.IndexOf(new Slot(SlotKind.Tacklebox, 1).Id); if (num < 0) { return new Vector2i(-1, -1); } Vector2i val = layout.CellOf(num); return new Vector2i(val.x, val.y + BackpackGrave.WaitingRows(grave)); } } public sealed class TackleboxKind : CraftedKind { public TackleboxStats Defaults { get; } public TackleboxStats Stats { get; internal set; } public override CraftStats Recipe => Stats; public override CraftStats DefaultRecipe => Defaults; public override bool Craftable => TackleboxSettings.Active; public TackleboxKind(string id, string word, string name, string look, float weight, TackleboxStats defaults) : base(id, "tacklebox", word, name, look, weight) { Defaults = defaults; Stats = defaults; } } public static class TackleboxPrefab { private const string Bundle = "packpanel_tackleboxes"; public static void Install(Harmony harmony) { NetPrefabs.OnSceneAwake(harmony, delegate(ZNetScene scene) { Setup(scene, harmony); }); } private static void Setup(ZNetScene scene, Harmony harmony) { foreach (TackleboxKind item in TackleboxCatalog.All) { try { if ((Object)(object)item.Item == (Object)null) { Build(scene, item); } NetPrefabs.Register(scene, item.Item); ItemPrefabs.Register(harmony, item.Item); } catch (Exception ex) { Plugin.Log.LogError((object)("the " + item.Name + " could not be built and is not in the game: " + ex.Message)); } } CraftRecipes.Install(ObjectDB.instance); } private static void Build(ZNetScene scene, TackleboxKind kind) { GameObject model = CraftedModels.Model("packpanel_tackleboxes", kind); Material look = CraftedModels.Look(scene, model); kind.Item = CraftedItem.Build(scene.GetPrefab("TrollHide"), CraftedModels.Dressed(model, "model", look), kind); Plugin.Log.LogInfo((object)(kind.Name + " ready: " + kind.Id)); } } public static class TackleboxSettings { public const string Section = "6. Tacklebox"; public static ConfigEntry<bool> Enabled { get; private set; } public static ConfigEntry<string> TackleItems { get; private set; } public static bool Active { get { if (Enabled.Value) { return InventorySettings.Enabled.Value; } return false; } } public static int Cells(TackleboxKind kind) { if (!Active || kind == null) { return 0; } return kind.Stats.Cells; } public static void Bind(SyncedConfiguration synced) { Enabled = synced.Bind("6. Tacklebox", "Tacklebox", true, "A Tacklebox slot right of the key ring button, and PackPanel's four tackleboxes, from the Driftwood Tacklebox to the Flametal Tacklebox (their cells, stations and costs are in PackPanel.Tackleboxes.yml). Put a box in the slot, by dropping it there or right clicking it, then right click it there to open it: a pop-up under the slot panel with its cells. Bait you pick up or take from a chest goes into it first, the fishing rod takes its bait from it first, and right clicking a bait in it fishes with that bait. Taking the box out moves what its cells hold into free cells and drops what does not fit at your feet. Off: no slot, none can be crafted.", true, null); TackleItems = synced.Bind("6. Tacklebox", "Tackle Items", "", "Items a tacklebox takes besides fishing bait, as prefab names, comma separated (chum, another mod's lures). Empty: bait only.", true, null); } } public static class TackleboxSlot { private static InventoryElement shownOn; private static int shownUsed = -1; private static int shownCells = -1; public static void Refresh(InventoryElement element) { //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_0041: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)element == (Object)null || !element.m_used || !Tacklebox.Active) { return; } IReadOnlyList<Vector2i> readOnlyList = InventoryState.CellsOf(SlotKind.Tackle); Inventory inventory = ((Humanoid)InventoryState.Player).GetInventory(); int num = 0; foreach (Vector2i item in readOnlyList) { num += ((inventory.GetItemAt(item.x, item.y) != null) ? 1 : 0); } ((Behaviour)element.m_amount).enabled = true; if (!((Object)(object)element == (Object)(object)shownOn) || num != shownUsed || readOnlyList.Count != shownCells) { element.m_amount.text = num + "/" + readOnlyList.Count; shownOn = element; shownUsed = num; shownCells = readOnlyList.Count; } } } public sealed class TackleboxStats : CraftStats { public int Cells { get; } public TackleboxStats(string station, int level, string cost, int cells) : base(station, level, cost) { Cells = cells; } } [HarmonyPatch(typeof(Humanoid), "UseItem")] public static class TackleboxUse { [HarmonyPrefix] public static bool Prefix(Humanoid __instance, Inventory inventory, ItemData item, bool fromInventoryGui) { //IL_004c: Unknown result type (might be due to invalid IL or missing references) if (!fromInventoryGui || item == null || !InventoryState.IsLocal(__instance)) { return true; } Inventory val = inventory ?? __instance.GetInventory(); if (!InventoryState.Manages(val) || !val.ContainsItem(item)) { return true; } if (TackleboxCatalog.Of(item) != null) { return !Box(val, item); } if (TackleRules.IsBait(item)) { Slot slot = InventoryState.SlotAt(val, item.m_gridPos); if (slot != null && slot.Kind == SlotKind.Tackle) { Choose(__instance, item); return false; } } return true; } private static bool Box(Inventory inventory, ItemData box) { //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_0043: 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_006a: Unknown result type (might be due to invalid IL or missing references) //IL_0058: Unknown result type (might be due to invalid IL or missing references) //IL_005d: Unknown result type (might be due to invalid IL or missing references) IReadOnlyList<Vector2i> readOnlyList = InventoryState.CellsOf(SlotKind.Tacklebox); if (readOnlyList.Count == 0) { return false; } if (box.m_gridPos == readOnlyList[0]) { if (Tacklebox.Active) { TackleState.Toggle(); } return true; } ItemData itemAt = inventory.GetItemAt(readOnlyList[0].x, readOnlyList[0].y); if (itemAt != null) { itemAt.m_gridPos = box.m_gridPos; } box.m_gridPos = readOnlyList[0]; inventory.Changed(false, false); return true; } private static void Choose(Humanoid player, ItemData bait) { if (bait.m_equipped) { player.UnequipItem(bait, true); return; } ItemData ammoItem = player.GetAmmoItem(); if (ammoItem != null) { player.UnequipItem(ammoItem, false); } player.EquipItem(bait, true); } } public static class TackleboxWear { public static void Tick(Player player) { if (!((Character)player).IsDead() && InventoryState.IsLocal((Humanoid)(object)player) && InventoryState.Active) { TackleboxKind kind = Tacklebox.InSlot(((Humanoid)player).GetInventory(), InventoryState.Layout); if (InventoryState.CellsOf(SlotKind.Tackle).Count != TackleboxSettings.Cells(kind)) { LayoutApply.Apply(player, dropOverflow: true); } } } } public static class TackleboxWords { public static string Tacklebox { get; private set; } public static string Bait { get; private set; } public static string Full { get; private set; } public static void Register() { foreach (TackleboxKind item in TackleboxCatalog.All) { Language.Add(item.Token.Substring(1), item.Name); } Tacklebox = Language.Add("packpanel_tackle", "Tackle"); Bait = Language.Add("packpanel_bait", "Bait"); Full = Language.Add("packpanel_tacklebox_full", "The tacklebox is full"); DescribeAll(); } public static void DescribeAll() { foreach (TackleboxKind item in TackleboxCatalog.All) { Language.Add(item.DescriptionToken.Substring(1), Describe(item)); } } private static string Describe(TackleboxKind kind) { int cells = kind.Stats.Cells; string text = ((cells == 1) ? "one cell" : $"{cells} cells"); return kind.Look + " Put it in your Tacklebox slot and right click it there to open it: " + text + " for bait, which the fishing rod takes first. Right click a bait in it to fish with that one."; } } public static class TackleCells { public const float CellScale = 0.8f; public const int Columns = 4; private static readonly List<InventoryElement> elements = new List<InventoryElement>(); public static int Count => elements.Count; public static InventoryElement At(int number) { if (number < 1 || number > elements.Count) { return null; } return elements[number - 1]; } public static void Clear() { elements.Clear(); } public static bool Adopt(InventoryGui gui, InventoryElement element, Slot slot) { //IL_0051: 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_005e: Unknown result type (might be due to invalid IL or missing references) //IL_005f: Unknown result type (might be due to invalid IL or missing references) //IL_0060: 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_0078: Unknown result type (might be due to invalid IL or missing references) //IL_0079: 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_0080: 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_0090: 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) RectTransform val = TacklePopup.Find(gui); if ((Object)(object)val == (Object)null || slot.Number < 1) { return false; } while (elements.Count < slot.Number) { elements.Add(null); } elements[slot.Number - 1] = element; RectTransform val2 = (RectTransform)((Component)element).transform; ((Transform)val2).SetParent((Transform)(object)val, false); Vector2 val3 = default(Vector2); ((Vector2)(ref val3))..ctor(0f, 1f); val2.pivot = val3; Vector2 anchorMin = (val2.anchorMax = val3); val2.anchorMin = anchorMin; ((Transform)val2).localScale = Vector3.one * 0.8f; Image component = ((Component)element).GetComponent<Image>(); if ((Object)(object)component != (Object)null) { ((Graphic)component).color = Color.white; } return true; } public static void Arrange(float pad, float step) { //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Unknown result type (might be due to invalid IL or missing references) for (int i = 0; i < elements.Count; i++) { if ((Object)(object)elements[i] != (Object)null) { ((RectTransform)((Component)elements[i]).transform).anchoredPosition = new Vector2(pad + (float)(i % 4) * step, 0f - (pad + (float)(i / 4) * step)); } } } public static bool Shows(int number) { InventoryElement val = At(number); if ((Object)(object)val != (Object)null) { return ((Component)val).gameObject.activeInHierarchy; } return false; } public static void Refresh(Inventory inventory) { //IL_0028: 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) foreach (InventoryElement element in elements) { if (!((Object)(object)element == (Object)null) && element.m_used) { ItemData itemAt = inventory.GetItemAt(element.Position.x, element.Position.y); ((Behaviour)element.m_amount).enabled = itemAt != null && itemAt.m_stack > 1; if (((Behaviour)element.m_amount).enabled) { element.m_amount.text = itemAt.m_stack.ToString(); } } } } } [HarmonyPatch(typeof(InventoryGui), "OnSelectedItem")] public static class TackleClicks { [HarmonyPrefix] [HarmonyPriority(800)] public static bool Prefix(InventoryGui __instance, InventoryGrid grid, ref ItemData item, ref Vector2i pos) { //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_005f: Unknown result type (might be due to invalid IL or missing references) //IL_0064: 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_007b: Unknown result type (might be due to invalid IL or missing references) //IL_007c: 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_008e: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)__instance.m_dragGo == (Object)null || (Object)(object)grid != (Object)(object)__instance.m_playerGrid || !Tacklebox.Active) { return true; } Slot slot = InventoryState.SlotAt(grid.GetInventory(), pos); if (slot == null || slot.Kind != SlotKind.Tacklebox || !TackleRules.IsTackle(__instance.m_dragItem)) { return true; } Vector2i val = Target(grid.GetInventory(), __instance.m_dragItem); if (val.x < 0) { Messages.Center(TackleboxWords.Full); return false; } pos = val; item = grid.GetInventory().GetItemAt(val.x, val.y); return true; } private static Vector2i Target(Inventory inventory, ItemData dragged) { //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_0020: 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_0035: 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_003e: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Unknown result type (might be due to invalid IL or missing references) //IL_0076: 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_0091: Unknown result type (might be due to invalid IL or missing references) IReadOnlyList<Vector2i> readOnlyList = InventoryState.CellsOf(SlotKind.Tackle); Vector2i val = default(Vector2i); ((Vector2i)(ref val))..ctor(-1, -1); foreach (Vector2i item in readOnlyList) { ItemData itemAt = inventory.GetItemAt(item.x, item.y); if (itemAt == null && val.x < 0) { val = item; } if (itemAt != null && itemAt != dragged && itemAt.IsSameType(dragged) && itemAt.m_quality == dragged.m_quality && itemAt.m_stack < itemAt.m_shared.m_maxStackSize) { return item; } } return val; } } public static class TackleGamepad { public static void Follow(bool open) { //IL_006a: Unknown result type (might be due to invalid IL or missing references) //IL_0059: Unknown result type (might be due to invalid IL or missing references) //IL_0085: Unknown result type (might be due to invalid IL or missing references) InventoryGrid val = (((Object)(object)InventoryGui.instance != (Object)null) ? InventoryGui.instance.m_playerGrid : null); IReadOnlyList<Vector2i> readOnlyList = InventoryState.CellsOf(SlotKind.Tackle); IReadOnlyList<Vector2i> readOnlyList2 = InventoryState.CellsOf(SlotKind.Tacklebox); if ((Object)(object)val == (Object)null || readOnlyList.Count == 0 || readOnlyList2.Count == 0 || !InventoryState.Active || !ZInput.IsExclusiveGamepadActive()) { return; } if (open) { KeyRingGamepad.Select(val, readOnlyList[0]); return; } Slot slot = InventoryState.Layout.SlotAt(val.m_selected); if (slot != null && slot.Kind == SlotKind.Tackle) { KeyRingGamepad.Select(val, readOnlyList2[0]); } } } public static class TacklePopup { public const string Name = "PackPanel_tacklebox"; private static float slotLeft; private static float boxCentre; private static float top; private static float step = 70f; private static bool placed; private static bool fresh; public static RectTransform Find(InventoryGui gui) { if (!((Object)(object)gui != (Object)null)) { return null; } Transform obj = ((Transform)gui.m_player).Find("PackPanel_tacklebox"); return (RectTransform)(object)((obj is RectTransform) ? obj : null); } public static void Place(InventoryGui gui, RectTransform slotPanel, SlotPanelLayout plan, float gridStep) { //IL_005f: Unknown result type (might be due to invalid IL or missing references) //IL_007c: Unknown result type (might be due to invalid IL or missing references) //IL_0086: Unknown result type (might be due to invalid IL or missing references) //IL_009d: Unknown result type (might be due to invalid IL or missing references) //IL_00a8: Unknown result type (might be due to invalid IL or missing references) RectTransform val = Find(gui); placed = (Object)(object)slotPanel != (Object)null && (plan?.TackleboxCell.HasValue ?? false); fresh = true; if (!placed) { if (val != null) { ((Component)val).gameObject.SetActive(false); } return; } if ((Object)(object)val == (Object)null) { Make(gui); } step = gridStep; slotLeft = slotPanel.anchoredPosition.x; boxCentre = slotLeft + SlotPanel.CellPosition(plan.TackleboxCell.Value, step).x + 32f; top = slotPanel.anchoredPosition.y - slotPanel.sizeDelta.y - 12f; } public static void Refresh(InventoryGui gui) { RectTransform val = Find(gui); if ((Object)(object)val == (Object)null) { return; } bool flag = placed && TackleState.Open && Tacklebox.Active && TackleCells.Count > 0; if (((Component)val).gameObject.activeSelf != flag) { ((Component)val).gameObject.SetActive(flag); } if (flag) { if (fresh) { Arrange(val); } PopupPlace.Under(gui, val, slotLeft, boxCentre, top); TackleCells.Refresh(((Humanoid)InventoryState.Player).GetInventory()); } } private static void Arrange(RectTransform popup) { //IL_0062: Unknown result type (might be due to invalid IL or missing references) fresh = false; float num = step * 0.8f; float num2 = (step - 64f) * 0.8f; int num3 = Mathf.Min(4, TackleCells.Count); int num4 = (TackleCells.Count + 4 - 1) / 4; float pad = SlotPanel.Pad; popup.sizeDelta = new Vector2(pad * 2f + (float)num3 * num - num2, pad * 2f + (float)num4 * num - num2); GridSkin.Panel(((Component)popup).GetComponent<Image>()); TackleCells.Arrange(pad, num); } private static void Make(InventoryGui gui) { //IL_0016: Unknown result type (might be due to invalid IL or missing references) RectTransform obj = SlotPanel.MakePanel(gui, "PackPanel_tacklebox"); obj.pivot = new Vector2(0f, 1f); GridSkin.Panel(((Component)obj).GetComponent<Image>()); } } [HarmonyPatch(typeof(Inventory), "AddItem", new Type[] { typeof(ItemData) })] public static class TackleRouting { [HarmonyPrefix] public static bool Prefix(Inventory __instance, ItemData item, ref bool __result, bool __runOriginal) { if (!__runOriginal) { return false; } if (item == null || !InventoryState.Manages(__instance) || !Tacklebox.Active || !TackleRules.IsTackle(item) || !TakeIn(__instance, item)) { return true; } __result = true; return false; } public static bool TakeIn(Inventory inventory, ItemData item) { //IL_0012: 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_001a: 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_0049: 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_0053: 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) IReadOnlyList<Vector2i> readOnlyList = InventoryState.CellsOf(SlotKind.Tackle); foreach (Vector2i item2 in readOnlyList) { if (Stack(inventory, item, item2)) { return true; } } foreach (Vector2i item3 in readOnlyList) { if (inventory.GetItemAt(item3.x, item3.y) == null) { Place(inventory, item, item3); return true; } } return false; } private static bool Stack(Inventory inventory, ItemData item, Vector2i cell) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Unknown result type (might be due to invalid IL or missing references) ItemData itemAt = inventory.GetItemAt(cell.x, cell.y); if (itemAt == null || itemAt == item || !itemAt.IsSameType(item) || itemAt.m_quality != item.m_quality) { return false; } int num = Math.Min(itemAt.m_shared.m_maxStackSize - itemAt.m_stack, item.m_stack); if (num <= 0) { return false; } itemAt.m_stack += num; item.m_stack -= num; inventory.Changed(false, false); return item.m_stack <= 0; } private static void Place(Inventory inventory, ItemData item, Vector2i cell) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0002: Unknown result type (might be due to invalid IL or missing references) item.m_gridPos = cell; if (!inventory.ContainsItem(item)) { inventory.m_inventory.Add(item); } inventory.Changed(false, false); } } public static class TackleRules { private const string Rod = "FishingRod"; private static string baitType; private static string parsed; private static HashSet<string> listed = new HashSet<string>(StringComparer.OrdinalIgnoreCase); public static bool IsTackle(ItemData item) { if (item != null) { if (!IsBait(item)) { if (IsListed(item) && !SlotRules.IsCoins(item)) { return !KeyRing.IsKey(item); } return false; } return true; } return false; } public static bool IsBait(ItemData item) { //IL_0009: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Invalid comparison between Unknown and I4 if (item == null || (int)item.m_shared.m_itemType != 23) { return false; } string text = BaitType(); if (text != null) { return item.m_shared.m_ammoType == text; } return true; } private static string BaitType() { if (baitType == null && (Object)(object)ObjectDB.instance != (Object)null) { GameObject itemPrefab = ObjectDB.instance.GetItemPrefab("FishingRod"); ItemDrop val = (((Object)(object)itemPrefab != (Object)null) ? itemPrefab.GetComponent<ItemDrop>() : null); string text = (((Object)(object)val != (Object)null) ? val.m_itemData.m_shared.m_ammoType : null); baitType = (string.IsNullOrEmpty(text) ? null : text); } return baitType; } private static bool IsListed(ItemData item) { string text = TackleboxSettings.TackleItems.Value ?? ""; if (text != parsed) { Parse(text); } if (listed.Count > 0) { return listed.Contains(ItemNames.PrefabName(item)); } return false; } private static void Parse(string value) { HashSet<string> hashSet = new HashSet<string>(StringComparer.OrdinalIgnoreCase); string[] array = value.Split(new char[1] { ',' }); foreach (string text in array) { if (text.Trim().Length > 0) { hashSet.Add(text.Trim()); } } listed = hashSet; parsed = value; } } public static class TackleState { [HarmonyPatch(typeof(InventoryGui), "Show")] public static class Shown { [HarmonyPostfix] public static void Postfix() { Close(); } } [HarmonyPatch(typeof(InventoryGui), "Hide")] public static class Hidden { [HarmonyPostfix] public static void Postfix() { Close(); } } public static bool Open { get; private set; } public static void Toggle() { Open = !Open; if (Open) { KeyRingState.Close(); } TackleGamepad.Follow(Open); } public static void Close() { if (Open) { Open = false; TackleGamepad.Follow(open: false); } } } } namespace PackPanel.Slots { [HarmonyPatch(typeof(Inventory), "GetAmmoItem")] public static class AmmoSearch { [HarmonyPrefix] public static bool Prefix(Inventory __instance, string ammoName, string matchPrefabName, ref ItemData __result) { if (!InventoryState.Manages(__instance)) { return true; } ItemData val = (Tacklebox.Active ? First(__instance, InventoryState.CellsOf(SlotKind.Tackle), ammoName, matchPrefabName) : null); val = val ?? First(__instance, InventoryState.CellsOf(SlotKind.Ammo), ammoName, matchPrefabName); if (val == null) { return true; } __result = val; return false; } private static ItemData First(Inventory inventory, IReadOnlyList<Vector2i> cells, string ammoName, string prefab) { //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Unknown result type (might be due to invalid IL or missing references) foreach (Vector2i cell in cells) { ItemData itemAt = inventory.GetItemAt(cell.x, cell.y); if (itemAt != null && Fits(itemAt, ammoName, prefab)) { return itemAt; } } return null; } private static bool Fits(ItemData item, string ammoName, string prefab) { //IL_0006: 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_000f: Invalid comparison between Unknown and I4 //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Invalid comparison between Unknown and I4 //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Invalid comparison between Unknown and I4 ItemType itemType = item.m_shared.m_itemType; if (((int)itemType == 9 || (int)itemType == 23 || (int)itemType == 2) && item.m_shared.m_ammoType == ammoName) { if (prefab != null) { if ((Object)(object)item.m_dropPrefab != (Object)null) { return ((Object)item.m_dropPrefab).name == prefab; } return false; } return true; } return false; } } [HarmonyPatch(typeof(Inventory), "AddItem", new Type[] { typeof(ItemData) })] public static class CoinPurse { [HarmonyPrefix] public static bool Prefix(Inventory __instance, ItemData item, ref bool __result) { if (item == null || !InventoryState.Manages(__instance) || !SlotRules.IsCoins(item) || !TakeIn(__instance, item)) { return true; } __result = true; return false; } private static bool TakeIn(Inventory inventory, ItemData item) { //IL_0015: 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_0037: 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) IReadOnlyList<Vector2i> readOnlyList = InventoryState.CellsOf(SlotKind.Purse); if (readOnlyList.Count == 0) { return false; } ItemData itemAt = inventory.GetItemAt(readOnlyList[0].x, readOnlyList[0].y); if (itemAt == null) { item.m_gridPos = readOnlyList[0]; inventory.m_inventory.Add(item); inventory.Changed(false, false); return true; } if (!SlotRules.IsCoins(itemAt) || itemAt.m_quality != item.m_quality || itemAt.m_worldLevel != item.m_worldLevel) { return false; } int num = Math.Min(itemAt.m_shared.m_maxStackSize - itemAt.m_stack, item.m_stack); if (num <= 0) { return false; } itemAt.m_stack += num; item.m_stack -= num; inventory.Changed(false, false); return item.m_stack <= 0; } } [HarmonyPatch(typeof(InventoryGui), "OnSelectedItem")] public static class DragSettle { public sealed class Pair { public ItemData Dragged; public ItemData Target; } [HarmonyPrefix] public static bool Prefix(InventoryGui __instance, InventoryGrid grid, ItemData item, Vector2i pos, out Pair __state, bool __runOriginal) { //IL_0032: Unknown result type (might be due to invalid IL or missing references) __state = null; if (!__runOriginal) { return false; } bool flag = (Object)(object)__instance.m_dragGo != (Object)null; if (flag && !SlotDrop.Allowed(grid.GetInventory(), __instance.m_dragInventory, __instance.m_dragItem, __instance.m_dragAmount, pos)) { Messages.Center(Words.WrongSlot); return false; } if (!InventoryState.Active) { return true; } WornPlacement.Suspend(); __state = new Pair { Dragged = (flag ? __instance.m_dragItem : null), Target = item }; return true; } [HarmonyPostfix] public static void Postfix(Pair __state) { if (__state != null) { WornPlacement.Resume(); Settle(__state.Dragged); Settle(__state.Target); } } [HarmonyFinalizer] public static void Finalizer(Pair __state, Exception __exception) { if (__state != null && __exception != null) { WornPlacement.Resume(); } } private static void Settle(ItemData item) { //IL_0025: Unknown result type (might be due to invalid IL or missing references) Player player = InventoryState.Player; if (item == null || !InventoryState.Active || !((Humanoid)player).GetInventory().ContainsItem(item)) { return; } Slot slot = InventoryState.Layout.SlotAt(item.m_gridPos); SlotKind? slotKind = SlotRules.WornKindOf(item); if (slot != null && SlotRules.IsWorn(slot.Kind)) { if (!item.m_equipped && slotKind == slot.Kind) { ((Humanoid)player).EquipItem(item, true); } } else if (item.m_equipped && slotKind.HasValue && InventoryState.CellsOf(slotKind.Value).Count > 0) { ((Humanoid)player).UnequipItem(item, true); } } } public static class FoodCount { public const int GameFoods = 3; private const string FeastMasterGuid = "com.FeastMaster"; private const string FeastMasterSection = "0. Global Settings"; private const string FeastMasterKey = "Food Slots"; private static ConfigEntry<int> feastMaster; private static bool looked; public static event Action Changed; public static int Slots() { int val = (InventorySettings.FoodSlotsFollowEating.Value ? Eatable() : InventorySettings.FoodSlots.Value); return Math.Max(0, Math.Min(5, val)); } public static int Eatable() { return FeastMasterEntry()?.Value ?? 3; } private static ConfigEntry<int> FeastMasterEntry() { if (looked) { return feastMaster; } looked = true; if (!Chainloader.PluginInfos.TryGetValue("com.FeastMaster", out var value) || (Object)(object)value.Instance == (Object)null) { return null; } if (!value.Instance.Config.TryGetEntry<int>("0. Global Settings", "Food Slots", ref feastMaster)) { Plugin.Log.LogWarning((object)string.Format("FeastMaster is loaded but has no {0} / {1}; food slots follow the game's {2} foods", "0. Global Settings", "Food Slots", 3)); return null; } feastMaster.SettingChanged += delegate { FoodCount.Changed?.Invoke(); }; Plugin.Log.LogInfo((object)$"food slots follow FeastMaster's Food Slots ({feastMaster.Value})"); return feastMaster; } } public static class GravePatches { [HarmonyPatch(typeof(Player), "CreateTombStone")] public static class Tombstone { public sealed class Death { public KeptOnDeath Kept; } [HarmonyPrefix] public static void Prefix(Player __instance, out Death __state) { __state = (InventoryState.IsLocal((Humanoid)(object)__instance) ? new Death() : null); if (__state != null) { WornPlacement.Suspend(); __state.Kept = KeptOnDeath.Take(__instance); } } [HarmonyFinalizer] public static void Finalizer(Player __instance, Death __state) { if (__state != null) { __state.Kept?.Return(__instance); WornPlacement.Resume(); } } } [HarmonyPatch(typeof(Inventory), "MoveAll")] public static class TakeAll { [HarmonyPrefix] public static void Prefix(Inventory __instance, Inventory fromInventory, out bool __state) { __state = InventoryState.Manages(__instance) && IsGrave(fromInventory); ForeignTakeAll = InventoryState.Manages(__instance) && !__state; if (__state) { BackpackGrave.WearFirst(__instance, fromInventory); TackleboxGrave.PutBackFirst(__instance, fromInventory); } } [HarmonyPostfix] public static void Postfix(Inventory __instance, bool __state) { if (__state) { WearWhatCameBack(__instance); } } [HarmonyFinalizer] public static void Finalizer() { ForeignTakeAll = false; } } public static bool ForeignTakeAll { get; private set; } private static bool IsGrave(Inventory inventory) { TombStone[] array = Object.FindObjectsByType<TombStone>((FindObjectsSortMode)0); for (int i = 0; i < array.Length; i++) { Container component = ((Component)array[i]).GetComponent<Container>(); if ((Object)(object)component != (Object)null && component.GetInventory() == inventory) { return true; } } return false; } private static void WearWhatCameBack(Inventory inventory) { //IL_0021: Unknown result type (might be due to invalid IL or missing references) foreach (ItemData item in new List<ItemData>(inventory.GetAllItems())) { Slot slot = InventoryState.Layout.SlotAt(item.m_gridPos); if (slot != null && SlotRules.IsWorn(slot.Kind) && !item.m_equipped && SlotRules.WornKindOf(item) == slot.Kind) { ((Humanoid)InventoryState.Player).EquipItem(item, false); } } } } [HarmonyPatch(typeof(Container), "Load")] public static class GraveWidth { private const int LoadWidth = 32; [HarmonyPrefix] public static void Prefix(Container __instance, out bool __state) { __state = __instance.m_inventory != null && (Object)(object)((Component)__instance).GetComponent<TombStone>() != (Object)null; if (__state) { __instance.m_inventory.m_width = 32; } } [HarmonyPostfix] public static void Postfix(Container __instance, bool __state) { if (!__state) { return; } int num = __instance.m_width; foreach (ItemData allItem in __instance.m_inventory.GetAllItems()) { num = Math.Max(num, allItem.m_gridPos.x + 1); } __instance.m_inventory.m_width = num; } } public sealed class KeptOnDeath { private readonly List<ItemData> items = new List<ItemData>(); private readonly HashSet<ItemData> worn = new HashSet<ItemData>(); public static KeptOnDeath Take(Player player) { //IL_0043: Unknown result type (might be due to invalid IL or missing references) if (!InventorySettings.KeepSlotsOnDeath.Value || !InventoryState.Active) { return null; } KeptOnDeath keptOnDeath = new KeptOnDeath(); Inventory inventory = ((Humanoid)player).GetInventory(); foreach (ItemData item in new List<ItemData>(inventory.GetAllItems())) { Slot slot = InventoryState.Layout.SlotAt(item.m_gridPos); if (slot != null && Kept(slot.Kind)) { keptOnDeath.items.Add(item); if (item.m_equipped) { keptOnDeath.worn.Add(item); } inventory.m_inventory.Remove(item); } } if (keptOnDeath.items.Count <= 0) { return null; } return keptOnDeath; } private static bool Kept(SlotKind kind) { if (kind != SlotKind.Purse && kind != SlotKind.Key && kind != SlotKind.Tackle) { return kind != SlotKind.Retired; } return false; } public void Return(Player player) { Inventory inventory = ((Humanoid)player).GetInventory(); foreach (ItemData item in items) { item.m_equipped = worn.Contains(item); if (!inventory.ContainsItem(item)) { inventory.m_inventory.Add(item); } } inventory.Changed(false, false); Plugin.Log.LogInfo((object)$"kept {items.Count} slot items through death ({worn.Count} worn)"); } } public sealed class Slot { public SlotKind Kind { get; } public int Number { get; } public string Id { get; } public Slot(SlotKind kind, int number) { Kind = kind; Number = number; Id = kind.ToString().ToLowerInvariant() + number; } public Slot(string id) { Kind = SlotKind.Retired; Number = 0; Id = id; } public override string ToString() { return Id; } } public static class SlotAddPatches { [HarmonyPatch(typeof(InventoryGrid), "DropItem")] public static class Drop { [HarmonyPrefix] [HarmonyPriority(600)] public static bool Prefix(InventoryGrid __instance, Inventory fromInventory, ItemData item, int amount, Vector2i pos, ref bool __result) { //IL_0009: Unknown result type (might be due to invalid IL or missing references) if (SlotDrop.Allowed(__instance.GetInventory(), fromInventory, item, amount, pos)) { return true; } Messages.Center(Words.WrongSlot); __result = false; return false; } } [HarmonyPatch(typeof(Inventory), "AddItem", new Type[] { typeof(ItemData), typeof(int), typeof(int), typeof(int), typeof(bool) })] public static class AtCell { [HarmonyPrefix] public static bool Prefix(Inventory __instance, ItemData item, int x, int y, bool skipValidPositionCheck, ref bool __result) { //IL_001c: 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) if (skipValidPositionCheck || !InventoryState.Manages(__instance)) { return true; } Vector2i pos = default(Vector2i); ((Vector2i)(ref pos))..ctor(x, y); if (InventoryState.Layout.IsMain(pos) || (!GravePatches.ForeignTakeAll && SlotDrop.Takes(__instance, pos, item))) { return true; } __result = false; return false; } } [HarmonyPatch(typeof(Inventory), "AddItem", new Type[] { typeof(ItemData), typeof(Vector2i) })] public static class AtPosition { [HarmonyPrefix] public static bool Prefix(Inventory __instance, ItemData item, Vector2i pos, ref bool __result) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) if (SlotDrop.Takes(__instance, pos, item)) { return true; } __result = __instance.AddItem(item); return false; } } } public static class SlotCounts { public static int Utility => Group(InventorySettings.UtilitySlots.Value); public static int Food { get { if (!Shared) { return FoodCount.Slots(); } return Group(0); } } public static int Mead => Group(InventorySettings.MeadSlots.Value); public static int Ammo => Group(InventorySettings.AmmoSlots.Value); public static bool Shared => InventorySettings.SlotsPerGroup.Value > 0; private static int Group(int own) { int val = (Shared ? InventorySettings.SlotsPerGroup.Value : own); return Math.Max(0, Math.Min(5, val)); } } public static class SlotDrop { public static bool Allowed(Inventory target, Inventory from, ItemData item, int amount, Vector2i pos) { //IL_0009: 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_0024: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Unknown result type (might be due to invalid IL or missing references) if (target == null || item == null) { return true; } ItemData itemAt = target.GetItemAt(pos.x, pos.y); if (itemAt == item) { return true; } if (!Takes(target, pos, item)) { return false; } if (itemAt != null && Swaps(itemAt, item, amount)) { return Takes(from, item.m_gridPos, itemAt); } return true; } public static bool Takes(Inventory inventory, Vector2i pos, ItemData item) { //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Unknown result type (might be due to invalid IL or missing references) if (!InventoryState.Manages(inventory) || InventoryState.Layout.IsMain(pos)) { return true; } Slot slot = InventoryState.Layout.SlotAt(pos); if (slot != null) { return SlotRules.Accepts(slot, item); } return false; } private static bool Swaps(ItemData at, ItemData item, int amount) { if (at.m_shared.m_name != item.m_shared.m_name || (item.m_shared.m_maxQuality > 1 && at.m_quality != item.m_quality) || at.m_shared.m_maxStackSize == 1) { return item.m_stack == amount; } return false; } } public enum SlotKind { Head, Chest, Legs, Back, Backpack, Utility, Food, Mead, Ammo, Purse, Retired, Key, Tacklebox, Tackle } public static class SlotRules { public const string CoinsName = "$item_coins"; public static bool IsWorn(SlotKind kind) { if (kind > SlotKind.Back) { return kind == SlotKind.Utility; } return true; } public static bool Accepts(Slot slot, ItemData item) { if (slot.Kind != SlotKind.Key) { return Accepts(slot.Kind, item); } if (item != null) { return KeyRing.NumberOf(item) == slot.Number; } return true; } public static bool Accepts(SlotKind kind, ItemData item) { if (item == null) { return true; } switch (kind) { case SlotKind.Backpack: return IsBackpack(item); case SlotKind.Food: return IsFood(item); case SlotKind.Mead: if (Is(item, (ItemType)2)) { return !IsFood(item); } return false; case SlotKind.Ammo: if (!Is(item, (ItemType)9)) { return Is(item, (ItemType)23); } return true; case SlotKind.Purse: return IsCoins(item); case SlotKind.Key: return KeyRing.IsKey(item); case SlotKind.Tacklebox: return TackleboxCatalog.Of(item) != null; case SlotKind.Tackle: return TackleRules.IsTackle(item); case SlotKind.Retired: return false; default: return WornKindOf(item) == kind; } } public static SlotKind? WornKindOf(ItemData item) { //IL_0006: 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_000e: Invalid comparison between Unknown and I4 //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Invalid comparison between Unknown and I4 //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Invalid comparison between Unknown and I4 //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Invalid comparison between Unknown and I4 //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Invalid comparison between Unknown and I4 //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Invalid comparison between Unknown and I4 ItemType itemType = item.m_shared.m_itemType; if ((int)itemType <= 7) { if ((int)itemType == 6) { return SlotKind.Head; } if ((int)itemType == 7) { return SlotKind.Chest; } } else { if ((int)itemType == 11) { return SlotKind.Legs; } if ((int)itemType == 17) { return SlotKind.Back; } if ((int)itemType == 18) { return SlotKind.Utility; } } return null; } public static bool IsCoins(ItemData item) { return item.m_shared.m_name == "$item_coins"; } public static bool IsFood(ItemData item) { //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_000e: Invalid comparison between Unknown and I4 SharedData shared = item.m_shared; if ((int)shared.m_itemType == 2) { if (!(shared.m_food > 0f) && !(shared.m_foodStamina > 0f)) { return shared.m_foodEitr > 0f; } return true; } return false; } public static bool IsBackpack(ItemData item) { if (BackpackCatalog.Of(item) != null) { return true; } string text = (((Object)(object)item.m_dropPrefab != (Object)null) ? ((Object)item.m_dropPrefab).name : ""); if (text.IndexOf("backpack", StringComparison.OrdinalIgnoreCase) >= 0) { return true; } string[] array = InventorySettings.BackpackItems.Value.Split(new char[1] { ',' }); foreach (string text2 in array) { if (text2.Trim().Length > 0 && string.Equals(text2.Trim(), text, StringComparison.OrdinalIgnoreCase)) { return true; } } return false; } private static bool Is(ItemData item, ItemType type) { //IL_0006: 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) return item.m_shared.m_itemType == type; } } [HarmonyPatch(typeof(Inventory), "StackAll")] public static class StackAllGuard { [HarmonyPrefix] public static void Prefix(Inventory fromInventory, out List<ItemData> __state) { __state = (InventoryState.Manages(fromInventory) ? UnwornSlotItems(fromInventory) : null); if (__state == null) { return; } foreach (ItemData item in __state) { fromInventory.m_inventory.Remove(item); } } [HarmonyFinalizer] public static void Finalizer(Inventory fromInventory, List<ItemData> __state) { if (__state == null || __state.Count == 0) { return; } foreach (ItemData item in __state) { if (!fromInventory.ContainsItem(item)) { fromInventory.m_inventory.Add(item); } } fromInventory.Changed(false, false); } public static bool InSlot(Inventory inventory, ItemData item) { //IL_0005: Unknown result type (might be due to invalid IL or missing references) if (item != null) { return InventoryState.SlotAt(inventory, item.m_gridPos) != null; } return false; } private static List<ItemData> UnwornSlotItems(Inventory inventory) { List<ItemData> list = new List<ItemData>(); foreach (ItemData allItem in inventory.GetAllItems()) { if (InSlot(inventory, allItem) && !allItem.m_equipped) { list.Add(allItem); } } return list; } } [HarmonyPatch(typeof(Inventory), "MoveAll")] public static class TakeAllRouting { [HarmonyPrefix] public static void Prefix(Inventory __instance, out HashSet<ItemData> __state) { bool flag = InventoryState.Manages(__instance) && (KeyRing.Active || Tacklebox.Active); __state = (flag ? new HashSet<ItemData>(__instance.GetAllItems()) : null); } [HarmonyPostfix] public static void Postfix(Inventory __instance, HashSet<ItemData> __state) { //IL_002e: Unknown result type (might be due to invalid IL or missing references) if (__state == null) { return; } foreach (ItemData item in new List<ItemData>(__instance.GetAllItems())) { if (!__state.Contains(item) && InventoryState.Layout.IsMain(item.m_gridPos) && Route(__instance, item) && item.m_stack <= 0) { __instance.RemoveItem(item); } } } private static bool Route(Inventory inventory, ItemData item) { if (KeyRing.IsKey(item)) { return KeyRouting.TakeIn(inventory, item); } if (Tacklebox.Active && TackleRules.IsTackle(item)) { return TackleRouting.TakeIn(inventory, item); } return false; } } } namespace PackPanel.Ring { public static class KeyRing { private static string parsed; private static List<string> prefabs = new List<string>(); private static string[] sharedNames; public static bool On { get { if (InventorySettings.Enabled.Value) { return KeyRingSettings.KeyRing.Value; } return false; } } public static bool Active { get { if (InventoryState.Active) { return InventoryState.CellsOf(SlotKind.Key).Count > 0; } return false; } } public static IReadOnlyList<string> Prefabs { get { Parse(); return prefabs; } } public static int NumberOf(string prefab) { IReadOnlyList<string> readOnlyList = Prefabs; for (int i = 0; i < readOnlyList.Count; i++) { if (string.Equals(readOnlyList[i], prefab, StringComparison.OrdinalIgnoreCase)) { return i + 1; } } return 0; } public static int NumberOf(ItemData item) { if (item == null) { return 0; } return NumberOf(ItemNames.PrefabName(item)); } public static bool IsKey(ItemData item) { return NumberOf(item) > 0; } public static Vector2i CellOf(InventoryLayout layout, ItemData item) { //IL_0028: 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) int num = NumberOf(item); IReadOnlyList<Vector2i> readOnlyList = layout?.CellsOf(SlotKind.Key); if (num <= 0 || readOnlyList == null || num > readOnlyList.Count) { return new Vector2i(-1, -1); } return readOnlyList[num - 1]; } public static Vector2i CellOf(ItemData item) { //IL_0015: 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) if (!InventoryState.Active) { return new Vector2i(-1, -1); } return CellOf(InventoryState.Layout, item); } public static ItemData Key(int number) { IReadOnlyList<string> readOnlyList = Prefabs; GameObject val = ((number >= 1 && number <= readOnlyList.Count && (Object)(object)ObjectDB.instance != (Object)null) ? ObjectDB.instance.GetItemPrefab(readOnlyList[number - 1]) : null); ItemDrop val2 = (((Object)(object)val != (Object)null) ? val.GetComponent<ItemDrop>() : null); if (!((Object)(object)val2 != (Object)null)) { return null; } return val2.m_itemData; } public static int[] Counts(Inventory inventory) { int[] array = new int[Prefabs.Count + 1]; foreach (ItemData allItem in inventory.GetAllItems()) { for (int i = 1; i < array.Length; i++) { if (allItem.m_shared.m_name == SharedName(i)) { array[i] += allItem.m_stack; } } } return array; } private static string SharedName(int number) { if (sharedNames == null || sharedNames.Length != Prefabs.Count) { sharedNames = new string[Prefabs.Count]; } if (sharedNames[number - 1] == null) { sharedNames[number - 1] = Key(number)?.m_shared.m_name; } return sharedNames[number - 1]; } private static void Parse() { string text = KeyRingSettings.KeyItems.Value ?? ""; if (text == parsed) { return; } sharedNames = null; List<string> list = new List<string>(); string[] array = text.Split(new char[1] { ',' }); foreach (string text2 in array) { string name = text2.Trim(); if (name.Length > 0 && !list.Exists((string known) => string.Equals(known, name, StringComparison.OrdinalIgnoreCase))) { list.Add(name); } } prefabs = list; parsed = text; } } public static class KeyRingButton { public const string Name = "PackPanel_keyring_button"; private static InventoryElement button; private static string shownList; public static void Place(InventoryGui gui, RectTransform panel, SlotPanelLayout plan, float step, TMP_FontAsset font) { //IL_0077: Unknown result type (might be due to invalid IL or missing references) //IL_007c: 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_0090: 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_0097: 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_009e: Unknown result type (might be due to invalid IL or missing references) //IL_00ad: Unknown result type (might be due to invalid IL or missing references) //IL_00b3: Unknown result type (might be due to invalid IL or missing references) Transform val = (((Object)(object)panel != (Object)null) ? ((Transform)panel).Find("PackPanel_keyring_button") : null); if ((Object)(object)panel == (Object)null || plan == null || !plan.RingCell.HasValue) { if (val != null) { ((Component)val).gameObject.SetActive(false); } button = null; return; } button = (((Object)(object)val != (Object)null) ? ((Component)val).GetComponent<InventoryElement>() : Make(gui, panel)); RectTransform val2 = (RectTransform)((Component)button).transform; Vector2 val3 = default(Vector2); ((Vector2)(ref val3))..ctor(0f, 1f); val2.pivot = val3; Vector2 anchorMin = (val2.anchorMax = val3); val2.anchorMin = anchorMin; val2.anchoredPosition = SlotPanel.CellPosition(plan.RingCell.Value, step); ((Component)button).gameObject.SetActive(true); GridSkin.Cell(button); SlotLabels.Set(button, new Slot(SlotKind.Key, 0), font); shownList = null; } public static void Refresh(InventoryGui gui) { //IL_0062: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)button == (Object)null) && ((Component)button).gameObject.activeInHierarchy && KeyRing.Active) { ((Behaviour)button.m_icon).enabled = !InventorySettings.SlotLabels.Value; button.m_icon.sprite = SlotIcons.For(SlotKind.Key); ((Graphic)button.m_icon).color = SlotIcons.Hint; int[] array = KeyRing.Counts(((Humanoid)InventoryState.Player).GetInventory()); int num = 0; for (int i = 1; i < array.Length; i++) { num += ((array[i] > 0) ? 1 : 0); } ((Behaviour)button.m_quality).enabled = num > 0; button.m_quality.text = num.ToString(); ShowList(gui, array); button.m_selected.SetActive(KeyRingGamepad.OnButton(gui)); KeyRingNotice.Show(button); } } private static void ShowList(InventoryGui gui, int[] counts) { //IL_00b7: 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) StringBuilder stringBuilder = new StringBuilder(); for (int i = 1; i < counts.Length; i++) { ItemData val = ((counts[i] > 0) ? KeyRing.Key(i) : null); if (val != null) { stringBuilder.Append((stringBuilder.Length > 0) ? "\n" : "").Append(val.m_shared.m_name).Append(": <color=orange>") .Append(counts[i]) .Append("</color>"); } } string text = ((stringBuilder.Length > 0) ? stringBuilder.ToString() : Words.NoKeysHeld); if (!(text == shownList)) { shownList = text; button.m_tooltip.Set(Words.KeyRing, text, gui.m_playerGrid.m_tooltipAnchor, default(Vector2)); } } private static InventoryElement Make(InventoryGui gui, RectTransform panel) { GameObject obj = Object.Instantiate<GameObject>(gui.m_playerGrid.m_elementPrefab, (Transform)(object)panel); ((Object)obj).name = "PackPanel_keyring_button"; InventoryElement component = obj.GetComponent<InventoryElement>(); component.Initialize(-1, -1); Blank(component); UIInputHandler componentInChildren = obj.GetComponentInChildren<UIInputHandler>(); componentInChildren.m_onLeftDown = (Action<UIInputHandler>)Delegate.Combine(componentInChildren.m_onLeftDown, (Action<UIInputHandler>)delegate { KeyRingClicks.OnButton(InventoryGui.instance); }); return component; } private static void Blank(InventoryElement element) { ((Behaviour)element.m_amount).enabled = false; ((Behaviour)element.m_quality).enabled = false; ((Behaviour)element.m_equiped).enabled = false; ((Behaviour)element.m_queued).enabled = false; ((Behaviour)element.m_noteleport).enabled = false; ((Behaviour)element.m_food).enabled = false; ((Component)element.m_durability).gameObject.SetActive(false); element.m_selected.SetActive(false); Transform val = ((Component)element).transform.Find("binding"); TMP_Text val2 = (((Object)(object)val != (Object)null) ? ((Component)val).GetComponent<TMP_Text>() : null); if ((Object)(object)val2 != (Object)null) { ((Behaviour)val2).enabled = false; } } } public static class KeyRingCells { private static readonly List<InventoryElement> elements = new List<InventoryElement>(); public static int Count => elements.Count; public static InventoryElement At(int number) { if (number < 1 || number > elements.Count) { return null; } return elements[number - 1]; } public static void Clear() { elements.Clear(); } public static bool Adopt(InventoryGui gui, InventoryElement element, Slot slot) { //IL_0051: 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_005e: Unknown result type (might be due to invalid IL or missing references) //IL_005f: Unknown result type (might be due to invalid IL or missing references) //IL_0060: 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_0078: Unknown result type (might be due to invalid IL or missing references) //IL_0079: 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_0080: 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_0090: 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) RectTransform val = KeyRingPopup.Find(gui); if ((Object)(object)val == (Object)null || slot.Number < 1) { return false; } while (elements.Count < slot.Number) { elements.Add(null); } elements[slot.Number - 1] = element; RectTransform val2 = (RectTransform)((Component)element).transform; ((Transform)val2).SetParent((Transform)(object)val, false); Vector2 val3 = default(Vector2); ((Vector2)(ref val3))..ctor(0.5f, 0.5f); val2.pivot = val3; Vector2 anchorMin = (val2.anchorMax = val3); val2.anchorMin = anchorMin; ((Transform)val2).localScale = Vector3.one * 0.65f; Image component = ((Component)element).GetComponent<Image>(); if ((Object)(object)component != (Object)null) { ((Graphic)component).color = Color.white; } return true; } public static void Found(List<int> found) { found.Clear(); for (int i = 1; i <= elements.Count; i++) { if ((Object)(object)elements[i - 1] != (Object)null && elements[i - 1].m_used) { found.Add(i); } } } public static bool Shows(int number) { InventoryElement val = At(number); if ((Object)(object)val != (Object)null) { return ((Component)val).gameObject.activeInHierarchy; } return false; } public static void Refresh(Inventory inventory) { //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_0043: Unknown result type (might be due to invalid IL or missing references) foreach (InventoryElement element in elements) { if (!((Object)(object)element == (Object)null) && element.m_used && ((Component)element).gameObject.activeSelf) { ItemData itemAt = inventory.GetItemAt(element.Position.x, element.Position.y); ((Behaviour)element.m_amount).enabled = itemAt != null && itemAt.m_stack > 1; if (((Behaviour)element.m_amount).enabled) { element.m_amount.text = itemAt.m_stack.ToString(); } } } } } public static class KeyRingCircle { public const float CellScale = 0.65f; private const float Spread = 1.12f; private const float MinRadius = 0.95f; private const float Frame = 10f; public const float WireScale = 2.077f; public static float Radius(int count, float step) { float num = 0.95f * step; if (count >= 2) { return Mathf.Max(num, 1.12f * step / (2f * Mathf.Sin((float)Math.PI / (float)count))); } return num; } public static Vector2 Position(int index, int count, float radius) { //IL_0024: 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) float num = (float)Math.PI / 2f - (float)Math.PI * 2f * (float)index / (float)Mathf.Max(1, count); return new Vector2(Mathf.Cos(num), Mathf.Sin(num)) * radius; } public static float Diameter(float radius, float cell) { return 2f * (radius + cell * 0.7072f + 10f); } } public static class KeyRingClicks { [HarmonyPatch(typeof(InventoryGui), "OnSelectedItem")] public static class Selected { [HarmonyPrefix] [HarmonyPriority(800)] public static bool Prefix(InventoryGui __instance, InventoryGrid grid, ref ItemData item, ref Vector2i pos) { //IL_0003: Unknown result type (might be due to invalid IL or missing references) if (RingSlot(__instance, grid, pos) == null) { return true; } if ((Object)(object)__instance.m_dragGo != (Object)null) { ToOwnCell(__instance, grid, ref item, ref pos); return true; } if (KeyRingState.Open) { return true; } KeyRingState.Toggle(); return false; } private static void ToOwnCell(InventoryGui gui, InventoryGrid grid, ref ItemData item, ref Vector2i pos) { //IL_0006: 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_0015: 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_0025: 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_0032: 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) Vector2i val = KeyRing.CellOf(gui.m_dragItem); if (val.x >= 0 && !(val == pos)) { pos = val; item = grid.GetInventory().GetItemAt(val.x, val.y); } } } [HarmonyPatch(typeof(InventoryGui), "OnRightClickItem")] public static class RightClick { [HarmonyPrefix] public static bool Prefix(InventoryGui __instance, InventoryGrid grid, Vector2i pos) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) if (RingSlot(__instance, grid, pos) == null || KeyRingState.Open) { return true; } KeyRingState.Toggle(); return false; } } public static void OnButton(InventoryGui gui) { //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) //IL_0031: 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_0055: Unknown result type (might be due to invalid IL or missing references) //IL_0069: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)gui == (Object)null || !KeyRing.Active) { return; } if ((Object)(object)gui.m_dragGo == (Object)null) { KeyRingState.Toggle(); return; } Vector2i val = KeyRing.CellOf(gui.m_dragItem); if (val.x < 0) { Messages.Center(Words.NotAKey); return; } ItemData itemAt = ((Humanoid)InventoryState.Player).GetInventory().GetItemAt(val.x, val.y); gui.OnSelectedItem(gui.m_playerGrid, itemAt, val, (Modifier)0); } private static Slot RingSlot(InventoryGui gui, InventoryGrid grid, Vector2i pos) { //IL_0017: Unknown result type (might be due to invalid IL or missing references) Slot slot = (((Object)(object)grid == (Object)(object)gui.m_playerGrid) ? InventoryState.SlotAt(grid.GetInventory(), pos) : null); if (slot == null || slot.Kind != SlotKind.Key) { return null; } return slot; } } public static class KeyRingGamepad { [HarmonyPatch(typeof(InventoryGrid), "UpdateGamepad")] public static class Move { [HarmonyPrefix] public static void Prefix(InventoryGrid __instance, out Vector2i __state) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Unknown result type (might be due to invalid IL or missing references) __state = __instance.m_selected; } [HarmonyPostfix] public static void Postfix(InventoryGrid __instance, Vector2i __state) { //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_0018: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_0025: 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_0034: Unknown result type (might be due to invalid IL or missing references) if (!(__instance.m_selected == __state) && IsPlayerGrid(__instance)) { Vector2i val = Settle(__instance, __state, __instance.m_selected); if (val != __instance.m_selected) { Select(__instance, val); } } } } [HarmonyPatch(typeof(InventoryGui), "Update")] public static class Back { [HarmonyPrefix] public static void Prefix(InventoryGui __instance) { if ((KeyRingState.Open || TackleState.Open) && ZInput.IsExclusiveGamepadActive() && InventoryGui.IsVisible() && NoDialog(__instance) && ZInput.GetButtonDown("JoyButtonB")) { ZInput.ResetButtonStatus("JoyButtonB"); KeyRingState.Close(); TackleState.Close(); } } } private static readonly List<int> found = new List<int>(); public static bool OnButton(InventoryGui gui) { //IL_0023: Unknown result type (might be due to invalid IL or missing references) InventoryGrid playerGrid = gui.m_playerGrid; if (!playerGrid.m_uiGroup.IsActive || !ZInput.IsExclusiveGamepadActive()) { return false; } Slot slot = InventoryState.Layout.SlotAt(playerGrid.m_selected); if (slot != null && slot.Kind == SlotKind.Key) { if (KeyRingState.Open) { return !KeyRingCells.Shows(slot.Number); } return true; } return false; } public static void Follow(bool open) { //IL_0049: Unknown result type (might be due to invalid IL or missing references) //IL_009b: Unknown result type (might be due to invalid IL or missing references) //IL_0067: Unknown result type (might be due to invalid IL or missing references) InventoryGrid val = (((Object)(object)InventoryGui.instance != (Object)null) ? InventoryGui.instance.m_playerGrid : null); IReadOnlyList<Vector2i> readOnlyList = InventoryState.CellsOf(SlotKind.Key); if ((Object)(object)val == (Object)null || readOnlyList.Count == 0 || !KeyRing.Active || !ZInput.IsExclusiveGamepadActive()) { return; } Slot slot = InventoryState.Layout.SlotAt(val.m_selected); if (!open && slot != null && slot.Kind == SlotKind.Key) { Select(val, readOnlyList[0]); } if (open) { KeyRingCells.Found(found); if (found.Count > 0) { Select(val, readOnlyList[found[0] - 1]); } } } private static bool IsPlayerGrid(InventoryGrid grid) { if ((Object)(object)InventoryGui.instance != (Object)null && (Object)(object)grid == (Object)(object)InventoryGui.instance.m_playerGrid) { return InventoryState.Manages(grid.GetInventory()); } return false; } private static Vector2i Settle(InventoryGrid grid, Vector2i before, Vector2i landed) { //IL_0000: 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_0013: 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_002d: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_005c: Unknown result type (might be due to invalid IL or missing references) //IL_008a: 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_006e: Unknown result type (might be due to invalid IL or missing references) //IL_007c: 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_0032: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_0047: 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_0042: Unknown result type (might be due to invalid IL or missing references) int num = Math.Sign(landed.x - before.x); int num2 = Math.Sign(landed.y - before.y); Inventory inventory = grid.GetInventory(); Vector2i val = landed; while (val.x >= 0 && val.y >= 0 && val.x < inventory.GetWidth() && val.y < inventory.GetHeight()) { Vector2i val2 = StandIn(val); if (Shows(val2)) { return val2; } ((Vector2i)(ref val))..ctor(val.x + num, val.y + num2); } return before; } private static Vect