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.17.2
plugins\PackPanel.dll
Decompiled a week 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 EliteCraftingLink; using HarmonyLib; using Hotkeys; using ItemCopies; using MagicaCloth2; using Microsoft.CodeAnalysis; using PackPanel.Backpacks; using PackPanel.Consume; using PackPanel.Core; using PackPanel.Crafting; using PackPanel.Elite; 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 Translations; 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.RepresentationModel; 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.17.2.0")] [assembly: AssemblyInformationalVersion("0.17.2+729815001313894f23d648ee59b26618052e26dd")] [assembly: AssemblyProduct("PackPanel")] [assembly: AssemblyTitle("PackPanel")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("0.17.2.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.17.2")] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] public class Plugin : BaseUnityPlugin { public const string PluginGuid = "milkyteam.packpanel"; public const string PluginName = "PackPanel"; public const string PluginVersion = "0.17.2"; 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_0016: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Expected O, but got Unknown Instance = this; Log = ((BaseUnityPlugin)this).Logger; Harmony harmony = new Harmony("milkyteam.packpanel"); Lang.Install(harmony, Assembly.GetExecutingAssembly(), "PackPanel", ((BaseUnityPlugin)this).Logger); Synced = new SyncedConfiguration((BaseUnityPlugin)(object)this, ((BaseUnityPlugin)this).Logger, "PackPanel", "0.17.2"); 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); EliteSetup.Register(); int num = PatchEverything(harmony); BackpackPrefab.Install(harmony); TackleboxPrefab.Install(harmony); Synced.Finish(harmony); Log.LogInfo((object)("Loading [PackPanel 0.17.2]" + ((num > 0) ? $" with {num} failed patches, see above" : ""))); Guard.Install(harmony, ((BaseUnityPlugin)this).Logger, Assembly.GetExecutingAssembly()); } private void Update() { GamePanelTheme.Update(); NightShade.Update(); } 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 { [HarmonyPatch(typeof(Humanoid), "UseItem")] public static class ChestWear { [HarmonyPrefix] public static bool Prefix(Humanoid __instance, Inventory inventory, ItemData item, bool fromInventoryGui) { if (!fromInventoryGui || inventory == null || item == null || !GearKeep.On || !InventoryState.IsLocal(__instance)) { return true; } if (InventoryState.Manages(inventory) || !inventory.ContainsItem(item)) { return true; } SlotKind? slotKind = SlotRules.WornKindOf(item); if (!slotKind.HasValue || InventoryState.CellsOf(slotKind.Value).Count == 0 || !Wearable(__instance, item, slotKind.Value)) { return true; } Wear(__instance, inventory, item, slotKind.Value); return false; } private static bool Wearable(Humanoid humanoid, ItemData item, SlotKind kind) { if (kind != SlotKind.Backpack) { return WearCheck.Guards(humanoid, item, tell: true); } if (BackpackCatalog.Of(item) != null) { return BackpackSettings.Active; } return false; } private static void Wear(Humanoid humanoid, Inventory chest, ItemData item, SlotKind kind) { //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) //IL_004b: Unknown result type (might be due to invalid IL or missing references) //IL_0051: Unknown result type (might be due to invalid IL or missing references) //IL_0068: 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_007b: Unknown result type (might be due to invalid IL or missing references) //IL_0081: Unknown result type (might be due to invalid IL or missing references) Inventory inventory = humanoid.GetInventory(); Vector2i val = Target(humanoid, item, kind); ItemData itemAt = inventory.GetItemAt(val.x, val.y); if (itemAt != null && !GearOut.HasRoom(inventory, kind)) { Messages.Center(Lang.Get("packpanel_noroomoff")); return; } if (itemAt != null) { TakeOut(humanoid, itemAt, kind); } if (inventory.GetItemAt(val.x, val.y) == null) { inventory.MoveItemToThis(chest, item, item.m_stack, val.x, val.y); ItemData itemAt2 = inventory.GetItemAt(val.x, val.y); if (itemAt2 != null) { humanoid.EquipItem(itemAt2, true); } } } private static Vector2i Target(Humanoid humanoid, ItemData item, SlotKind kind) { //IL_000d: 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_002c: 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_001e: 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_0038: Unknown result type (might be due to invalid IL or missing references) IReadOnlyList<Vector2i> readOnlyList = InventoryState.CellsOf(kind); if (kind != SlotKind.Utility) { return readOnlyList[0]; } if (WearCheck.Beside(humanoid, item)) { return BesideCell(humanoid, readOnlyList); } Vector2i val = WearCheck.Replaced(humanoid, item, readOnlyList); if (val.x < 0) { return readOnlyList[0]; } return val; } private static Vector2i BesideCell(Humanoid humanoid, IReadOnlyList<Vector2i> cells) { //IL_0009: Unknown result type (might be due to invalid IL or missing references) //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_0018: 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_0065: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_0050: Unknown result type (might be due to invalid IL or missing references) //IL_0055: Unknown result type (might be due to invalid IL or missing references) Inventory inventory = humanoid.GetInventory(); Vector2i result = cells[0]; bool flag = false; for (int i = 0; i < cells.Count; i++) { ItemData itemAt = inventory.GetItemAt(cells[i].x, cells[i].y); if (itemAt == null) { return cells[i]; } if (!flag && !humanoid.IsItemEquiped(itemAt)) { result = cells[i]; flag = true; } } return result; } private static void TakeOut(Humanoid humanoid, ItemData there, SlotKind kind) { if (humanoid.IsItemEquiped(there)) { WornPlacement.Suspend(); try { humanoid.UnequipItem(there, true); } finally { WornPlacement.Resume(); } } GearOut.Away(humanoid, there, kind); } } 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 (BackpackEquip.Takes(item)) { __result = BackpackEquip.Wear(__instance, item, triggerEquipEffects); } else { 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), "EquipItem")] public static class EquipBoots { [HarmonyPrefix] [HarmonyPriority(800)] public static void Prefix(ItemData item) { if (EliteEquipmentLink.IsBoots(item)) { WornPlacement.BeginEquip(); } } [HarmonyFinalizer] public static void Finalizer(ItemData item) { if (EliteEquipmentLink.IsBoots(item)) { 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), "DrainEquipedItemDurability")] public static class Break { [HarmonyPrefix] public static void Prefix() { WornPlacement.BeginBreak(); } [HarmonyFinalizer] public static void Finalizer() { WornPlacement.EndBreak(); } } [HarmonyPatch(typeof(Humanoid), "IsItemEquiped")] public static class IsEquipped { [HarmonyPostfix] public static void Postfix(Humanoid __instance, ItemData item, ref bool __result) { if (!__result && InventoryState.IsLocal(__instance)) { __result = ExtraUtilities.IsWorn(item) || BackpackEquip.IsWorn(__instance, item); } } } [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); BackpackEquip.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); BackpackEquip.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) { if (worn.Count == 0) { return; } Inventory inventory = humanoid.GetInventory(); bool flag = false; for (int num = worn.Count - 1; num >= 0; num--) { if (!worn[num].m_equipped || !inventory.ContainsItem(worn[num])) { worn.RemoveAt(num); flag = true; } } if (flag) { 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 GearKeep { private static readonly SlotKind[] Kinds = new SlotKind[7] { SlotKind.Head, SlotKind.Chest, SlotKind.Legs, SlotKind.Feet, SlotKind.Back, SlotKind.Utility, SlotKind.Trinket }; private static readonly List<ItemData> leftOff = new List<ItemData>(); public static bool On { get { if (InventoryState.Active) { return InventorySettings.AutoEquip.Value; } return false; } } public static void LeaveOff(ItemData item) { if (!leftOff.Contains(item)) { leftOff.Add(item); } } public static void Tick(Player player) { if (!On || ((Character)player).IsDead()) { leftOff.Clear(); } else if (!WornPlacement.Suspended && !Dragging()) { Forget(player); WearAll(player); } } private static void Forget(Player player) { for (int num = leftOff.Count - 1; num >= 0; num--) { if (!GearOut.LiesUnworn((Humanoid)(object)player, leftOff[num], out var _)) { leftOff.RemoveAt(num); } } } private static void WearAll(Player player) { //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Unknown result type (might be due to invalid IL or missing references) Inventory inventory = ((Humanoid)player).GetInventory(); SlotKind[] kinds = Kinds; foreach (SlotKind kind in kinds) { IReadOnlyList<Vector2i> readOnlyList = InventoryState.CellsOf(kind); for (int j = 0; j < readOnlyList.Count; j++) { Wear(player, inventory.GetItemAt(readOnlyList[j].x, readOnlyList[j].y), kind); } } } private static void Wear(Player player, ItemData item, SlotKind kind) { if (item != null && SlotRules.WornKindOf(item) == kind && !((Humanoid)player).IsItemEquiped(item) && !leftOff.Contains(item) && WearCheck.Guards((Humanoid)(object)player, item, tell: false) && WearCheck.Beside((Humanoid)(object)player, item) && !((Humanoid)player).EquipItem(item, true)) { leftOff.Add(item); } } private static bool Dragging() { if ((Object)(object)InventoryGui.instance != (Object)null) { return (Object)(object)InventoryGui.instance.m_dragGo != (Object)null; } return false; } } public static class GearOut { public static Vector2i FreeCell(Inventory inventory, SlotKind kind) { //IL_0017: 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) if (kind != SlotKind.Backpack) { return MainCells.FindEmpty(inventory, InventoryState.Layout, topFirst: false); } return MainCells.FindEmptyOffPack(inventory, InventoryState.Layout); } public static bool HasRoom(Inventory inventory, SlotKind kind) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) return FreeCell(inventory, kind).x >= 0; } public static bool Away(Humanoid humanoid, ItemData item, SlotKind kind) { //IL_0009: Unknown result type (might be due to invalid IL or missing references) //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_001b: 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) Inventory inventory = humanoid.GetInventory(); Vector2i val = FreeCell(inventory, kind); if (val.x < 0) { return false; } item.m_gridPos = val; inventory.Changed(false, false); return true; } public static bool LiesUnworn(Humanoid humanoid, ItemData item, out SlotKind kind) { //IL_0023: Unknown result type (might be due to invalid IL or missing references) kind = SlotKind.Retired; if (!humanoid.GetInventory().ContainsItem(item) || humanoid.IsItemEquiped(item)) { return false; } Slot slot = InventoryState.Layout.SlotAt(item.m_gridPos); if (slot == null || !SlotRules.IsWorn(slot.Kind) || SlotRules.WornKindOf(item) != slot.Kind) { return false; } kind = slot.Kind; return true; } } [HarmonyPatch(typeof(Player), "ToggleEquipped")] public static class InstantEquip { [HarmonyPrefix] public static bool Prefix(Player __instance, ItemData item, ref bool __result) { if (!InventorySettings.Enabled.Value || !InventorySettings.InstantEquip.Value || item == null || !item.IsEquipable() || ((Character)__instance).InAttack() || item.m_shared.m_equipDuration <= 0f) { return true; } if (((Humanoid)__instance).IsItemEquiped(item)) { ((Humanoid)__instance).UnequipItem(item, true); } else { ((Humanoid)__instance).EquipItem(item, true); } __result = true; return false; } } public static class ModifierFields { private static FieldInfo[] madeFrom; private static FieldRef<SharedData, float>[] getters = new FieldRef<SharedData, float>[0]; public static FieldRef<SharedData, float>[] Get() { FieldInfo[] s_equipmentModifierSourceFields = Player.s_equipmentModifierSourceFields; if (s_equipmentModifierSourceFields == null || s_equipmentModifierSourceFields == madeFrom) { return getters; } FieldRef<SharedData, float>[] array = new FieldRef<SharedData, float>[s_equipmentModifierSourceFields.Length]; for (int i = 0; i < s_equipmentModifierSourceFields.Length; i++) { array[i] = AccessTools.FieldRefAccess<SharedData, float>(s_equipmentModifierSourceFields[i]); } getters = array; madeFrom = s_equipmentModifierSourceFields; return getters; } } 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) { IReadOnlyList<ItemData> worn = ExtraUtilities.Worn; if (worn.Count == 0 || !InventoryState.IsLocal(__instance)) { return; } for (int i = 0; i < worn.Count; i++) { if (worn[i].m_shared.m_setName == setName) { __result++; } } } } [HarmonyPatch(typeof(Player), "GetEquipmentEitrRegenModifier")] public static class EitrRegen { [HarmonyPostfix] public static void Postfix(Player __instance, ref float __result) { IReadOnlyList<ItemData> worn = ExtraUtilities.Worn; if (worn.Count != 0 && InventoryState.IsLocal((Humanoid)(object)__instance)) { for (int i = 0; i < worn.Count; i++) { __result += worn[i].m_shared.m_eitrRegenModifier; } } } } [HarmonyPatch(typeof(Player), "UpdateModifiers")] public static class Modifiers { [HarmonyPostfix] public static void Postfix(Player __instance) { if (Player.s_equipmentModifierSourceFields != null && InventoryState.IsLocal((Humanoid)(object)__instance)) { float[] equipmentModifierValues = __instance.m_equipmentModifierValues; AddUtilities(equipmentModifierValues); if (equipmentModifierValues.Length != 0) { equipmentModifierValues[0] += BackpackLevels.WornSpeed(__instance); } } } private static void AddUtilities(float[] values) { IReadOnlyList<ItemData> worn = ExtraUtilities.Worn; if (worn.Count == 0) { return; } FieldRef<SharedData, float>[] array = ModifierFields.Get(); int num = Math.Min(values.Length, array.Length); for (int i = 0; i < worn.Count; i++) { SharedData shared = worn[i].m_shared; for (int j = 0; j < num; j++) { values[j] += array[j].Invoke(shared); } } } } [HarmonyPatch(typeof(Humanoid), "GetEquipmentWeight")] public static class Weight { [HarmonyPostfix] public static void Postfix(Humanoid __instance, ref float __result) { IReadOnlyList<ItemData> worn = ExtraUtilities.Worn; if (worn.Count != 0 && InventoryState.IsLocal(__instance)) { for (int i = 0; i < worn.Count; i++) { __result += worn[i].m_shared.m_weight; } } } } [HarmonyPatch(typeof(Humanoid), "UpdateEquipment")] public static class Durability { [HarmonyPostfix] public static void Postfix(Humanoid __instance, float dt) { if (ExtraUtilities.Worn.Count == 0 || !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 WearCheck { public static bool Guards(Humanoid humanoid, ItemData item, bool tell) { //IL_007b: Unknown result type (might be due to invalid IL or missing references) //IL_0082: Invalid comparison between Unknown and I4 //IL_008a: Unknown result type (might be due to invalid IL or missing references) //IL_0091: Invalid comparison between Unknown and I4 if (((Character)humanoid).InAttack() || ((Character)humanoid).InDodge() || (((Character)humanoid).IsSwimming() && !((Character)humanoid).IsOnGround())) { return false; } if (item.m_shared.m_useDurability && item.m_durability <= 0f) { return false; } if (item.m_shared.m_dlc.Length > 0 && !DLCMan.instance.IsDLCInstalled(item.m_shared.m_dlc)) { return Refuse(humanoid, tell, "$msg_dlcrequired"); } if (((int)item.m_shared.m_itemType == 18 || (int)item.m_shared.m_itemType == 24) && Game.m_worldLevel > 0 && item.m_worldLevel < Game.m_worldLevel) { return Refuse(humanoid, tell, "$msg_ng_item_too_low"); } return true; } public static bool Beside(Humanoid humanoid, ItemData item) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Invalid comparison between Unknown and I4 if ((int)item.m_shared.m_itemType == 18 && humanoid.m_utilityItem != null) { return ExtraUtilities.Takes(humanoid, item); } return true; } public static Vector2i Replaced(Humanoid humanoid, ItemData item, IReadOnlyList<Vector2i> cells) { //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) //IL_0082: 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_006f: Unknown result type (might be due to invalid IL or missing references) //IL_0074: Unknown result type (might be due to invalid IL or missing references) Inventory inventory = humanoid.GetInventory(); Vector2i result = default(Vector2i); ((Vector2i)(ref result))..ctor(-1, -1); for (int i = 0; i < cells.Count; i++) { ItemData itemAt = inventory.GetItemAt(cells[i].x, cells[i].y); if (itemAt != null && humanoid.IsItemEquiped(itemAt)) { if (itemAt.m_shared.m_name == item.m_shared.m_name) { return cells[i]; } if (itemAt == humanoid.m_utilityItem) { result = cells[i]; } } } return result; } private static bool Refuse(Humanoid humanoid, bool tell, string message) { if (tell) { ((Character)humanoid).Message((MessageType)2, message, 0, (Sprite)null, false); } return false; } } public static class WornPlacement { private static int suspended; private static int equipping; private static int breaking; public static bool Suspended => suspended > 0; public static void BeginEquip() { equipping++; } public static void EndEquip() { equipping = ((equipping > 0) ? (equipping - 1) : 0); } public static void BeginBreak() { breaking++; } public static void EndBreak() { breaking = ((breaking > 0) ? (breaking - 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_0034: Unknown result type (might be due to invalid IL or missing references) Inventory inventory = humanoid.GetInventory(); if (!Suspended && equipping <= 0 && breaking <= 0 && item != null && !item.m_equipped && InventoryState.IsLocal(humanoid)) { Slot slot = InventoryState.SlotAt(inventory, item.m_gridPos); if (slot != null && SlotRules.IsWorn(slot.Kind) && SlotRules.WornKindOf(item) == slot.Kind && inventory.ContainsItem(item) && !GearOut.Away(humanoid, item, slot.Kind)) { GearKeep.LeaveOff(item); } } } 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", 2f, new TackleboxStats("piece_workbench", 2, "Wood:10, LeatherScraps:10, DeerHide:5", 1)), new TackleboxKind("PackPanel_FinewoodTacklebox", "finewood", 3f, new TackleboxStats("piece_workbench", 3, "PackPanel_DriftwoodTacklebox:1, FineWood:10, TrollHide:10, Bronze:2", 2)), new TackleboxKind("PackPanel_CarapaceTacklebox", "carapace", 3f, new TackleboxStats("blackforge", 1, "PackPanel_FinewoodTacklebox:1, Carapace:10, YggdrasilWood:10", 6)), new TackleboxKind("PackPanel_FlametalTacklebox", "flametal", 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(); CraftedWords.WriteAll(); 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(YamlConfig.YamlNode root) { YamlConfig.YamlNode yamlNode = root.Get("tackleboxes"); if (yamlNode.Kind == YamlNodeKind.Map) { foreach (KeyValuePair<string, YamlConfig.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, YamlConfig.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 { 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, float weight, TackleboxStats defaults) : base(id, "tacklebox", word, 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.Id + " 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.Id + " ready")); } } 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; private static string shownText; public static void Refresh(InventoryElement element) { //IL_005a: 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) if ((Object)(object)element == (Object)null || !Tacklebox.Active) { return; } TMP_Text amount = element.m_amount; if (((Behaviour)amount).enabled != element.m_used) { ((Behaviour)amount).enabled = element.m_used; } if (element.m_used) { IReadOnlyList<Vector2i> readOnlyList = InventoryState.CellsOf(SlotKind.Tackle); Inventory inventory = ((Humanoid)InventoryState.Player).GetInventory(); int num = 0; for (int i = 0; i < readOnlyList.Count; i++) { num += ((inventory.GetItemAt(readOnlyList[i].x, readOnlyList[i].y) != null) ? 1 : 0); } if (!((Object)(object)element == (Object)(object)shownOn) || num != shownUsed || readOnlyList.Count != shownCells || !(amount.text == shownText)) { shownText = num + "/" + readOnlyList.Count; amount.text = shownText; 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 void DescribeAll() { foreach (TackleboxKind item in TackleboxCatalog.All) { Lang.Add(item.DescriptionToken, Describe(item)); } } private static string Describe(TackleboxKind kind) { int cells = kind.Stats.Cells; string text = ((cells == 1) ? Lang.Get("packpanel_tacklebox_one_cell") : Lang.Format("packpanel_tacklebox_cells", cells)); return Lang.Format("packpanel_tacklebox_describe", Lang.Get(kind.LookKey), text); } } 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_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Unknown result type (might be due to invalid IL or missing references) foreach (InventoryElement element in elements) { if (!((Object)(object)element == (Object)null)) { ItemData item = (element.m_used ? inventory.GetItemAt(element.Position.x, element.Position.y) : null); NumberText.ShowCount(element.m_amount, item); } } } } [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_0080: Unknown result type (might be due to invalid IL or missing references) //IL_0081: Unknown result type (might be due to invalid IL or missing references) //IL_008d: Unknown result type (might be due to invalid IL or missing references) //IL_0093: Unknown result type (might be due to invalid IL or missing references) 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(Lang.Get("packpanel_tacklebox_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; private static readonly PanelFind popupFind = new PanelFind("PackPanel_tacklebox"); public static RectTransform Find(InventoryGui gui) { return popupFind.In(gui); } 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_0023: Unknown result type (might be due to invalid IL or missing references) RectTransform val = SlotPanel.MakePanel(gui, "PackPanel_tacklebox"); popupFind.Made(gui, val); val.pivot = new Vector2(0f, 1f); GridSkin.Panel(((Component)val).GetComponent<Image>()); } } public static class TackleRouting { public static bool TakeIn(Inventory inventory, ItemData item) { return SlotFill.TakeIn(inventory, item, InventoryState.CellsOf(SlotKind.Tackle)); } } public static class TackleRules { private const string Rod = "FishingRod"; private const string GameBait = "$item_fishingbait"; 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_000b: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_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_0019: Invalid comparison between Unknown and I4 if (item == null) { return false; } ItemType itemType = item.m_shared.m_itemType; if ((int)itemType == 9 || (int)itemType == 23) { return item.m_shared.m_ammoType == (BaitType() ?? "$item_fishingbait"); } return false; } 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), "AddItem", new Type[] { typeof(ItemData) })] public static class AddRouting { [HarmonyPrefix] public static bool Prefix(Inventory __instance, ItemData item, ref bool __result, bool __runOriginal) { if (!__runOriginal) { return false; } if (item == null || !InventoryState.Manages(__instance) || !Routed(__instance, item)) { return true; } __result = true; return false; } private static bool Routed(Inventory inventory, ItemData item) { if (SlotRules.IsCoins(item) && CoinPurse.TakeIn(inventory, item)) { return true; } if (KeyRouting.TakeIn(inventory, item)) { return true; } if (Tacklebox.Active && TackleRules.IsTackle(item) && TackleRouting.TakeIn(inventory, item)) { return true; } if (AmmoRouting.IsAmmo(item)) { return AmmoRouting.TakeIn(inventory, item); } return false; } } public static class AmmoRouting { public static bool IsAmmo(ItemData item) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Invalid comparison between Unknown and I4 if ((int)item.m_shared.m_itemType == 9) { return !TackleRules.IsBait(item); } return false; } public static bool TakeIn(Inventory inventory, ItemData item) { return SlotFill.TakeIn(inventory, item, InventoryState.CellsOf(SlotKind.Ammo)); } } [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; } } public static class CoinPurse { public 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(Lang.Get("packpanel_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) && slotKind == slot.Kind) { if (!item.m_equipped) { ((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; } } [HarmonyPatch(typeof(TombStone), "EasyFitInInventory")] public static class GraveFit { [HarmonyPrefix] public static bool Prefix(TombStone __instance, Player player, ref bool __result) { Container component = ((Component)__instance).GetComponent<Container>(); if (!InventoryState.IsLocal((Humanoid)(object)player) || !InventoryState.Manages(((Humanoid)player).GetInventory()) || (Object)(object)component == (Object)null) { return true; } __result = Fits(player, component.GetInventory()); return false; } private static bool Fits(Player player, Inventory grave) { Inventory inventory = ((Humanoid)player).GetInventory(); InventoryLayout layout = InventoryState.Layout; ItemData val = BackpackGrave.WaitingPack(grave); BackpackKind kind = BackpackCatalog.Of(val); int num = BackpackSettings.SlotsOf(val); int num2 = BackpackGrave.RowsAdded(layout, num); int num3 = MainCells.CountEmpty(inventory, layout) + num; if (GridItems(inventory, grave, val, layout.MainRows + num2, num2) > num3) { return false; } float num4 = player.GetMaxCarryWeight() + BackpackSettings.Carry(kind) * Game.m_carryWeightRate; return inventory.GetTotalWeight() + grave.GetTotalWeight() <= num4; } private static int GridItems(Inventory inventory, Inventory grave, ItemData pack, int mainRows, int shift) { //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_0023: 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_0033: Unknown result type (might be due to invalid IL or missing references) int num = 0; foreach (ItemData allItem in grave.GetAllItems()) { if (allItem != pack) { Vector2i gridPos = allItem.m_gridPos; if ((gridPos.y < mainRows || inventory.GetItemAt(gridPos.x, gridPos.y - shift) != null) && inventory.FindFreeStackSpace(allItem.m_shared.m_name, (float)allItem.m_worldLevel) < allItem.m_stack) { num++; } } } return num; } } public static class GravePatches { [HarmonyPatch(typeof(Container), "RPC_TakeAllResponse")] public static class Granted { [HarmonyPrefix] public static void Prefix(Container __instance) { grantedFrom = __instance; } [HarmonyFinalizer] public static void Finalizer() { grantedFrom = null; } } [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; } } private static Container grantedFrom; public static bool ForeignTakeAll { get; private set; } private static bool IsGrave(Inventory inventory) { if (From(((Object)(object)InventoryGui.instance != (Object)null) ? InventoryGui.instance.m_currentContainer : null, inventory, out var grave) || From(grantedFrom, inventory, out grave)) { return grave; } 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 bool From(Container container, Inventory inventory, out bool grave) { grave = false; if ((Object)(object)container == (Object)null || container.GetInventory() != inventory) { return false; } grave = (Object)(object)((Component)container).GetComponent<TombStone>() != (Object)null; return true; } 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; } } [Flags] public enum KeptGroups { None = 0, Gear = 1, Backpack = 2, Utility = 4, Trinket = 8, Food = 0x10, Mead = 0x20, Ammo = 0x40, Tacklebox = 0x80 } 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_0047: Unknown result type (might be due to invalid IL or missing references) KeptGroups value = InventorySettings.KeepOnDeath.Value; if (value == KeptGroups.None || !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 && (value & GroupOf(slot.Kind)) != KeptGroups.None) { 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 KeptGroups GroupOf(SlotKind kind) { switch (kind) { case SlotKind.Head: case SlotKind.Chest: case SlotKind.Legs: case SlotKind.Back: case SlotKind.Feet: return KeptGroups.Gear; case SlotKind.Backpack: return KeptGroups.Backpack; case SlotKind.Utility: return KeptGroups.Utility; case SlotKind.Trinket: return KeptGroups.Trinket; case SlotKind.Food: return KeptGroups.Food; case SlotKind.Mead: return KeptGroups.Mead; case SlotKind.Ammo: return KeptGroups.Ammo; case SlotKind.Tacklebox: return KeptGroups.Tacklebox; default: return KeptGroups.None; } } 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 { private static readonly SlotKind[] kinds = (SlotKind[])Enum.GetValues(typeof(SlotKind)); private static readonly string[] prefixes = Prefixes(); public SlotKind Kind { get; } public int Number { get; } public string Id { get; } public static IReadOnlyList<SlotKind> Kinds => kinds; public Slot(SlotKind kind, int number) { Kind = kind; Number = number; Id = Prefix(kind) + number; } public Slot(string id) { Kind = SlotKind.Retired; Number = 0; Id = id; } public override string ToString() { return Id; } public static string Prefix(SlotKind kind) { int num = (int)kind; if (num < 0 || num >= prefixes.Length || prefixes[num] == null) { return kind.ToString().ToLowerInvariant(); } return prefixes[num]; } private static string[] Prefixes() { int num = 0; SlotKind[] array = kinds; foreach (SlotKind slotKind in array) { num = Math.Max(num, (int)(slotKind + 1)); } string[] array2 = new string[num]; array = kinds; for (int i = 0; i < array.Length; i++) { SlotKind slotKind2 = array[i]; if (slotKind2 >= SlotKind.Head) { array2[(int)slotKind2] = slotKind2.ToString().ToLowerInvariant(); } } return array2; } } 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(Lang.Get("packpanel_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 static class SlotFill { public static bool TakeIn(Inventory inventory, ItemData item, IReadOnlyList<Vector2i> cells) { //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_0012: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_0041: 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_0049: 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) foreach (Vector2i cell in cells) { if (Stack(inventory, item, cell)) { return true; } } foreach (Vector2i cell2 in cells) { if (inventory.GetItemAt(cell2.x, cell2.y) == null) { Place(inventory, item, cell2); return true; } } return false; } public static int EmptyRoom(Inventory inventory, IReadOnlyList<Vector2i> cells, ItemData item) { //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0014: 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) int num = 0; foreach (Vector2i cell in cells) { num += ((inventory.GetItemAt(cell.x, cell.y) == null) ? 1 : 0); } return num * item.m_shared.m_maxStackSize; } 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 enum SlotKind { Head, Chest, Legs, Back, Backpack, Utility, Food, Mead, Ammo, Purse, Retired, Key, Tacklebox, Tackle, Trinket, Feet } public static class SlotRules { public const string CoinsName = "$item_coins"; private static HashSet<string> listedPacks; private static bool watchingList; public static bool IsWorn(SlotKind kind) { if (kind > SlotKind.Utility && kind != SlotKind.Trinket) { return kind == SlotKind.Feet; } 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_0025: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Invalid comparison between Unknown and I4 //IL_003f: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Invalid comparison between Unknown and I4 //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Invalid comparison between Unknown and I4 //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Invalid comparison between Unknown and I4 //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Invalid comparison between Unknown and I4 //IL_0049: Unknown result type (might be due to invalid IL or missing references) //IL_004c: Invalid comparison between Unknown and I4 //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Invalid comparison between Unknown and I4 if (BackpackCatalog.Of(item) != null) { return SlotKind.Backpack; } if (EliteEquipmentLink.IsBoots(item)) { return SlotKind.Feet; } ItemType itemType = item.m_shared.m_itemType; if ((int)itemType <= 11) { if ((int)itemType == 6) { return SlotKind.Head; } if ((int)itemType == 7) { return SlotKind.Chest; } if ((int)itemType == 11) { return SlotKind.Legs; } } else { if ((int)itemType == 17) { return SlotKind.Back; } if ((int)itemType == 18) { return SlotKind.Utility; } if ((int)itemType == 24) { return SlotKind.Trinket; } } 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) ? ItemNames.PrefabName(item) : ""); if (text.IndexOf("backpack", StringComparison.OrdinalIgnoreCase) >= 0) { return true; } return ListedPacks().Contains(text); } private static HashSet<string> ListedPacks() { if (listedPacks != null) { return listedPacks; } if (!watchingList) { watchingList = true; InventorySettings.BackpackItems.SettingChanged += delegate { listedPacks = null; }; } listedPacks = new HashSet<string>(StringComparer.OrdinalIgnoreCase); string[] array = InventorySettings.BackpackItems.Value.Split(new char[1] { ',' }); foreach (string text in array) { if (text.Trim().Length > 0) { listedPacks.Add(text.Trim()); } } return listedPacks; } 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 { private static readonly HashSet<ItemData> before = new HashSet<ItemData>(); [HarmonyPrefix] public static void Prefix(Inventory __instance, out bool __state) { __state = InventoryState.Manages(__instance) && (KeyRing.Active || Tacklebox.Active || InventoryState.CellsOf(SlotKind.Ammo).Count > 0); if (__state) { before.Clear(); before.UnionWith(__instance.GetAllItems()); } } [HarmonyPostfix] public static void Postfix(Inventory __instance, bool __state) { //IL_0032: Unknown result type (might be due to invalid IL or missing references) if (!__state) { return; } foreach (ItemData item in new List<ItemData>(__instance.GetAllItems())) { if (!before.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 (AmmoRouting.IsAmmo(item)) { return AmmoRouting.TakeIn(inventory, item); } if (Tacklebox.Active && TackleRules.IsTackle(item)) { return TackleRouting.TakeIn(inventory, item); } return false; } } } namespace PackPanel.Ring { public static class KeyNames { private static readonly Dictionary<string, List<int>> numbers = new Dictionary<string, List<int>>(); private static IReadOnlyList<string> madeFor; private static ObjectDB madeFrom; private static int madeItems = -1; public static int Version { get; private set; } public static Dictionary<string, List<int>> Get() { IReadOnlyList<string> prefabs = KeyRing.Prefabs; ObjectDB instance = ObjectDB.instance; int num = (((Object)(object)instance != (Object)null) ? instance.m_items.Count : (-1)); if (prefabs == madeFor && instance == madeFrom && num == madeItems) { return numbers; } Make(prefabs.Count); madeFor = prefabs; madeFrom = instance; madeItems = num; Version++; return numbers; } private static void Make(int keys) { numbers.Clear(); for (int i = 1; i <= keys; i++) { string text = KeyRing.Key(i)?.m_shared.m_name; if (text != null) { if (!numbers.TryGetValue(text, out var value)) { value = (numbers[text] = new List<int>()); } value.Add(i); } } } } public static class KeyRing { private static string parsed; private static List<string> prefabs = new List<string>(); 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(I