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 InventoryReforged v0.1.1
InventoryReforged.dll
Decompiled a day agousing System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Reflection; using System.Reflection.Emit; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Text; using BepInEx; using BepInEx.Configuration; using HarmonyLib; using Microsoft.CodeAnalysis; using TMPro; using UnityEngine; using UnityEngine.Events; using UnityEngine.UI; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")] [assembly: AssemblyCompany("InventoryReforged")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0+c22b6113e73f7d18e66f88d4ffc9bfcb6a2808b2")] [assembly: AssemblyProduct("InventoryReforged")] [assembly: AssemblyTitle("InventoryReforged")] [assembly: AssemblyVersion("1.0.0.0")] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace InventoryReforged { public static class ArmourSlots { [HarmonyPatch(typeof(Player), "SetInventorySize")] private static class OneRowTaller { private static bool Prefix(Player __instance, int rows) { if (!On) { return true; } rows = Mathf.Clamp(rows, 0, 9); ((Humanoid)__instance).GetInventory().SetHeight(rows + 1); __instance.AddUniqueKeyValue("invrows", rows.ToString()); InventoryGui.instance.SetInventorySize(rows + 1); if ((Object)(object)__instance == (Object)(object)Player.m_localPlayer) { s_sized = true; } ((Humanoid)__instance).DropInvalidItems(); return false; } } [HarmonyPatch(typeof(Player), "Awake")] private static class ResetOnNewPlayer { private static void Postfix() { s_sized = false; } } [HarmonyPatch(typeof(Player), "Update")] private static class ReconcileEachFrame { private static void Postfix(Player __instance) { if (On && (Object)(object)__instance == (Object)(object)Player.m_localPlayer) { Reconcile(__instance); } } } [HarmonyPatch(typeof(Inventory), "FindEmptySlot")] private static class SlotSearchMainGridOnly { private static void Prefix(Inventory __instance, ref int __state) { __state = -1; if (IsLocal(__instance)) { __state = Height.Invoke(__instance); Height.Invoke(__instance) = __state - 1; } } private static void Postfix(Inventory __instance, int __state) { if (__state >= 0) { Height.Invoke(__instance) = __state; } } } [HarmonyPatch(typeof(Inventory), "GetEmptySlots")] private static class CountMainGrid { private static bool Prefix(Inventory __instance, ref int __result) { if (!IsLocal(__instance)) { return true; } __result = MainFreeSlots(__instance); return false; } } [HarmonyPatch(typeof(Inventory), "HaveEmptySlot")] private static class HaveMainGridSlot { private static bool Prefix(Inventory __instance, ref bool __result) { if (!IsLocal(__instance)) { return true; } __result = MainFreeSlots(__instance) > 0; return false; } } [HarmonyPatch(typeof(Inventory), "CanAddItem", new Type[] { typeof(ItemData), typeof(int) })] private static class CanAddToMainGrid { private static bool Prefix(Inventory __instance, ItemData item, int stack, ref bool __result) { if (!IsLocal(__instance)) { return true; } if (stack <= 0) { stack = item.m_stack; } __result = __instance.FindFreeStackSpace(item.m_shared.m_name, (float)item.m_worldLevel) + MainFreeSlots(__instance) * item.m_shared.m_maxStackSize >= stack; return false; } } [HarmonyPatch(typeof(InventoryGrid), "DropItem")] private static class DropRules { private static bool Prefix(InventoryGrid __instance, ItemData item, Vector2i pos, ref bool __result) { //IL_000d: 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_0037: Unknown result type (might be due to invalid IL or missing references) if (!IsLocal(__instance.GetInventory()) || pos.y != RowOf(__instance.GetInventory())) { return true; } if (pos.x >= Slots.Length || SlotFor(item) != pos.x) { __result = false; return false; } return true; } private static void Postfix(InventoryGrid __instance, Vector2i pos, bool __result) { //IL_0010: 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_0030: Unknown result type (might be due to invalid IL or missing references) if (__result && IsLocal(__instance.GetInventory()) && pos.y == RowOf(__instance.GetInventory())) { ItemData itemAt = __instance.GetInventory().GetItemAt(pos.x, pos.y); if (itemAt != null && !itemAt.m_equipped) { ((Humanoid)Player.m_localPlayer).EquipItem(itemAt, true); } } } } [HarmonyPatch(typeof(InventoryGrid), "UpdateGui")] private static class DressRow { private static void Postfix(InventoryGrid __instance) { //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_0053: Unknown result type (might be due to invalid IL or missing references) //IL_00cd: Unknown result type (might be due to invalid IL or missing references) //IL_011e: Unknown result type (might be due to invalid IL or missing references) //IL_0133: Unknown result type (might be due to invalid IL or missing references) //IL_0148: Unknown result type (might be due to invalid IL or missing references) //IL_015c: Unknown result type (might be due to invalid IL or missing references) Inventory inventory = __instance.GetInventory(); if (!IsLocal(inventory)) { return; } int num = RowOf(inventory); foreach (InventoryElement item in Elements.Invoke(__instance)) { if (!Object.op_Implicit((Object)(object)item) || item.Position.y != num) { continue; } if (item.Position.x >= Slots.Length) { if (((Component)item).gameObject.activeSelf) { ((Component)item).gameObject.SetActive(false); } continue; } Transform obj = ((Component)item).transform.Find("binding"); TMP_Text val = ((obj != null) ? ((Component)obj).GetComponent<TMP_Text>() : null); if (Object.op_Implicit((Object)(object)val) && !((Behaviour)val).enabled) { ((Behaviour)val).enabled = true; val.text = Labels[item.Position.x]; val.fontSize *= 0.8f; val.enableWordWrapping = false; val.overflowMode = (TextOverflowModes)0; val.alignment = (TextAlignmentOptions)257; RectTransform rectTransform = val.rectTransform; rectTransform.anchorMin = new Vector2(0f, 0f); rectTransform.anchorMax = new Vector2(1f, 1f); rectTransform.offsetMin = new Vector2(4f, 0f); rectTransform.offsetMax = new Vector2(0f, -2f); Tint(item); } } } } private static bool s_sized; private static readonly ItemType[] Slots; private static readonly string[] Labels; private static readonly Color SlotTint; private static readonly FieldRef<Inventory, int> Height; private static readonly FieldRef<InventoryGrid, List<InventoryElement>> Elements; private static readonly FieldRef<Inventory, List<ItemData>> Items; private static bool On => Plugin.ArmourSlots.Value; private static int RowOf(Inventory inv) { return inv.GetHeight() - 1; } private static bool IsLocal(Inventory inv) { if (On && s_sized && Object.op_Implicit((Object)(object)Player.m_localPlayer)) { return ((Humanoid)Player.m_localPlayer).GetInventory() == inv; } return false; } public static int SlotFor(ItemData item) { //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Invalid comparison between I4 and Unknown for (int i = 0; i < Slots.Length; i++) { if ((int)Slots[i] == (int)item.m_shared.m_itemType) { return i; } } return -1; } private static bool InSlot(Inventory inv, ItemData item) { return item.m_gridPos.y == RowOf(inv); } private static void Relocate(Inventory inv, ItemData item, Vector2i pos) { //IL_000a: Unknown result type (might be due to invalid IL or missing references) inv.RemoveItem(item); if (!inv.AddItem(item, pos)) { inv.AddItem(item); } } private static void Reconcile(Player player) { //IL_004c: 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_00bd: Unknown result type (might be due to invalid IL or missing references) //IL_00c2: Unknown result type (might be due to invalid IL or missing references) //IL_005e: Unknown result type (might be due to invalid IL or missing references) //IL_0065: Unknown result type (might be due to invalid IL or missing references) //IL_00d7: Unknown result type (might be due to invalid IL or missing references) //IL_00a2: 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_007e: Unknown result type (might be due to invalid IL or missing references) //IL_0096: Unknown result type (might be due to invalid IL or missing references) Inventory inventory = ((Humanoid)player).GetInventory(); int num = RowOf(inventory); Vector2i val = default(Vector2i); foreach (ItemData item in new List<ItemData>(inventory.GetAllItems())) { int num2 = SlotFor(item); if (item.m_equipped && num2 >= 0) { ((Vector2i)(ref val))..ctor(num2, num); if (item.m_gridPos == val) { continue; } ItemData itemAt = inventory.GetItemAt(val.x, val.y); if (itemAt != null) { Vector2i gridPos = itemAt.m_gridPos; inventory.RemoveItem(itemAt); if (!inventory.AddItem(itemAt)) { inventory.AddItem(itemAt, gridPos); continue; } } Relocate(inventory, item, val); } else if (InSlot(inventory, item) && !item.m_equipped) { Vector2i gridPos2 = item.m_gridPos; inventory.RemoveItem(item); if (!inventory.AddItem(item)) { inventory.AddItem(item, gridPos2); } } } } private static int MainFreeSlots(Inventory inv) { int num = RowOf(inv); int num2 = 0; foreach (ItemData item in Items.Invoke(inv)) { if (item.m_gridPos.y < num) { num2++; } } return inv.GetWidth() * num - num2; } private static void Tint(InventoryElement el) { //IL_004c: Unknown result type (might be due to invalid IL or missing references) Image component = ((Component)el).GetComponent<Image>(); if (!Object.op_Implicit((Object)(object)component)) { Transform val = ((Component)el).transform.Find("bkg") ?? ((Component)el).transform.Find("background"); if (Object.op_Implicit((Object)(object)val)) { component = ((Component)val).GetComponent<Image>(); } } if (Object.op_Implicit((Object)(object)component)) { ((Graphic)component).color = SlotTint; } } static ArmourSlots() { //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) ItemType[] array = new ItemType[6]; RuntimeHelpers.InitializeArray(array, (RuntimeFieldHandle)/*OpCode not supported: LdMemberToken*/); Slots = (ItemType[])(object)array; Labels = new string[6] { "Head", "Chest", "Legs", "Cape", "Util", "Trinket" }; SlotTint = new Color(0.85f, 0.7f, 0.45f, 1f); Height = AccessTools.FieldRefAccess<Inventory, int>("m_height"); Elements = AccessTools.FieldRefAccess<InventoryGrid, List<InventoryElement>>("m_elements"); Items = AccessTools.FieldRefAccess<Inventory, List<ItemData>>("m_inventory"); } } public static class CraftFromChests { [HarmonyPatch(typeof(Inventory), "CountItems")] private static class PoolCount { private static void Postfix(Inventory __instance, string name, int quality, bool matchWorldLevel, ref int __result) { if (Active && IsLocal(__instance)) { __result += ChestCount(name, quality, matchWorldLevel); } } } [HarmonyPatch(typeof(Inventory), "CountItemsByName")] private static class PoolCountByName { private static void Postfix(Inventory __instance, string[] names, int quality, bool matchWorldLevel, ref int __result) { if (Active && IsLocal(__instance)) { foreach (string name in names) { __result += ChestCount(name, quality, matchWorldLevel); } } } } [HarmonyPatch(typeof(Inventory), "HaveItem", new Type[] { typeof(string), typeof(bool) })] private static class PoolHave { private static void Postfix(Inventory __instance, string name, bool matchWorldLevel, ref bool __result) { if (!__result && Active && IsLocal(__instance)) { __result = ChestCount(name, -1, matchWorldLevel) > 0; } } } [HarmonyPatch(typeof(Inventory), "RemoveItem", new Type[] { typeof(string), typeof(int), typeof(int), typeof(bool) })] private static class PoolRemove { private static bool Prefix(Inventory __instance, string name, int amount, int itemQuality, bool worldLevelBased) { if (!Active || !IsLocal(__instance)) { return true; } s_bypass = true; try { int num = Mathf.Min(__instance.CountItems(name, itemQuality, worldLevelBased), amount); if (num > 0) { __instance.RemoveItem(name, num, itemQuality, worldLevelBased); } if (amount - num > 0) { ChestRemove(name, amount - num, itemQuality, worldLevelBased); } } finally { s_bypass = false; } return false; } } [HarmonyPatch(typeof(Player), "HaveRequirements", new Type[] { typeof(Recipe), typeof(bool), typeof(int), typeof(int) })] private static class Scope1 { private static void Prefix() { Enter(); } private static void Postfix() { Exit(); } } [HarmonyPatch(typeof(Player), "HaveRequirements", new Type[] { typeof(Piece), typeof(RequirementMode) })] private static class Scope2 { private static void Prefix() { Enter(); } private static void Postfix() { Exit(); } } [HarmonyPatch(typeof(Player), "GetFirstRequiredItem")] private static class Scope3 { private static void Prefix() { Enter(); } private static void Postfix() { Exit(); } } [HarmonyPatch(typeof(Player), "ConsumeResources")] private static class Scope4 { private static void Prefix() { Enter(); } private static void Postfix() { Exit(); } } [HarmonyPatch(typeof(InventoryGui), "SetupRequirement")] private static class Scope5 { private static void Prefix() { Enter(); } private static void Postfix() { Exit(); } } [HarmonyPatch(typeof(Smelter), "OnAddFuel")] private static class Scope6 { private static void Prefix() { Enter(); } private static void Postfix() { Exit(); } } [HarmonyPatch(typeof(Smelter), "CanUseItems")] private static class Scope7 { private static void Prefix() { Enter(); } private static void Postfix() { Exit(); } } [HarmonyPatch(typeof(CookingStation), "OnAddFuelSwitch")] private static class Scope8 { private static void Prefix() { Enter(); } private static void Postfix() { Exit(); } } [HarmonyPatch(typeof(CookingStation), "CanUseItems")] private static class Scope9 { private static void Prefix() { Enter(); } private static void Postfix() { Exit(); } } [HarmonyPatch(typeof(Fireplace), "Interact")] private static class Scope10 { private static void Prefix() { Enter(); } private static void Postfix() { Exit(); } } [HarmonyPatch(typeof(Fireplace), "UseItem")] private static class Scope11 { private static void Prefix() { Enter(); } private static void Postfix() { Exit(); } } [HarmonyPatch(typeof(Fireplace), "CanUseItems")] private static class Scope12 { private static void Prefix() { Enter(); } private static void Postfix() { Exit(); } } [HarmonyPatch(typeof(Smelter), "OnAddOre")] private static class PullOre { private static void Prefix(Smelter __instance, Humanoid user, ItemData item) { if (item == null) { PullCookable(user, Froms(__instance.m_conversion)); } } } [HarmonyPatch(typeof(CookingStation), "Interact")] private static class PullFood { private static void Prefix(CookingStation __instance, Humanoid user, bool hold) { if (!hold) { PullCookable(user, Froms(__instance.m_conversion)); } } } [HarmonyPatch(typeof(Fermenter), "Interact")] private static class PullBrew { private static void Prefix(Fermenter __instance, Humanoid user, bool hold) { if (!hold) { PullCookable(user, Froms(__instance.m_conversion)); } } } private static int s_depth; private static bool s_bypass; private static float s_cacheTime = -1f; private static List<Container> s_cache = new List<Container>(); private static bool Active { get { if (Plugin.CraftFromChests.Value && s_depth > 0) { return !s_bypass; } return false; } } private static bool IsLocal(Inventory inv) { if (Object.op_Implicit((Object)(object)Player.m_localPlayer)) { return ((Humanoid)Player.m_localPlayer).GetInventory() == inv; } return false; } public static List<Container> Nearby() { //IL_0036: Unknown result type (might be due to invalid IL or missing references) Player localPlayer = Player.m_localPlayer; if (!Object.op_Implicit((Object)(object)localPlayer)) { return new List<Container>(); } if (Time.time - s_cacheTime > 0.5f) { s_cacheTime = Time.time; s_cache = Stash.FindNearby(((Component)localPlayer).transform.position, Plugin.CraftRange.Value); s_cache.RemoveAll(delegate(Container c) { ZNetView component = ((Component)c).GetComponent<ZNetView>(); return !component.IsOwner() && component.GetZDO().GetInt(ZDOVars.s_inUse, 0) == 1; }); } return s_cache; } private static int ChestCount(string name, int quality, bool wl) { int num = 0; foreach (Container item in Nearby()) { num += item.GetInventory().CountItems(name, quality, wl); } return num; } private static void ChestRemove(string name, int amount, int quality, bool wl) { foreach (Container item in Nearby()) { if (amount <= 0) { break; } Inventory inventory = item.GetInventory(); int num = inventory.CountItems(name, quality, wl); if (num > 0) { int num2 = Mathf.Min(num, amount); ((Component)item).GetComponent<ZNetView>().ClaimOwnership(); inventory.RemoveItem(name, num2, quality, wl); amount -= num2; } } } public static ItemData PullOne(Humanoid user, string name) { Inventory inventory = user.GetInventory(); foreach (Container item2 in Nearby()) { Inventory inventory2 = item2.GetInventory(); ItemData item = inventory2.GetItem(name, -1, false); if (item != null) { if (!inventory.CanAddItem(item, 1)) { ((Character)user).Message((MessageType)2, "$msg_noroom", 0, (Sprite)null, false); return null; } ((Component)item2).GetComponent<ZNetView>().ClaimOwnership(); ItemData val = item.Clone(); val.m_stack = 1; inventory2.RemoveItem(item, 1); if (inventory.AddItem(val)) { return inventory.GetItem(name, -1, false); } inventory2.AddItem(val); return null; } } return null; } private static ItemData FirstOwned(Humanoid user, IEnumerable<ItemDrop> froms) { foreach (ItemDrop from in froms) { if (Object.op_Implicit((Object)(object)from)) { ItemData item = user.GetInventory().GetItem(from.m_itemData.m_shared.m_name, -1, false); if (item != null) { return item; } } } return null; } private static void PullCookable(Humanoid user, IEnumerable<ItemDrop> froms) { if (!Plugin.CraftFromChests.Value || !Object.op_Implicit((Object)(object)user) || (Object)(object)user != (Object)(object)Player.m_localPlayer || FirstOwned(user, froms) != null) { return; } foreach (ItemDrop from in froms) { if (Object.op_Implicit((Object)(object)from) && PullOne(user, from.m_itemData.m_shared.m_name) != null) { break; } } } private static void Enter() { s_depth++; } private static void Exit() { s_depth--; } private static IEnumerable<ItemDrop> Froms(List<ItemConversion> l) { foreach (ItemConversion item in l) { yield return item.m_from; } } private static IEnumerable<ItemDrop> Froms(List<ItemConversion> l) { foreach (ItemConversion item in l) { yield return item.m_from; } } private static IEnumerable<ItemDrop> Froms(List<ItemConversion> l) { foreach (ItemConversion item in l) { yield return item.m_from; } } } public static class Favourites { [HarmonyPatch(typeof(InventoryGui), "OnSelectedItem")] private static class ToggleOnAltClick { private static readonly FieldRef<InventoryGui, GameObject> DragGo = AccessTools.FieldRefAccess<InventoryGui, GameObject>("m_dragGo"); private static bool Prefix(InventoryGui __instance, InventoryGrid grid, ItemData item, Modifier mod) { //IL_0003: Unknown result type (might be due to invalid IL or missing references) if (item == null || (int)mod != 0 || !AltHeld() || Object.op_Implicit((Object)(object)DragGo.Invoke(__instance))) { return true; } if (!Object.op_Implicit((Object)(object)Player.m_localPlayer) || grid.GetInventory() != ((Humanoid)Player.m_localPlayer).GetInventory()) { return true; } Toggle(item); return false; } } [HarmonyPatch(typeof(InventoryGrid), "UpdateGui")] private static class ToggleOnKey { private static void Postfix(InventoryGrid __instance, Player player) { //IL_000d: 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_0057: Unknown result type (might be due to invalid IL or missing references) //IL_0062: Unknown result type (might be due to invalid IL or missing references) if (!Object.op_Implicit((Object)(object)player)) { return; } KeyboardShortcut value = Plugin.FavouriteKey.Value; if (!((KeyboardShortcut)(ref value)).IsDown() || __instance.GetInventory() != ((Humanoid)player).GetInventory()) { return; } InventoryElement value2 = Traverse.Create((object)__instance).Method("GetHoveredElement", Array.Empty<object>()).GetValue<InventoryElement>(); if (Object.op_Implicit((Object)(object)value2)) { ItemData itemAt = __instance.GetInventory().GetItemAt(value2.Position.x, value2.Position.y); if (itemAt != null) { Toggle(itemAt); } } } } [HarmonyPatch(typeof(InventoryGrid), "UpdateGui")] private static class DrawStar { private static readonly FieldRef<InventoryGrid, List<InventoryElement>> Elements = AccessTools.FieldRefAccess<InventoryGrid, List<InventoryElement>>("m_elements"); private static readonly Dictionary<InventoryElement, TMP_Text> s_stars = new Dictionary<InventoryElement, TMP_Text>(); private static void Postfix(InventoryGrid __instance) { //IL_0031: 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) Inventory inventory = __instance.GetInventory(); if (inventory == null) { return; } foreach (InventoryElement item in Elements.Invoke(__instance)) { if (!Object.op_Implicit((Object)(object)item)) { continue; } ItemData itemAt = inventory.GetItemAt(item.Position.x, item.Position.y); bool flag = itemAt != null && Is(itemAt); if (!s_stars.TryGetValue(item, out var value) || !Object.op_Implicit((Object)(object)value)) { if (!flag) { continue; } value = MakeStar(item); if (!Object.op_Implicit((Object)(object)value)) { continue; } s_stars[item] = value; } ((Behaviour)value).enabled = flag; } } private static TMP_Text MakeStar(InventoryElement el) { //IL_0081: Unknown result type (might be due to invalid IL or missing references) //IL_00a6: Unknown result type (might be due to invalid IL or missing references) //IL_00bb: Unknown result type (might be due to invalid IL or missing references) //IL_00d0: Unknown result type (might be due to invalid IL or missing references) //IL_00e4: Unknown result type (might be due to invalid IL or missing references) Transform val = ((Component)el).transform.Find("binding"); if (!Object.op_Implicit((Object)(object)val)) { return null; } GameObject obj = Object.Instantiate<GameObject>(((Component)val).gameObject, ((Component)el).transform); ((Object)obj).name = "IR_star"; TMP_Text component = obj.GetComponent<TMP_Text>(); component.text = ((Object.op_Implicit((Object)(object)component.font) && component.font.HasCharacter('★', false, false)) ? "★" : "*"); ((Graphic)component).color = new Color(1f, 0.85f, 0.2f); component.alignment = (TextAlignmentOptions)260; RectTransform component2 = obj.GetComponent<RectTransform>(); component2.anchorMin = new Vector2(0f, 0f); component2.anchorMax = new Vector2(1f, 1f); component2.offsetMin = new Vector2(2f, 2f); component2.offsetMax = new Vector2(-4f, -2f); return component; } } private const string Key = "IR_fav"; public static bool Is(ItemData item) { if (item?.m_customData != null) { return item.m_customData.ContainsKey("IR_fav"); } return false; } public static void Toggle(ItemData item) { if (Is(item)) { item.m_customData.Remove("IR_fav"); } else { item.m_customData["IR_fav"] = "1"; } } private static bool AltHeld() { if (!ZInput.GetKey((KeyCode)308, true)) { return ZInput.GetKey((KeyCode)307, true); } return true; } } [HarmonyPatch(typeof(InventoryGui), "Show", new Type[] { typeof(Container), typeof(int) })] internal static class LayoutDump { private static bool s_done; private static void Postfix(InventoryGui __instance) { if (!s_done && Plugin.DebugLayout.Value) { s_done = true; StringBuilder stringBuilder = new StringBuilder("[IR layout]\n"); Dump((Transform)(object)__instance.m_player, 0, stringBuilder); Dump((Transform)(object)__instance.m_container, 0, stringBuilder); Debug.Log((object)stringBuilder.ToString()); } } private static void Dump(Transform t, int depth, StringBuilder sb) { //IL_003d: 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_0059: 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_0061: 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_007d: Unknown result type (might be due to invalid IL or missing references) //IL_008b: Unknown result type (might be due to invalid IL or missing references) if (depth > 3) { return; } RectTransform val = (RectTransform)(object)((t is RectTransform) ? t : null); sb.Append(' ', depth * 2).Append(((Object)t).name); if (Object.op_Implicit((Object)(object)val)) { object[] obj = new object[7] { val.anchoredPosition, val.sizeDelta, null, null, null, null, null }; Rect rect = val.rect; obj[2] = ((Rect)(ref rect)).size; obj[3] = val.anchorMin; obj[4] = val.anchorMax; obj[5] = val.pivot; obj[6] = ((Component)t).gameObject.activeSelf; sb.Append(string.Format(" pos={0} size={1} rect={2} aMin={3} aMax={4} pivot={5} active={6}", obj)); } Component[] components = ((Component)t).GetComponents<Component>(); foreach (Component val2 in components) { if (Object.op_Implicit((Object)(object)val2) && !(val2 is Transform)) { sb.Append(" [").Append(((object)val2).GetType().Name).Append(']'); } } sb.Append('\n'); for (int j = 0; j < t.childCount; j++) { Dump(t.GetChild(j), depth + 1, sb); } } } [BepInPlugin("games.loxley.inventoryreforged", "InventoryReforged", "0.1.1")] public class Plugin : BaseUnityPlugin { public const string PluginGUID = "games.loxley.inventoryreforged"; public const string PluginName = "InventoryReforged"; public const string PluginVersion = "0.1.1"; public static ConfigEntry<KeyboardShortcut> StashKey; public static ConfigEntry<float> StashRange; public static ConfigEntry<bool> StashKeepHotbar; public static ConfigEntry<bool> StashPlayerBuiltOnly; public static ConfigEntry<KeyboardShortcut> FavouriteKey; public static ConfigEntry<bool> StashButton; public static ConfigEntry<float> StashButtonX; public static ConfigEntry<float> StashButtonY; public static ConfigEntry<float> StashButtonSize; public static ConfigEntry<bool> SharedChests; public static ConfigEntry<bool> ArmourSlots; public static ConfigEntry<bool> CraftFromChests; public static ConfigEntry<float> CraftRange; public static ConfigEntry<bool> DebugLayout; private void Awake() { //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_00a6: Unknown result type (might be due to invalid IL or missing references) //IL_01ef: Unknown result type (might be due to invalid IL or missing references) StashKey = ((BaseUnityPlugin)this).Config.Bind<KeyboardShortcut>("Stash", "Key", new KeyboardShortcut((KeyCode)112, Array.Empty<KeyCode>()), "Stash everything into nearby chests."); StashRange = ((BaseUnityPlugin)this).Config.Bind<float>("Stash", "Range", 10f, "How far (m) to look for chests."); StashKeepHotbar = ((BaseUnityPlugin)this).Config.Bind<bool>("Stash", "KeepHotbar", true, "Leave items on the hotbar alone."); StashPlayerBuiltOnly = ((BaseUnityPlugin)this).Config.Bind<bool>("Stash", "PlayerBuiltOnly", true, "Ignore chests you didn't build (dungeon chests, etc)."); FavouriteKey = ((BaseUnityPlugin)this).Config.Bind<KeyboardShortcut>("Stash", "FavouriteKey", new KeyboardShortcut((KeyCode)102, Array.Empty<KeyCode>()), "Press while hovering an item to favourite it (Alt+click also works where the desktop lets it through)."); StashButton = ((BaseUnityPlugin)this).Config.Bind<bool>("Stash", "ShowButton", true, "Add a Stash button to the inventory screen."); StashButtonX = ((BaseUnityPlugin)this).Config.Bind<float>("Stash", "ButtonX", 33f, "Button centre, relative to the bottom-right corner of the inventory panel."); StashButtonY = ((BaseUnityPlugin)this).Config.Bind<float>("Stash", "ButtonY", 8f, "Button centre, relative to the bottom-right corner of the inventory panel."); StashButtonSize = ((BaseUnityPlugin)this).Config.Bind<float>("Stash", "ButtonSize", 38f, "Button width and height (px)."); SharedChests = ((BaseUnityPlugin)this).Config.Bind<bool>("SharedChests", "Enabled", true, "Let more than one player use a chest at the same time. Everyone needs the mod."); ArmourSlots = ((BaseUnityPlugin)this).Config.Bind<bool>("ArmourSlots", "Enabled", true, "Extra row with head / chest / legs / cape / utility / trinket slots."); CraftFromChests = ((BaseUnityPlugin)this).Config.Bind<bool>("CraftFromChests", "Enabled", true, "Crafting, building and stations (smelter, kiln, fire, cooking, fermenter) use items from nearby chests."); CraftRange = ((BaseUnityPlugin)this).Config.Bind<float>("CraftFromChests", "Range", 15f, "How far (m) to look for chests when crafting."); DebugLayout = ((BaseUnityPlugin)this).Config.Bind<bool>("Debug", "DumpLayout", false, "Log the inventory panel hierarchy once when the inventory opens."); new Harmony("games.loxley.inventoryreforged").PatchAll(); } private void Update() { //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Unknown result type (might be due to invalid IL or missing references) if (!Object.op_Implicit((Object)(object)Player.m_localPlayer)) { return; } KeyboardShortcut value = StashKey.Value; if (((KeyboardShortcut)(ref value)).IsDown() && !Console.IsVisible()) { Chat instance = Chat.instance; if ((instance == null || !instance.HasFocus()) && !TextInput.IsVisible() && !Menu.IsVisible()) { Stash.Run(Player.m_localPlayer); } } } } public static class SharedChest { private class PendingPut { public ItemData Item; public Inventory From; public int Amount; public Vector2i Origin; public float Sent; } private class PendingTake { public Container Chest; public Vector2i Slot; public Inventory To; public int X; public int Y; public bool Drop; public float Sent; } [HarmonyPatch(typeof(Container), "Awake")] private static class RegisterRpcs { private static void Postfix(Container __instance) { ZNetView val = View(__instance); if (Object.op_Implicit((Object)(object)val) && val.GetZDO() != null) { Container c = __instance; val.Register<ZPackage>("IR_Put", (Action<long, ZPackage>)delegate(long s, ZPackage p) { OnPut(c, s, p); }); val.Register<ZPackage>("IR_PutResp", (Action<long, ZPackage>)delegate(long s, ZPackage p) { OnPutResp(c, s, p); }); val.Register<ZPackage>("IR_Take", (Action<long, ZPackage>)delegate(long s, ZPackage p) { OnTake(c, s, p); }); val.Register<ZPackage>("IR_TakeResp", (Action<long, ZPackage>)delegate(long s, ZPackage p) { OnTakeResp(c, s, p); }); val.Register<ZPackage>("IR_Move", (Action<long, ZPackage>)delegate(long s, ZPackage p) { OnMove(c, s, p); }); val.Register<ZPackage>("IR_Eat", (Action<long, ZPackage>)delegate(long s, ZPackage p) { OnEat(c, s, p); }); val.Register<ZPackage>("IR_EatResp", (Action<long, ZPackage>)delegate(long s, ZPackage p) { OnEatResp(c, s, p); }); } } } [HarmonyPatch(typeof(Container), "RPC_RequestOpen")] private static class GrantGuestOpen { private static bool Prefix(Container __instance, long uid, long playerID) { return GrantWithoutOwnership(__instance, uid, playerID, "RPC_OpenResponse"); } } [HarmonyPatch(typeof(Container), "RPC_RequestStack")] private static class GrantGuestStack { private static bool Prefix(Container __instance, long uid, long playerID) { return GrantWithoutOwnership(__instance, uid, playerID, "RPC_StackResponse"); } } [HarmonyPatch(typeof(Container), "RPC_StackResponse")] private static class RouteStackGrant { [HarmonyPriority(200)] private static bool Prefix(Container __instance, bool granted) { ZNetView val = View(__instance); if (!granted || !Object.op_Implicit((Object)(object)val) || !val.IsValid() || val.IsOwner() || !Object.op_Implicit((Object)(object)Player.m_localPlayer)) { return true; } PutMatching(__instance, ((Humanoid)Player.m_localPlayer).GetInventory()); return false; } } [HarmonyPatch(typeof(InventoryGui), "UpdateContainer")] private static class KeepGuestPanelOpen { private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> il) { MethodInfo target = AccessTools.Method(typeof(Container), "IsOwner", (Type[])null, (Type[])null); MethodInfo repl = AccessTools.Method(typeof(SharedChest), "OwnerOrGuest", (Type[])null, (Type[])null); foreach (CodeInstruction item in il) { yield return CodeInstructionExtensions.Calls(item, target) ? CodeInstructionExtensions.WithBlocks(CodeInstructionExtensions.WithLabels(new CodeInstruction(OpCodes.Call, (object)repl), (IEnumerable<Label>)item.labels), (IEnumerable<ExceptionBlock>)item.blocks) : item; } } private static void Prefix() { ExpireLocks(); Container current = Current; if (Object.op_Implicit((Object)(object)current) && IsGuestOf(current)) { Traverse.Create((object)current).Method("Load", Array.Empty<object>()).GetValue<bool>(); } } } [HarmonyPatch(typeof(Inventory), "Load", new Type[] { typeof(ZPackage) })] private static class KeepDragAcrossReload { private static void Postfix(Inventory __instance) { InventoryGui instance = InventoryGui.instance; if (!Object.op_Implicit((Object)(object)instance) || DragItem.Invoke(instance) == null || DragInventory.Invoke(instance) != __instance) { return; } Container current = Current; if (Object.op_Implicit((Object)(object)current) && current.GetInventory() == __instance) { ItemData val = DragItem.Invoke(instance); ItemData itemAt = __instance.GetItemAt(val.m_gridPos.x, val.m_gridPos.y); if (itemAt == null || NameOf(itemAt) != NameOf(val)) { SetupDrag(null, null, 1); } else { SetupDrag(itemAt, __instance, Mathf.Min(itemAt.m_stack, DragAmount.Invoke(instance))); } } } } [HarmonyPatch(typeof(InventoryGrid), "DropItem")] private static class RouteDrops { private static bool Prefix(InventoryGrid __instance, Inventory fromInventory, ItemData item, int amount, Vector2i pos, ref bool __result) { //IL_0046: Unknown result type (might be due to invalid IL or missing references) //IL_005a: Unknown result type (might be due to invalid IL or missing references) //IL_006d: 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) //IL_00a2: Unknown result type (might be due to invalid IL or missing references) //IL_00a9: Unknown result type (might be due to invalid IL or missing references) //IL_008c: Unknown result type (might be due to invalid IL or missing references) //IL_0093: Unknown result type (might be due to invalid IL or missing references) //IL_010a: Unknown result type (might be due to invalid IL or missing references) //IL_0111: Unknown result type (might be due to invalid IL or missing references) Inventory inventory = __instance.GetInventory(); Container container; bool flag = IsGuest(inventory, out container); Container container2; bool flag2 = IsGuest(fromInventory, out container2); if (!flag && !flag2) { if (!IsLocked(item)) { return true; } return Refuse(ref __result); } __result = true; if (IsLocked(item) || (flag2 && s_lockedChestSlots.Contains(item.m_gridPos)) || (flag && s_lockedChestSlots.Contains(pos))) { return false; } if (flag && flag2) { Move(container, item, amount, pos.x, pos.y); } else if (flag) { Put(container, fromInventory, item, amount, pos.x, pos.y); } else { ItemData itemAt = inventory.GetItemAt(pos.x, pos.y); if (itemAt != null && !CanStack(itemAt, item) && !IsLocked(itemAt) && !((Humanoid)Player.m_localPlayer).IsItemEquiped(itemAt)) { Put(container2, inventory, itemAt, itemAt.m_stack, item.m_gridPos.x, item.m_gridPos.y); } else { Take(container2, item, amount, inventory, pos.x, pos.y); } } return false; } private static bool Refuse(ref bool result) { result = false; return false; } } [HarmonyPatch(typeof(InventoryGui), "OnSelectedItem")] private static class IgnoreLockedClicks { [HarmonyPriority(600)] private static bool Prefix(InventoryGrid grid, ItemData item, Vector2i pos) { //IL_0010: Unknown result type (might be due to invalid IL or missing references) if (IsLocked(item)) { return false; } if (IsLockedChestSlot(grid.GetInventory(), pos)) { return false; } return true; } } [HarmonyPatch(typeof(InventoryGui), "OnRightClickItem")] private static class RouteEat { private static bool Prefix(InventoryGrid grid, ItemData item) { if (item == null || !IsGuest(grid.GetInventory(), out var container)) { return true; } if (Object.op_Implicit((Object)(object)Player.m_localPlayer) && ((Humanoid)Player.m_localPlayer).CanConsumeItem(item, false)) { Eat(container, item); } return false; } } [HarmonyPatch(typeof(Inventory), "MoveItemToThis", new Type[] { typeof(Inventory), typeof(ItemData) })] private static class RouteQuickMove { private static bool Prefix(Inventory __instance, Inventory fromInventory, ItemData item) { if (IsGuest(__instance, out var container)) { Put(container, fromInventory, item, item.m_stack, -1, -1); return false; } if (IsGuest(fromInventory, out var container2)) { if (__instance.CanAddItem(item, -1)) { Take(container2, item, item.m_stack, __instance, -1, -1); } return false; } return !IsLocked(item); } } [HarmonyPatch(typeof(Inventory), "MoveAll")] private static class RouteTakeAll { private static bool Prefix(Inventory __instance, Inventory fromInventory) { if (!IsGuest(fromInventory, out var container)) { return true; } foreach (ItemData item in new List<ItemData>(fromInventory.GetAllItems())) { if (__instance.CanAddItem(item, -1)) { Take(container, item, item.m_stack, __instance, -1, -1); } } return false; } } [HarmonyPatch(typeof(Inventory), "StackAll")] private static class RoutePlaceStacks { [HarmonyPriority(600)] private static bool Prefix(Inventory __instance, Inventory fromInventory, ref int __result) { if (!IsGuest(__instance, out var container)) { return true; } PutMatching(container, fromInventory); __result = 0; return false; } } [HarmonyPatch(typeof(Container), "StackAll")] private static class RouteHoldToStack { private static bool Prefix(Container __instance) { if (!IsGuestOf(__instance) || !Object.op_Implicit((Object)(object)Player.m_localPlayer)) { return true; } PutMatching(__instance, ((Humanoid)Player.m_localPlayer).GetInventory()); return false; } } [HarmonyPatch(typeof(InventoryGui), "OnDropOutside")] private static class RouteDropOutside { private static bool Prefix(InventoryGui __instance) { //IL_0040: Unknown result type (might be due to invalid IL or missing references) if (!Object.op_Implicit((Object)(object)DragGo.Invoke(__instance)) || !IsGuest(DragInventory.Invoke(__instance), out var container)) { return true; } ItemData val = DragItem.Invoke(__instance); if (val != null && !s_lockedChestSlots.Contains(val.m_gridPos)) { Take(container, val, DragAmount.Invoke(__instance), null, -1, -1, drop: true); } SetupDrag(null, null, 1); return false; } } [HarmonyPatch(typeof(Humanoid), "DropItem")] private static class NoDropWhileLocked { private static bool Prefix(Inventory inventory, ItemData item, ref bool __result) { if (IsGuest(inventory, out var _) || IsLocked(item)) { __result = false; return false; } return true; } } [HarmonyPatch(typeof(Humanoid), "UseItem")] private static class NoUseWhileLocked { private static bool Prefix(ItemData item) { return !IsLocked(item); } } private const string RpcPut = "IR_Put"; private const string RpcPutResp = "IR_PutResp"; private const string RpcTake = "IR_Take"; private const string RpcTakeResp = "IR_TakeResp"; private const string RpcMove = "IR_Move"; private const string RpcEat = "IR_Eat"; private const string RpcEatResp = "IR_EatResp"; private const float Timeout = 5f; private static readonly FieldRef<InventoryGui, Container> CurrentContainer = AccessTools.FieldRefAccess<InventoryGui, Container>("m_currentContainer"); private static readonly FieldRef<InventoryGui, ItemData> DragItem = AccessTools.FieldRefAccess<InventoryGui, ItemData>("m_dragItem"); private static readonly FieldRef<InventoryGui, Inventory> DragInventory = AccessTools.FieldRefAccess<InventoryGui, Inventory>("m_dragInventory"); private static readonly FieldRef<InventoryGui, int> DragAmount = AccessTools.FieldRefAccess<InventoryGui, int>("m_dragAmount"); private static readonly FieldRef<InventoryGui, GameObject> DragGo = AccessTools.FieldRefAccess<InventoryGui, GameObject>("m_dragGo"); private static readonly FieldRef<Container, ZNetView> ContainerView = AccessTools.FieldRefAccess<Container, ZNetView>("m_nview"); private static readonly Dictionary<int, PendingPut> s_puts = new Dictionary<int, PendingPut>(); private static readonly Dictionary<int, PendingTake> s_takes = new Dictionary<int, PendingTake>(); private static readonly HashSet<ItemData> s_lockedItems = new HashSet<ItemData>(); private static readonly HashSet<Vector2i> s_lockedChestSlots = new HashSet<Vector2i>(); private static bool s_eating; private static float s_eatSent; private static int s_req; public static Container Current { get { if (!Object.op_Implicit((Object)(object)InventoryGui.instance)) { return null; } return CurrentContainer.Invoke(InventoryGui.instance); } } private static ZNetView View(Container c) { if (!Object.op_Implicit((Object)(object)c)) { return null; } return ContainerView.Invoke(c); } private static void SetupDrag(ItemData item, Inventory inv, int amount) { Traverse.Create((object)InventoryGui.instance).Method("SetupDragItem", new object[3] { item, inv, amount }).GetValue(); } public static bool IsGuest(Inventory inv, out Container container) { container = null; if (!Plugin.SharedChests.Value) { return false; } Container current = Current; if (!Object.op_Implicit((Object)(object)current) || current.GetInventory() != inv) { return false; } ZNetView val = View(current); if (!Object.op_Implicit((Object)(object)val) || !val.IsValid()) { return false; } if (!val.HasOwner()) { Traverse.Create((object)current).Method("Load", Array.Empty<object>()).GetValue<bool>(); val.ClaimOwnership(); return false; } if (val.IsOwner()) { return false; } container = current; return true; } public static bool IsGuestOf(Container c) { Container container; if (Object.op_Implicit((Object)(object)c) && (Object)(object)Current == (Object)(object)c) { return IsGuest(c.GetInventory(), out container); } return false; } private static ZPackage PackItem(ItemData item, int amount) { //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Expected O, but got Unknown ItemData obj = item.Clone(); obj.m_stack = amount; ZPackage val = new ZPackage(); val.Write(109); val.Write((ushort)1); obj.Save(val); return val; } private static ZPackage PackInventory(Inventory inv) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Expected O, but got Unknown ZPackage val = new ZPackage(); inv.Save(val); return val; } private static Inventory Unpack(ZPackage pkg) { //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Expected O, but got Unknown Inventory val = new Inventory("IR_tmp", (Sprite)null, 8, 8); val.Load(pkg); return val; } private static string NameOf(ItemData item) { return item.m_shared.m_name; } private static void DropInto(Inventory to, Inventory from, ItemData item, int amount, int x, int y) { //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_003d: 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) ItemData itemAt = to.GetItemAt(x, y); if (itemAt != item) { if (itemAt != null && !CanStack(itemAt, item) && item.m_stack == amount) { Vector2i gridPos = item.m_gridPos; from.RemoveItem(item); from.MoveItemToThis(to, itemAt, itemAt.m_stack, gridPos.x, gridPos.y); to.MoveItemToThis(from, item, amount, x, y); } else { to.MoveItemToThis(from, item, amount, x, y); } } } private static bool CanStack(ItemData a, ItemData b) { if (a.m_shared.m_name == b.m_shared.m_name && (b.m_shared.m_maxQuality <= 1 || a.m_quality == b.m_quality)) { return a.m_shared.m_maxStackSize > 1; } return false; } public static bool IsLocked(ItemData item) { if (item != null) { return s_lockedItems.Contains(item); } return false; } private static bool IsLockedChestSlot(Inventory inv, Vector2i pos) { //IL_000f: Unknown result type (might be due to invalid IL or missing references) if (IsGuest(inv, out var _)) { return s_lockedChestSlots.Contains(pos); } return false; } private static void ExpireLocks() { //IL_012d: Unknown result type (might be due to invalid IL or missing references) float time = Time.time; List<int> list = new List<int>(); foreach (KeyValuePair<int, PendingPut> s_put in s_puts) { if (time - s_put.Value.Sent > 5f) { list.Add(s_put.Key); } } foreach (int item in list) { s_lockedItems.Remove(s_puts[item].Item); s_puts.Remove(item); } list.Clear(); foreach (KeyValuePair<int, PendingTake> s_take in s_takes) { if (time - s_take.Value.Sent > 5f) { list.Add(s_take.Key); } } foreach (int item2 in list) { s_lockedChestSlots.Remove(s_takes[item2].Slot); s_takes.Remove(item2); } if (s_eating && time - s_eatSent > 5f) { s_eating = false; } } public static void Put(Container c, Inventory from, ItemData item, int amount, int x, int y) { //IL_0039: 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_005f: Unknown result type (might be due to invalid IL or missing references) //IL_0065: Expected O, but got Unknown if (!IsLocked(item)) { int num = ++s_req; s_puts[num] = new PendingPut { Item = item, From = from, Amount = amount, Origin = item.m_gridPos, Sent = Time.time }; s_lockedItems.Add(item); ZPackage val = new ZPackage(); val.Write(num); val.Write(x); val.Write(y); val.Write(PackItem(item, amount)); View(c).InvokeRPC("IR_Put", new object[1] { val }); } } public static void Take(Container c, ItemData chestItem, int amount, Inventory to, int toX, int toY, bool drop = false) { //IL_0006: 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_0074: Unknown result type (might be due to invalid IL or missing references) //IL_007f: Unknown result type (might be due to invalid IL or missing references) //IL_0085: Expected O, but got Unknown if (!s_lockedChestSlots.Contains(chestItem.m_gridPos)) { int num = ++s_req; s_takes[num] = new PendingTake { Chest = c, Slot = chestItem.m_gridPos, To = to, X = toX, Y = toY, Drop = drop, Sent = Time.time }; s_lockedChestSlots.Add(chestItem.m_gridPos); ZPackage val = new ZPackage(); val.Write(num); val.Write(chestItem.m_gridPos.x); val.Write(chestItem.m_gridPos.y); val.Write(amount); val.Write(NameOf(chestItem)); View(c).InvokeRPC("IR_Take", new object[1] { val }); } } public static void Move(Container c, ItemData chestItem, int amount, int toX, int toY) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Expected O, but got Unknown if (!s_lockedChestSlots.Contains(chestItem.m_gridPos)) { ZPackage val = new ZPackage(); val.Write(chestItem.m_gridPos.x); val.Write(chestItem.m_gridPos.y); val.Write(toX); val.Write(toY); val.Write(amount); val.Write(NameOf(chestItem)); View(c).InvokeRPC("IR_Move", new object[1] { val }); } } public static void Eat(Container c, ItemData chestItem) { //IL_000d: 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_0030: Expected O, but got Unknown if (!s_eating && !s_lockedChestSlots.Contains(chestItem.m_gridPos)) { s_eating = true; s_eatSent = Time.time; ZPackage val = new ZPackage(); val.Write(chestItem.m_gridPos.x); val.Write(chestItem.m_gridPos.y); val.Write(NameOf(chestItem)); View(c).InvokeRPC("IR_Eat", new object[1] { val }); } } public static void PutMatching(Container c, Inventory from) { Inventory inventory = c.GetInventory(); foreach (ItemData item in new List<ItemData>(from.GetAllItems())) { if (Stash.CanLeave(item, respectHotbar: false) && inventory.ContainsItemByName(NameOf(item))) { Put(c, from, item, item.m_stack, -1, -1); } } } private static void OnPutResp(Container c, long sender, ZPackage pkg) { //IL_00b0: Unknown result type (might be due to invalid IL or missing references) int key = pkg.ReadInt(); int num = pkg.ReadInt(); Inventory val = Unpack(pkg.ReadPackage()); if (!s_puts.TryGetValue(key, out var value)) { return; } s_puts.Remove(key); s_lockedItems.Remove(value.Item); if (num > 0 && value.From.ContainsItem(value.Item)) { value.From.RemoveItem(value.Item, Mathf.Min(num, value.Item.m_stack)); } foreach (ItemData item in new List<ItemData>(val.GetAllItems())) { val.RemoveItem(item); if (!value.From.AddItem(item, value.Origin) && !value.From.AddItem(item)) { DropAtFeet(item); } } } private static void OnTakeResp(Container c, long sender, ZPackage pkg) { //IL_0035: Unknown result type (might be due to invalid IL or missing references) int key = pkg.ReadInt(); Inventory val = Unpack(pkg.ReadPackage()); if (!s_takes.TryGetValue(key, out var value)) { return; } s_takes.Remove(key); s_lockedChestSlots.Remove(value.Slot); foreach (ItemData item in new List<ItemData>(val.GetAllItems())) { if (value.Drop) { val.RemoveItem(item); DropAtFeet(item); continue; } if (value.X >= 0) { ItemData itemAt = value.To.GetItemAt(value.X, value.Y); if (itemAt == null || CanStack(itemAt, item)) { value.To.MoveItemToThis(val, item, item.m_stack, value.X, value.Y); } } if (val.ContainsItem(item) && item.m_stack > 0 && value.To.AddItem(item)) { val.RemoveItem(item); } } foreach (ItemData item2 in new List<ItemData>(val.GetAllItems())) { val.RemoveItem(item2); if (IsGuestOf(c)) { PutLoose(c, item2); } else { DropAtFeet(item2); } } } private static void PutLoose(Container c, ItemData item) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Expected O, but got Unknown ZPackage val = new ZPackage(); val.Write(0); val.Write(-1); val.Write(-1); val.Write(PackItem(item, item.m_stack)); View(c).InvokeRPC("IR_Put", new object[1] { val }); } private static void OnEatResp(Container c, long sender, ZPackage pkg) { s_eating = false; Inventory val = Unpack(pkg.ReadPackage()); Player localPlayer = Player.m_localPlayer; foreach (ItemData item in new List<ItemData>(val.GetAllItems())) { if (!Object.op_Implicit((Object)(object)localPlayer) || !((Humanoid)localPlayer).CanConsumeItem(item, false) || !((Humanoid)localPlayer).ConsumeItem(val, item, false)) { val.RemoveItem(item); if (!Object.op_Implicit((Object)(object)localPlayer) || !((Humanoid)localPlayer).GetInventory().AddItem(item)) { DropAtFeet(item); } } } } private static void DropAtFeet(ItemData item) { //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_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_003f: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Unknown result type (might be due to invalid IL or missing references) Player localPlayer = Player.m_localPlayer; if (Object.op_Implicit((Object)(object)localPlayer) && item.m_stack > 0) { ItemDrop val = ItemDrop.DropItem(item, item.m_stack, ((Component)localPlayer).transform.position + ((Component)localPlayer).transform.forward + Vector3.up, ((Component)localPlayer).transform.rotation); if (Object.op_Implicit((Object)(object)val)) { val.OnPlayerDrop(); } } } private static void OnPut(Container c, long sender, ZPackage pkg) { //IL_0119: Unknown result type (might be due to invalid IL or missing references) //IL_0120: Expected O, but got Unknown //IL_00e5: Unknown result type (might be due to invalid IL or missing references) //IL_00ea: Unknown result type (might be due to invalid IL or missing references) //IL_00ef: Unknown result type (might be due to invalid IL or missing references) //IL_00f4: Unknown result type (might be due to invalid IL or missing references) if (!View(c).IsOwner()) { return; } int num = pkg.ReadInt(); int num2 = pkg.ReadInt(); int y = pkg.ReadInt(); Inventory val = Unpack(pkg.ReadPackage()); int num3 = 0; List<ItemData> allItems = val.GetAllItems(); if (allItems.Count > 0) { ItemData val2 = allItems[0]; int stack = val2.m_stack; if (num2 < 0) { num3 = (c.GetInventory().AddItem(val2) ? stack : (stack - val2.m_stack)); } else { DropInto(c.GetInventory(), val, val2, stack, num2, y); num3 = (val.ContainsItem(val2) ? (stack - val2.m_stack) : stack); } if (val.ContainsItem(val2)) { val.RemoveItem(val2); } } if (num == 0) { foreach (ItemData item in new List<ItemData>(val.GetAllItems())) { ItemDrop.DropItem(item, item.m_stack, ((Component)c).transform.position + Vector3.up, Quaternion.identity); } return; } ZPackage val3 = new ZPackage(); val3.Write(num); val3.Write(num3); val3.Write(PackInventory(val)); View(c).InvokeRPC(sender, "IR_PutResp", new object[1] { val3 }); } private static void OnTake(Container c, long sender, ZPackage pkg) { //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_0041: Expected O, but got Unknown //IL_0083: Unknown result type (might be due to invalid IL or missing references) //IL_008a: Expected O, but got Unknown if (View(c).IsOwner()) { int num = pkg.ReadInt(); int num2 = pkg.ReadInt(); int num3 = pkg.ReadInt(); int num4 = pkg.ReadInt(); string text = pkg.ReadString(); Inventory val = new Inventory("IR_tmp", (Sprite)null, 8, 8); ItemData itemAt = c.GetInventory().GetItemAt(num2, num3); if (itemAt != null && NameOf(itemAt) == text) { val.MoveItemToThis(c.GetInventory(), itemAt, Mathf.Min(num4, itemAt.m_stack), 0, 0); } ZPackage val2 = new ZPackage(); val2.Write(num); val2.Write(PackInventory(val)); View(c).InvokeRPC(sender, "IR_TakeResp", new object[1] { val2 }); } } private static void OnMove(Container c, long sender, ZPackage pkg) { if (View(c).IsOwner()) { int num = pkg.ReadInt(); int num2 = pkg.ReadInt(); int x = pkg.ReadInt(); int y = pkg.ReadInt(); int num3 = pkg.ReadInt(); string text = pkg.ReadString(); Inventory inventory = c.GetInventory(); ItemData itemAt = inventory.GetItemAt(num, num2); if (itemAt != null && NameOf(itemAt) == text) { DropInto(inventory, inventory, itemAt, Mathf.Min(num3, itemAt.m_stack), x, y); } } } private static void OnEat(Container c, long sender, ZPackage pkg) { //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Expected O, but got Unknown //IL_0065: Unknown result type (might be due to invalid IL or missing references) //IL_006c: Expected O, but got Unknown if (View(c).IsOwner()) { int num = pkg.ReadInt(); int num2 = pkg.ReadInt(); string text = pkg.ReadString(); Inventory val = new Inventory("IR_tmp", (Sprite)null, 8, 8); ItemData itemAt = c.GetInventory().GetItemAt(num, num2); if (itemAt != null && NameOf(itemAt) == text) { val.MoveItemToThis(c.GetInventory(), itemAt, 1, 0, 0); } ZPackage val2 = new ZPackage(); val2.Write(PackInventory(val)); View(c).InvokeRPC(sender, "IR_EatResp", new object[1] { val2 }); } } private static bool GrantWithoutOwnership(Container c, long uid, long playerID, string response) { if (!Plugin.SharedChests.Value) { return true; } ZNetView val = View(c); if (!Object.op_Implicit((Object)(object)val) || !val.IsOwner()) { return true; } if ((!c.IsInUse() && (!Object.op_Implicit((Object)(object)c.m_wagon) || !c.m_wagon.InUse())) || uid == ZNet.GetUID()) { return true; } if (!Traverse.Create((object)c).Method("CheckAccess", new object[1] { playerID }).GetValue<bool>()) { return true; } val.InvokeRPC(uid, response, new object[1] { true }); return false; } public static bool OwnerOrGuest(Container c) { if (!c.IsOwner()) { if (Plugin.SharedChests.Value) { return (Object)(object)Current == (Object)(object)c; } return false; } return true; } } public static class Stash { public static readonly HashSet<Container> Pending = new HashSet<Container>(); public static int Moved; private static float s_lastRun; public static void Run(Player player) { //IL_0023: Unknown result type (might be due to invalid IL or missing references) if (Time.time - s_lastRun < 0.5f) { return; } s_lastRun = Time.time; List<Container> list = FindNearby(((Component)player).transform.position, Plugin.StashRange.Value); if (list.Count == 0) { ((Character)player).Message((MessageType)2, "No chests nearby", 0, (Sprite)null, false); return; } Moved = 0; Pending.Clear(); foreach (Container item in list) { Pending.Add(item); item.StackAll(); } ((MonoBehaviour)player).StartCoroutine(Report(player)); } private static IEnumerator Report(Player player) { yield return (object)new WaitForSeconds(1.5f); Pending.Clear(); ((Character)player).Message((MessageType)2, (Moved > 0) ? $"Stashed {Moved} items" : "Nothing to stash", 0, (Sprite)null, false); } public static List<Container> FindNearby(Vector3 pos, float range) { //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_00c4: Unknown result type (might be due to invalid IL or missing references) List<Container> list = new List<Container>(); HashSet<Container> hashSet = new HashSet<Container>(); Collider[] array = Physics.OverlapSphere(pos, range, LayerMask.GetMask(new string[2] { "piece", "item" })); for (int i = 0; i < array.Length; i++) { Container componentInParent = ((Component)array[i]).GetComponentInParent<Container>(); if (!Object.op_Implicit((Object)(object)componentInParent) || !hashSet.Add(componentInParent)) { continue; } ZNetView component = ((Component)componentInParent).GetComponent<ZNetView>(); if (component == null || !component.IsValid() || Object.op_Implicit((Object)(object)componentInParent.m_wagon) || Object.op_Implicit((Object)(object)((Component)componentInParent).GetComponentInParent<Ship>())) { continue; } if (Plugin.StashPlayerBuiltOnly.Value) { Piece component2 = ((Component)componentInParent).GetComponent<Piece>(); if (!Object.op_Implicit((Object)(object)component2) || !component2.IsPlacedByPlayer()) { continue; } } if (!componentInParent.m_checkGuardStone || PrivateArea.CheckAccess(((Component)componentInParent).transform.position, 0f, false, false)) { list.Add(componentInParent); } } return list; } public static bool CanLeave(ItemData item, bool respectHotbar) { if (item.m_equipped || Favourites.Is(item) || SharedChest.IsLocked(item)) { return false; } if (respectHotbar && Plugin.StashKeepHotbar.Value && item.m_gridPos.y == 0) { return false; } return true; } public static int StackInto(Inventory chest, Inventory from) { int num = 0; foreach (ItemData item in new List<ItemData>(from.GetAllItems())) { if (CanLeave(item, respectHotbar: true) && chest.ContainsItemByName(item.m_shared.m_name)) { int stack = item.m_stack; if (chest.AddItem(item)) { from.RemoveItem(item); num += stack; } } } return num; } } [HarmonyPatch(typeof(Container), "RPC_StackResponse")] internal static class Container_RPC_StackResponse_Patch { private static bool Prefix(Container __instance, bool granted) { //IL_0087: Unknown result type (might be due to invalid IL or missing references) //IL_008c: Unknown result type (might be due to invalid IL or missing references) //IL_009a: Unknown result type (might be due to invalid IL or missing references) //IL_00a0: Unknown result type (might be due to invalid IL or missing references) if (!Stash.Pending.Remove(__instance)) { return true; } if (!granted || !Object.op_Implicit((Object)(object)Player.m_localPlayer)) { return false; } ZNetView component = ((Component)__instance).GetComponent<ZNetView>(); if (Object.op_Implicit((Object)(object)component) && component.IsValid() && !component.IsOwner()) { SharedChest.PutMatching(__instance, ((Humanoid)Player.m_localPlayer).GetInventory()); return false; } int num = Stash.StackInto(__instance.GetInventory(), ((Humanoid)Player.m_localPlayer).GetInventory()); if (num > 0) { Stash.Moved += num; InventoryGui.instance.m_moveItemEffects.Create(((Component)__instance).transform.position, Quaternion.identity, (Transform)null, 1f, -1, default(ZDOID)); } return false; } } [HarmonyPatch(typeof(Inventory), "StackAll")] internal static class Inventory_StackAll_Favourites { private static bool Prefix(Inventory __instance, Inventory fromInventory, bool message, ref int __result) { if (!Object.op_Implicit((Object)(object)Player.m_localPlayer) || fromInventory != ((Humanoid)Player.m_localPlayer).GetInventory()) { return true; } if (SharedChest.IsGuest(__instance, out var _)) { return true; } int num = 0; foreach (ItemData item in new List<ItemData>(fromInventory.GetAllItems())) { if (Stash.CanLeave(item, respectHotbar: false) && __instance.ContainsItemByName(item.m_shared.m_name)) { int stack = item.m_stack; if (__instance.AddItem(item)) { fromInventory.RemoveItem(item); num += stack; } } } if (message) { ((Character)Player.m_localPlayer).Message((MessageType)2, (num > 0) ? ("$msg_stackall " + num) : "$msg_stackall_none", 0, (Sprite)null, false); } Game.instance.IncrementPlayerStat((PlayerStatType)82, 1f, false); __result = num; return false; } } [HarmonyPatch(typeof(InventoryGui), "Awake")] internal static class StashButton { [Serializable] [CompilerGenerated] private sealed class <>c { public static readonly <>c <>9 = new <>c(); public static UnityAction <>9__0_0; internal void <Postfix>b__0_0() { if (Object.op_Implicit((Object)(object)Player.m_localPlayer)) { Stash.Run(Player.m_localPlayer); } } } private static void Postfix(InventoryGui __instance) { //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_0041: Expected O, but got Unknown //IL_005b: Unknown result type (might be due to invalid IL or missing references) //IL_0060: Unknown result type (might be due to invalid IL or missing references) //IL_0066: Expected O, but got Unknown //IL_00d5: Unknown result type (might be due to invalid IL or missing references) //IL_00db: Unknown result type (might be due to invalid IL or missing references) //IL_00ec: Unknown result type (might be due to invalid IL or missing references) //IL_010b: Unknown result type (might be due to invalid IL or missing references) //IL_0129: Unknown result type (might be due to invalid IL or missing references) if (!Plugin.StashButton.Value || !Object.op_Implicit((Object)(object)__instance.m_takeAllButton)) { return; } Button obj = Object.Instantiate<Button>(__instance.m_takeAllButton, (Transform)(object)__instance.m_player); ((Object)obj).name = "IR_StashButton"; obj.onClick = new ButtonClickedEvent(); ButtonClickedEvent onClick = obj.onClick; object obj2 = <>c.<>9__0_0; if (obj2 == null) { UnityAction val = delegate { if (Object.op_Implicit((Object)(object)Player.m_localPlayer)) { Stash.Run(Player.m_localPlayer); } }; <>c.<>9__0_0 = val; obj2 = (object)val; } ((UnityEvent)onClick).AddListener((UnityAction)obj2); TMP_Text componentInChildren = ((Component)obj).GetComponentInChildren<TMP_Text>(); if (Object.op_Implicit((Object)(object)componentInChildren)) { componentInChildren.text = "»"; componentInChildren.alignment = (TextAlignmentOptions)514; componentInChildren.enableAutoSizing = false; componentInChildren.fontSize = 22f; } Text componentInChildren2 = ((Component)obj).GetComponentInChildren<Text>(); if (Object.op_Implicit((Object)(object)componentInChildren2)) { componentInChildren2.text = "»"; } RectTransform component = ((Component)obj).GetComponent<RectTransform>(); Vector2 val2 = default(Vector2); ((Vector2)(ref val2))..ctor(1f, 0f); component.anchorMax = val2; component.anchorMin = val2; component.pivot = new Vector2(0.5f, 0.5f); component.sizeDelta = new Vector2(Plugin.StashButtonSize.Value, Plugin.StashButtonSize.Value); component.anchoredPosition = new Vector2(Plugin.StashButtonX.Value, Plugin.StashButtonY.Value); UITooltip component2 = ((Component)obj).GetComponent<UITooltip>(); if (Object.op_Implicit((Object)(object)component2)) { component2.m_text = "Stash to nearby chests"; component2.m_topic = ""; } } } }