Decompiled source of MultiUserChest v0.6.0
MultiUserChest.dll
Decompiled 2 weeks ago
The result has been truncated due to the large size, download it to view full contents!
using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Reflection; using System.Reflection.Emit; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using BepInEx; using BepInEx.Bootstrap; using BepInEx.Logging; using HarmonyLib; using Jotunn.Managers; using Jotunn.Utils; using MultiUserChest.Patches; using UnityEngine; using UnityEngine.UI; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: AssemblyTitle("MultiUserChest")] [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("")] [assembly: AssemblyProduct("MultiUserChest")] [assembly: AssemblyCopyright("Copyright © 2021")] [assembly: AssemblyTrademark("")] [assembly: InternalsVisibleTo("UnitTests")] [assembly: InternalsVisibleTo("Tests")] [assembly: ComVisible(false)] [assembly: Guid("FE8B42E3-7082-4DFF-A5CC-6B62B0315ACA")] [assembly: AssemblyFileVersion("0.6.0")] [assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("0.6.0.0")] [module: UnverifiableCode] namespace MultiUserChest { public static class CodeMatcherExtensions { public static CodeMatcher GetPosition(this CodeMatcher codeMatcher, out int position) { position = codeMatcher.Pos; return codeMatcher; } public static CodeMatcher AddLabel(this CodeMatcher codeMatcher, out Label label) { label = default(Label); codeMatcher.AddLabels((IEnumerable<Label>)new Label[1] { label }); return codeMatcher; } public static CodeMatcher GetOperand(this CodeMatcher codeMatcher, out object operand) { operand = codeMatcher.Operand; return codeMatcher; } internal static CodeMatcher Print(this CodeMatcher codeMatcher, int before, int after) { for (int i = -before; i <= after; i++) { int num = i; int num2 = codeMatcher.Pos + num; if (num2 > 0) { if (num2 >= codeMatcher.Length) { break; } try { CodeInstruction val = codeMatcher.InstructionAt(num); Log.LogCodeInstruction($"[{num}] " + ((object)val).ToString()); } catch (Exception ex) { Log.LogCodeInstruction(ex.Message); } } } return codeMatcher; } public static bool IsVirtCall(this CodeInstruction i, string declaringType, string name) { if (i.opcode == OpCodes.Callvirt && i.operand is MethodInfo methodInfo && methodInfo.DeclaringType?.Name == declaringType) { return methodInfo.Name == name; } return false; } } public static class Compatibility { private static bool IsExtendedInventory(this Inventory inventory, out List<Inventory> inventories) { if (inventory.IsType("ExtendedInventory") && inventory.HasField("_inventories")) { inventories = inventory.GetField<List<Inventory>>("_inventories"); return true; } inventories = null; return false; } public static List<Inventory> GetInventories(this Inventory inventory) { if (inventory.IsExtendedInventory(out var inventories)) { return inventories; } return new List<Inventory> { inventory }; } } public class ContainerExtend : MonoBehaviour { private static readonly ConditionalWeakTable<Inventory, ContainerInventoryOwner> Containers = new ConditionalWeakTable<Inventory, ContainerInventoryOwner>(); private Inventory inventory; private void Awake() { Container container = default(Container); if (!((Component)this).TryGetComponent<Container>(ref container)) { return; } inventory = container.GetInventory(); if (inventory != null) { Containers.TryAdd(inventory, (Inventory i) => new ContainerInventoryOwner(container)); } } private void OnDestroy() { if (inventory != null) { Containers.Remove(inventory); } } public static bool GetContainer(Inventory inventory, out ContainerInventoryOwner container) { return Containers.TryGetValue(inventory, out container); } } public static class ContainerHandler { public static RequestChestAdd AddItemToChest(this Container container, ItemData item, Inventory sourceInventory, Vector2i to, ZDOID sender, int dragAmount = -1) { //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_004e: Unknown result type (might be due to invalid IL or missing references) //IL_008a: Unknown result type (might be due to invalid IL or missing references) //IL_0099: Unknown result type (might be due to invalid IL or missing references) //IL_00b1: Unknown result type (might be due to invalid IL or missing references) if (!Object.op_Implicit((Object)(object)container) || !Object.op_Implicit((Object)(object)container.m_nview) || !container.m_nview.HasOwner()) { return new RequestChestAdd(Vector2i.zero, 0, null, null, null); } dragAmount = PossibleDragAmount(container.GetInventory(), item, to, dragAmount); ItemData itemAt = container.GetInventory().GetItemAt(to.x, to.y); bool flag = itemAt != null && dragAmount != item.m_stack && !InventoryHelper.CanStack(itemAt, item); if (dragAmount <= 0 || flag || !sourceInventory.ContainsItem(item)) { return new RequestChestAdd(Vector2i.zero, 0, null, null, null); } RequestChestAdd requestChestAdd = new RequestChestAdd(to, dragAmount, item, sourceInventory, container.GetInventory()); InventoryBlock.Get(sourceInventory).BlockSlot(item.m_gridPos); InventoryPreview.AddPackage(requestChestAdd); sourceInventory.RemoveItem(item, dragAmount); if (container.m_nview.IsOwner()) { RequestChestAddResponse response = container.GetInventory().RequestItemAdd(requestChestAdd); InventoryHandler.RPC_RequestItemAddResponse(sourceInventory, response); return null; } GamePatches.InvokeRPC(container.m_nview, "MUC_RequestItemAdd", requestChestAdd); return requestChestAdd; } internal static int PossibleDragAmount(Inventory inventoryTo, ItemData dragItem, Vector2i to, int dragAmount) { //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_002f: 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) dragAmount = ((dragAmount >= 0) ? Mathf.Min(dragAmount, dragItem.m_stack) : dragItem.m_stack); if (to.x >= 0 && to.y >= 0) { ItemData itemAt = inventoryTo.GetItemAt(to.x, to.y); if (itemAt != null && dragAmount < dragItem.m_stack) { if (InventoryHelper.CanStack(itemAt, dragItem)) { return Mathf.Min(dragAmount, itemAt.m_shared.m_maxStackSize - itemAt.m_stack); } return 0; } } else if (!inventoryTo.HaveEmptySlot()) { int num = inventoryTo.FindFreeStackSpace(dragItem.m_shared.m_name, (float)dragItem.m_worldLevel); return Mathf.Min(dragAmount, num); } return dragAmount; } public static RequestChestRemove RemoveItemFromChest(this Container container, ItemData item, Inventory destinationInventory, Vector2i to, ZDOID sender, int dragAmount = -1, ItemData switchItem = null) { //IL_0022: 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_003d: 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_005f: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Unknown result type (might be due to invalid IL or missing references) //IL_0074: 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_00cc: Unknown result type (might be due to invalid IL or missing references) //IL_00a3: 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) if (!Object.op_Implicit((Object)(object)container) || !Object.op_Implicit((Object)(object)container.m_nview) || !container.m_nview.HasOwner()) { return new RequestChestRemove(Vector2i.zero, Vector2i.zero, 0, null, container.GetInventory(), destinationInventory); } dragAmount = PossibleDragAmount(destinationInventory, item, to, dragAmount); if (dragAmount <= 0 || InventoryBlock.Get(destinationInventory).IsSlotBlocked(to)) { return new RequestChestRemove(Vector2i.zero, Vector2i.zero, 0, null, container.GetInventory(), destinationInventory); } RequestChestRemove requestChestRemove = new RequestChestRemove(item.m_gridPos, to, dragAmount, switchItem, container.GetInventory(), destinationInventory); if (switchItem != null && !InventoryHelper.CanStack(item, switchItem)) { if (dragAmount != item.m_stack) { return new RequestChestRemove(Vector2i.zero, Vector2i.zero, 0, null, container.GetInventory(), destinationInventory); } destinationInventory.RemoveItem(switchItem); } InventoryBlock.Get(destinationInventory).BlockSlot(requestChestRemove.toPos); InventoryPreview.AddPackage(requestChestRemove); if (container.m_nview.IsOwner()) { RequestChestRemoveResponse response = container.GetInventory().RequestItemRemove(requestChestRemove); InventoryHandler.RPC_RequestItemRemoveResponse(destinationInventory, response); return null; } GamePatches.InvokeRPC(container.m_nview, "MUC_RequestItemRemove", requestChestRemove); return requestChestRemove; } public static void MoveItemInChest(this Container container, ItemData item, Vector2i toPos, int dragAmount) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) RequestMove package = new RequestMove(item, toPos, dragAmount, container.GetInventory()); InventoryPreview.AddPackage(package); GamePatches.InvokeRPC(container.m_nview, "MUC_RequestItemMove", package); } } public static class ContainerRPCHandler { public static void RPC_RequestItemAdd(long sender, ZDOID containerId, ZPackage package) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) HandleRPC(containerId, sender, "MUC_RequestItemAddResponse", RequestItemAdd, new RequestChestAdd(package)); } public static void RPC_RequestItemRemove(long sender, ZDOID containerId, ZPackage package) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) HandleRPC(containerId, sender, "MUC_RequestItemRemoveResponse", RequestItemRemove, new RequestChestRemove(package)); } public static void RPC_RequestItemConsume(long sender, ZDOID containerId, ZPackage package) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) HandleRPC(containerId, sender, "MUC_RequestItemConsumeResponse", RequestItemConsume, new RequestConsume(package)); } public static void RPC_RequestItemMove(long sender, ZDOID containerId, ZPackage package) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) HandleRPC(containerId, sender, "MUC_RequestItemMoveResponse", RequestItemMove, new RequestMove(package)); } public static void RPC_RequestDrop(long sender, ZDOID containerId, ZPackage package) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) HandleRPC(containerId, sender, "MUC_RequestItemDropResponse", RequestDrop, new RequestDrop(package)); } private static void HandleRPC<TResponse, TInput>(ZDOID containerId, long target, string rpcInvoke, Func<Inventory, TInput, TResponse> message, TInput input) where TResponse : IResponse, new() where TInput : IPackage { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_00aa: Unknown result type (might be due to invalid IL or missing references) ZDO zDO = ZDOMan.instance.GetZDO(containerId); ZNetView val = ((zDO != null) ? ZNetScene.instance.FindInstance(zDO) : null); TResponse val2; if (!Object.op_Implicit((Object)(object)val) || !val.IsOwner()) { val2 = FallbackResponse<TResponse>(input as IRequest); } else { Container componentInChildren = ((Component)val).GetComponentInChildren<Container>(); if (Object.op_Implicit((Object)(object)componentInChildren)) { val2 = message(componentInChildren.GetInventory(), input); } else { Log.LogWarning(input.GetType().Name + ": not handling RPC, Container component not found on " + ((Object)val).name); val2 = FallbackResponse<TResponse>(input as IRequest); } } ZRoutedRpc.instance.InvokeRoutedRPC(target, rpcInvoke, new object[2] { containerId, val2.WriteToPackage() }); } private static TResponse FallbackResponse<TResponse>(IRequest request) where TResponse : IResponse, new() { //IL_0058: 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_005d: Unknown result type (might be due to invalid IL or missing references) TResponse val = new TResponse { SourceID = (request?.RequestID ?? 0) }; if (request is RequestChestAdd requestChestAdd && (object)val is RequestChestAddResponse requestChestAddResponse) { requestChestAddResponse.switchItem = requestChestAdd.dragItem; requestChestAddResponse.inventoryPos = requestChestAdd.dragItem?.m_gridPos ?? Vector2i.zero; } else if (request is RequestChestRemove requestChestRemove && (object)val is RequestChestRemoveResponse requestChestRemoveResponse) { requestChestRemoveResponse.responseItem = requestChestRemove.switchItem; } return val; } public static RequestChestAddResponse RequestItemAdd(this Inventory inventory, RequestChestAdd request) { //IL_000f: Unknown result type (might be due to invalid IL or missing references) if (request.dragItem == null) { return new RequestChestAddResponse(request.RequestID, success: false, Vector2i.zero, 0, request.dragItem); } if (request.toPos.x < 0 || request.toPos.y < 0) { return AddToAnySlot(inventory, request); } return AddToSlot(inventory, request); } private static RequestChestAddResponse AddToSlot(Inventory inventory, RequestChestAdd request) { //IL_0037: 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_0093: 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_0081: Unknown result type (might be due to invalid IL or missing references) if (!CanStack(inventory, request, out var stackSpace, out var removedItem)) { return new RequestChestAddResponse(request.RequestID, success: false, request.dragItem.m_gridPos, 0, request.dragItem); } bool flag = inventory.AddItemToInventory(request.dragItem, stackSpace, request.toPos); if (!flag) { stackSpace = 0; } if (!flag || stackSpace != request.dragItem.m_stack) { removedItem = request.dragItem; removedItem.m_stack = request.dragItem.m_stack - stackSpace; } if (removedItem != null) { removedItem.m_gridPos = request.dragItem.m_gridPos; } return new RequestChestAddResponse(request.RequestID, flag, request.dragItem.m_gridPos, stackSpace, removedItem); } private static bool CanStack(Inventory inventory, RequestChestAdd request, out int stackSpace, out ItemData removedItem) { ItemData itemAt = inventory.GetItemAt(request.toPos.x, request.toPos.y); removedItem = null; if (itemAt == null) { stackSpace = request.dragItem.m_stack; return true; } if (InventoryHelper.CanStack(itemAt, request.dragItem)) { stackSpace = Mathf.Min(itemAt.m_shared.m_maxStackSize - itemAt.m_stack, request.dragItem.m_stack); return true; } if (request.allowSwitch) { inventory.RemoveItem(itemAt, itemAt.m_stack); removedItem = itemAt; stackSpace = request.dragItem.m_stack; return true; } stackSpace = 0; return false; } private static RequestChestAddResponse AddToAnySlot(Inventory inventory, RequestChestAdd request) { //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_000e: Expected O, but got Unknown //IL_00bf: 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 val = new Inventory("tmp", (Sprite)null, 1, 1); val.AddItem(request.dragItem.Clone(), request.dragItem.m_stack, 0, 0); inventory.MoveItemToThis(val, val.GetItemAt(0, 0)); ItemData itemAt = val.GetItemAt(0, 0); if (itemAt == null) { return new RequestChestAddResponse(request.RequestID, success: true, request.dragItem.m_gridPos, request.dragItem.m_stack, null); } ItemData val2 = request.dragItem.Clone(); int num = request.dragItem.m_stack - itemAt.m_stack; val2.m_stack -= num; bool success = itemAt.m_stack != request.dragItem.m_stack; return new RequestChestAddResponse(request.RequestID, success, request.dragItem.m_gridPos, num, val2); } public static RequestChestRemoveResponse RequestItemRemove(this Inventory inventory, RequestChestRemove request) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_00d2: Unknown result type (might be due to invalid IL or missing references) Vector2i fromPos = request.fromPos; int dragAmount = request.dragAmount; ItemData switchItem = request.switchItem; ItemData itemAt = inventory.GetItemAt(request.fromPos.x, request.fromPos.y); if (itemAt == null) { Log.LogDebug("from is null"); return new RequestChestRemoveResponse(request.RequestID, success: false, 0, hasSwitched: false, null); } int num = 0; bool flag = false; bool flag2 = false; if (switchItem == null) { num = Mathf.Min(itemAt.m_stack, dragAmount); flag = inventory.RemoveItem(itemAt, num); } else if (InventoryHelper.CanStack(itemAt, switchItem)) { num = Mathf.Min(switchItem.m_shared.m_maxStackSize - switchItem.m_stack, dragAmount); flag = inventory.RemoveItem(itemAt, num); } else { if (dragAmount < itemAt.m_stack) { return new RequestChestRemoveResponse(request.RequestID, success: false, 0, hasSwitched: false, request.switchItem); } flag = inventory.RemoveItem(itemAt, dragAmount); num = Mathf.Min(itemAt.m_stack, dragAmount); flag2 = inventory.AddItemToInventory(switchItem, switchItem.m_stack, fromPos); if (!flag2) { Log.LogWarning("Could not switch item in Remove Request"); InventoryHandler.DropItem(switchItem, switchItem.m_stack); } } ItemData val = itemAt.Clone(); val.m_stack = num; return new RequestChestRemoveResponse(request.RequestID, flag, num, flag2, val); } public static RequestConsumeResponse RequestItemConsume(this Inventory inventory, RequestConsume request) { ItemData itemAt = inventory.GetItemAt(request.itemPosX, request.itemPosY); if (itemAt == null || itemAt.m_stack <= 0) { return new RequestConsumeResponse(null, success: false, 0); } inventory.RemoveOneItem(itemAt); ItemData val = itemAt.Clone(); val.m_stack = 1; return new RequestConsumeResponse(val, success: true, 1); } public static RequestMoveResponse RequestItemMove(this Inventory inventory, RequestMove request) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_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_0016: 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_005d: Unknown result type (might be due to invalid IL or missing references) Vector2i fromPos = request.fromPos; Vector2i toPos = request.toPos; int dragAmount = request.dragAmount; ItemData itemAt = inventory.GetItemAt(fromPos.x, fromPos.y); if (itemAt == null) { return new RequestMoveResponse(request.RequestID, success: false, 0); } if (StringExtensionMethods.GetStableHashCode(itemAt.PrefabName()) != request.itemHash) { return new RequestMoveResponse(request.RequestID, success: false, 0); } int movedAmount; bool success = InventoryHelper.MoveItem(inventory, itemAt, dragAmount, toPos, out movedAmount); return new RequestMoveResponse(request.RequestID, success, movedAmount); } public static RequestDropResponse RequestDrop(this Inventory inventory, RequestDrop request) { //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_006c: 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) ItemData itemAt = inventory.GetItemAt(request.targetContainerSlot.x, request.targetContainerSlot.y); if (itemAt == null) { return new RequestDropResponse(null, request.sender, success: false, 0); } int num = Mathf.Min(itemAt.m_stack, request.amount); inventory.RemoveItem(itemAt, num); if (num == 0) { return new RequestDropResponse(null, request.sender, success: false, 0); } ItemData val = itemAt.Clone(); val.m_stack = num; return new RequestDropResponse(val, request.sender, success: true, num); } } public interface IPackage { ZPackage WriteToPackage(); } public interface IRequest : IPackage { int RequestID { get; set; } Inventory SourceInventory { get; } Inventory TargetInventory { get; } } public interface IResponse : IPackage { int SourceID { get; set; } bool Success { get; set; } int Amount { get; set; } } public class RequestChestAdd : IRequest, IPackage { public readonly Vector2i toPos; public readonly ItemData dragItem; public readonly bool allowSwitch; public int RequestID { get; set; } public Inventory SourceInventory { get; } public Inventory TargetInventory { get; } public RequestChestAdd(Vector2i toPos, int dragAmount, ItemData dragItem, Inventory sourceInventory, Inventory targetInventory) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) this.toPos = toPos; if (dragItem != null) { this.dragItem = dragItem.Clone(); this.dragItem.m_stack = Mathf.Min(dragAmount, this.dragItem.m_stack); allowSwitch = dragAmount == dragItem.m_stack; } SourceInventory = sourceInventory; TargetInventory = targetInventory; } public RequestChestAdd(ZPackage package) { //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Unknown result type (might be due to invalid IL or missing references) RequestID = package.ReadInt(); toPos = package.ReadVector2i(); dragItem = InventoryHelper.LoadItemFromPackage(package); allowSwitch = package.ReadBool(); } public ZPackage WriteToPackage() { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Expected O, but got Unknown //IL_0014: Unknown result type (might be due to invalid IL or missing references) ZPackage val = new ZPackage(); val.Write(RequestID); val.Write(toPos); InventoryHelper.WriteItemToPackage(dragItem, val); val.Write(allowSwitch); return val; } } public class RequestChestAddResponse : IPackage, IResponse { public Vector2i inventoryPos; public ItemData switchItem; public int SourceID { get; set; } public bool Success { get; set; } public int Amount { get; set; } public RequestChestAddResponse(int sourceID, bool success, Vector2i inventoryPos, int amount, ItemData switchItem) { //IL_001d: 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) SourceID = sourceID; Success = success; Amount = amount; this.inventoryPos = inventoryPos; this.switchItem = switchItem.ClampStackSize(); } public RequestChestAddResponse(ZPackage package) { //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Unknown result type (might be due to invalid IL or missing references) SourceID = package.ReadInt(); inventoryPos = package.ReadVector2i(); Success = package.ReadBool(); Amount = package.ReadInt(); switchItem = InventoryHelper.LoadItemFromPackage(package); } public RequestChestAddResponse() { //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) SourceID = 0; Success = false; inventoryPos = new Vector2i(-1, -1); Amount = 0; switchItem = null; } public ZPackage WriteToPackage() { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Expected O, but got Unknown //IL_0014: Unknown result type (might be due to invalid IL or missing references) ZPackage val = new ZPackage(); val.Write(SourceID); val.Write(inventoryPos); val.Write(Success); val.Write(Amount); InventoryHelper.WriteItemToPackage(switchItem, val); return val; } } public class RequestConsume : IPackage { public readonly int itemPosX; public readonly int itemPosY; public RequestConsume(ItemData item) { itemPosX = item.m_gridPos.x; itemPosY = item.m_gridPos.y; } public RequestConsume(ZPackage package) { itemPosX = package.ReadInt(); itemPosY = package.ReadInt(); } public ZPackage WriteToPackage() { //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(itemPosX); val.Write(itemPosY); return val; } } public class RequestConsumeResponse : IPackage, IResponse { public readonly ItemData item; public int SourceID { get; set; } public bool Success { get; set; } public int Amount { get; set; } public RequestConsumeResponse(ZPackage package) { item = InventoryHelper.LoadItemFromPackage(package); Success = package.ReadBool(); Amount = package.ReadInt(); } public RequestConsumeResponse(ItemData item, bool success, int amount) { this.item = item.ClampStackSize(); Success = success; Amount = amount; } public RequestConsumeResponse() { item = null; } public ZPackage WriteToPackage() { //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(); InventoryHelper.WriteItemToPackage(item, val); val.Write(Success); val.Write(Amount); return val; } } public class RequestDrop : IPackage { public readonly Vector2i targetContainerSlot; public readonly int amount; public readonly ZDOID sender; public RequestDrop(Vector2i targetContainerSlot, int amount, ZDOID sender) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Unknown result type (might be due to invalid IL or missing references) this.targetContainerSlot = targetContainerSlot; this.amount = amount; this.sender = sender; } public RequestDrop(ZPackage package) { //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_0020: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Unknown result type (might be due to invalid IL or missing references) targetContainerSlot = package.ReadVector2i(); amount = package.ReadInt(); sender = package.ReadZDOID(); } public ZPackage WriteToPackage() { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Expected O, but got Unknown //IL_0008: 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) ZPackage val = new ZPackage(); val.Write(targetContainerSlot); val.Write(amount); val.Write(sender); return val; } } public class RequestDropResponse : IPackage, IResponse { public readonly ItemData responseItem; public readonly ZDOID sender; public int SourceID { get; set; } public bool Success { get; set; } public int Amount { get; set; } public RequestDropResponse(ItemData responseItem, ZDOID sender, bool success, int amount) { //IL_0013: 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) this.responseItem = responseItem.ClampStackSize(); this.sender = sender; Success = success; Amount = amount; } public RequestDropResponse(ZPackage package) { //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Unknown result type (might be due to invalid IL or missing references) responseItem = InventoryHelper.LoadItemFromPackage(package); sender = package.ReadZDOID(); Success = package.ReadBool(); Amount = package.ReadInt(); } public RequestDropResponse() { responseItem = null; } public ZPackage WriteToPackage() { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Expected O, but got Unknown //IL_0014: Unknown result type (might be due to invalid IL or missing references) ZPackage val = new ZPackage(); InventoryHelper.WriteItemToPackage(responseItem, val); val.Write(sender); val.Write(Success); val.Write(Amount); return val; } } public class RequestMove : IRequest, IPackage { public readonly Vector2i fromPos; public readonly Vector2i toPos; public readonly int itemHash; public readonly int dragAmount; public readonly ItemData item; public int RequestID { get; set; } public Inventory SourceInventory { get; } public Inventory TargetInventory { get; } public RequestMove(ItemData itemToMove, Vector2i toPos, int dragAmount, Inventory inventory) { //IL_004e: 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_0059: 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_0016: 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_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) if (itemToMove == null) { Log.LogWarning("Item is null"); fromPos = new Vector2i(-1, -1); this.toPos = new Vector2i(-1, -1); itemHash = 0; this.dragAmount = 0; } else { SourceInventory = inventory; TargetInventory = inventory; fromPos = itemToMove.m_gridPos; this.toPos = toPos; itemHash = StringExtensionMethods.GetStableHashCode(itemToMove.PrefabName()); item = itemToMove.Clone(); this.dragAmount = dragAmount; } } public RequestMove(ZPackage package) { //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Unknown result type (might be due to invalid IL or missing references) RequestID = package.ReadInt(); fromPos = package.ReadVector2i(); toPos = package.ReadVector2i(); itemHash = package.ReadInt(); dragAmount = package.ReadInt(); } public ZPackage WriteToPackage() { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Expected O, but got Unknown //IL_0014: 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) ZPackage val = new ZPackage(); val.Write(RequestID); val.Write(fromPos); val.Write(toPos); val.Write(itemHash); val.Write(dragAmount); return val; } } public class RequestChestRemove : IRequest, IPackage { public readonly Vector2i fromPos; public readonly Vector2i toPos; public readonly int dragAmount; public readonly ItemData switchItem; public readonly ItemData item; public int RequestID { get; set; } public Inventory SourceInventory { get; } public Inventory TargetInventory { get; } public RequestChestRemove(Vector2i fromPos, Vector2i toPos, int dragAmount, ItemData switchItem, Inventory sourceInventory, Inventory targetInventory) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0049: Unknown result type (might be due to invalid IL or missing references) //IL_004f: Unknown result type (might be due to invalid IL or missing references) this.fromPos = fromPos; this.toPos = toPos; this.dragAmount = dragAmount; this.switchItem = ((switchItem != null) ? switchItem.Clone() : null); SourceInventory = sourceInventory; TargetInventory = targetInventory; object obj; if (sourceInventory == null) { obj = null; } else { ItemData itemAt = sourceInventory.GetItemAt(fromPos.x, fromPos.y); obj = ((itemAt != null) ? itemAt.Clone() : null); } item = (ItemData)obj; } public RequestChestRemove(ZPackage package) { //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Unknown result type (might be due to invalid IL or missing references) RequestID = package.ReadInt(); fromPos = package.ReadVector2i(); toPos = package.ReadVector2i(); dragAmount = package.ReadInt(); switchItem = InventoryHelper.LoadItemFromPackage(package); } public ZPackage WriteToPackage() { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Expected O, but got Unknown //IL_0014: 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) ZPackage val = new ZPackage(); val.Write(RequestID); val.Write(fromPos); val.Write(toPos); val.Write(dragAmount); InventoryHelper.WriteItemToPackage(switchItem, val); return val; } } public class RequestChestRemoveResponse : IPackage, IResponse { public ItemData responseItem; public bool hasSwitched; public int SourceID { get; set; } public bool Success { get; set; } public int Amount { get; set; } public RequestChestRemoveResponse(int sourceID, bool success, int amount, bool hasSwitched, ItemData responseItem) { SourceID = sourceID; Success = success; Amount = amount; this.hasSwitched = hasSwitched; this.responseItem = responseItem.ClampStackSize(); } public RequestChestRemoveResponse(ZPackage package) { SourceID = package.ReadInt(); Success = package.ReadBool(); Amount = package.ReadInt(); hasSwitched = package.ReadBool(); responseItem = InventoryHelper.LoadItemFromPackage(package); } public RequestChestRemoveResponse() { Success = false; Amount = 0; hasSwitched = false; responseItem = null; } public ZPackage WriteToPackage() { //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(SourceID); val.Write(Success); val.Write(Amount); val.Write(hasSwitched); InventoryHelper.WriteItemToPackage(responseItem, val); return val; } } public class RequestMoveResponse : IPackage, IResponse { public int SourceID { get; set; } public bool Success { get; set; } public int Amount { get; set; } public RequestMoveResponse(int sourceID, bool success, int amount) { SourceID = sourceID; Success = success; Amount = amount; } public RequestMoveResponse() { SourceID = 0; Success = false; Amount = 0; } public RequestMoveResponse(ZPackage package) { SourceID = package.ReadInt(); Success = package.ReadBool(); Amount = package.ReadInt(); } public ZPackage WriteToPackage() { //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(SourceID); val.Write(Success); val.Write(Amount); return val; } } public class SlotPreview { private Inventory originalInventory; private Inventory inventory; private bool hasChanges; public SlotPreview(Inventory inventory) { originalInventory = inventory; this.inventory = InventoryHelper.CopyInventory(inventory); } public void Add(Vector2i pos, ItemData item, int amount) { //IL_0015: 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_002f: 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) if (item != null && amount != 0) { ItemData val = item.Clone(); val.m_stack = amount; if (pos.x >= 0 && pos.y >= 0) { inventory.AddItem(val, amount, pos.x, pos.y); } else { inventory.AddItem(val); } hasChanges = true; } } public void Add(Vector2i pos, ItemData item) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) Add(pos, item, item?.m_stack ?? 0); } public void Remove(Vector2i pos, ItemData item) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) Remove(pos, item, item?.m_stack ?? 0); } public void Remove(Vector2i pos, ItemData item, int amount) { //IL_000d: 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_002f: 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) if (item != null && amount != 0) { ItemData itemAt = inventory.GetItemAt(pos.x, pos.y); if (itemAt != null) { inventory.RemoveItem(inventory.GetItemAt(pos.x, pos.y), amount); hasChanges = true; } } } public bool GetSlot(Vector2i pos, out ItemData item) { //IL_0006: 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_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Unknown result type (might be due to invalid IL or missing references) ItemData itemAt = originalInventory.GetItemAt(pos.x, pos.y); item = inventory.GetItemAt(pos.x, pos.y); if (itemAt == null && item == null) { return false; } if (itemAt == null || item == null) { return true; } if (!(itemAt.m_shared.m_name != item.m_shared.m_name)) { return itemAt.m_stack != item.m_stack; } return true; } public bool HasChanges() { return hasChanges; } } public static class ConditionalWeakTableExtension { public static void TryAdd<TKey, TValue>(this ConditionalWeakTable<TKey, TValue> table, TKey key, ConditionalWeakTable<TKey, TValue>.CreateValueCallback createCallback) where TKey : class where TValue : class { table.GetValue(key, createCallback); } } public static class InventoryHelper { public delegate void MoveAction(Inventory from, Inventory to); private static MethodBase memberwiseCloneMethod = AccessTools.Method(typeof(object), "MemberwiseClone", (Type[])null, (Type[])null); public static ItemData LoadItemFromPackage(ZPackage pkg) { //IL_0022: 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_009a: Unknown result type (might be due to invalid IL or missing references) //IL_00a3: Unknown result type (might be due to invalid IL or missing references) //IL_00ac: Unknown result type (might be due to invalid IL or missing references) //IL_00b3: Expected O, but got Unknown //IL_00b8: Unknown result type (might be due to invalid IL or missing references) //IL_00d1: Unknown result type (might be due to invalid IL or missing references) //IL_00d8: Unknown result type (might be due to invalid IL or missing references) if (!pkg.ReadBool()) { return null; } string text = pkg.ReadString(); int num = pkg.ReadInt(); float num2 = pkg.ReadSingle(); Vector2i val = pkg.ReadVector2i(); int num3 = pkg.ReadInt(); int num4 = pkg.ReadInt(); long num5 = pkg.ReadLong(); string text2 = pkg.ReadString(); int num6 = pkg.ReadInt(); bool flag = pkg.ReadBool(); Dictionary<string, string> dictionary = new Dictionary<string, string>(); int num7 = pkg.ReadInt(); for (int i = 0; i < num7; i++) { string key = pkg.ReadString(); string value = pkg.ReadString(); dictionary[key] = value; } Inventory val2 = new Inventory("tmp", (Sprite)null, val.x + 1, val.y + 1); val2.AddItem(text, num, num2, val, false, num3, num4, num5, text2, dictionary, num6, flag); ItemData itemAt = val2.GetItemAt(val.x, val.y); val2.RemoveItem(itemAt); return itemAt; } public static void WriteItemToPackage(ItemData itemData, ZPackage pkg) { //IL_0034: Unknown result type (might be due to invalid IL or missing references) pkg.Write(itemData != null); if (itemData == null) { return; } pkg.Write(itemData.PrefabName()); pkg.Write(itemData.m_stack); pkg.Write(itemData.m_durability); pkg.Write(itemData.m_gridPos); pkg.Write(itemData.m_quality); pkg.Write(itemData.m_variant); pkg.Write(itemData.m_crafterID); pkg.Write(itemData.m_crafterName); pkg.Write(itemData.m_worldLevel); pkg.Write(itemData.m_pickedUp); pkg.Write(itemData.m_customData.Count); foreach (KeyValuePair<string, string> customDatum in itemData.m_customData) { pkg.Write(customDatum.Key); pkg.Write(customDatum.Value); } } public static ItemData ClampStackSize(this ItemData item) { if (item == null) { return null; } ItemDrop prefab = Cache.GetPrefab<ItemDrop>(item.PrefabName()); item.m_shared.m_maxStackSize = prefab.m_itemData.m_shared.m_maxStackSize; return item; } public static string PrefabName(this ItemData item) { if ((Object)(object)item.m_dropPrefab != (Object)null) { return ((Object)item.m_dropPrefab).name; } Log.LogWarning("Item missing prefab " + item.m_shared.m_name); return item.m_shared.m_name; } public static bool MoveItem(Inventory inventory, ItemData item, int amount, Vector2i toPos, out int movedAmount) { //IL_000a: 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_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) //IL_0069: 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_00b7: Unknown result type (might be due to invalid IL or missing references) //IL_00bd: Unknown result type (might be due to invalid IL or missing references) movedAmount = 0; if (item == null) { return false; } ItemData itemAt = inventory.GetItemAt(toPos.x, toPos.y); if (itemAt == item) { return true; } if (itemAt == null) { movedAmount = amount; return inventory.MoveItemToThis(inventory, item, amount, toPos.x, toPos.y); } if (CanStack(itemAt, item)) { movedAmount = Mathf.Min(amount, itemAt.m_shared.m_maxStackSize - itemAt.m_stack); return inventory.MoveItemToThis(inventory, item, movedAmount, toPos.x, toPos.y); } if (item.m_stack != amount) { return false; } inventory.RemoveItem(item); inventory.MoveItemToThis(inventory, itemAt, itemAt.m_stack, item.m_gridPos.x, item.m_gridPos.y); inventory.MoveItemToThis(inventory, item, amount, toPos.x, toPos.y); movedAmount = amount; return true; } public static bool CanStack(ItemData itemA, ItemData itemB) { if (itemA.m_shared.m_name == itemB.m_shared.m_name && (itemA.m_shared.m_maxQuality <= 1 || itemB.m_quality == itemA.m_quality)) { return itemA.m_shared.m_maxStackSize != 1; } return false; } public static Vector2i FindEmptySlot(Inventory inventory, List<Vector2i> blockedSlots) { //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Unknown result type (might be due to invalid IL or missing references) for (int i = 0; i < inventory.m_height; i++) { for (int j = 0; j < inventory.m_width; j++) { if (inventory.GetItemAt(j, i) == null && !blockedSlots.Contains(new Vector2i(j, i))) { return new Vector2i(j, i); } } } return new Vector2i(-1, -1); } public static List<ItemData> GetAllMoveableItems(Inventory from, Inventory to, MoveAction moveAction) { Inventory val = CopyInventory(from); Inventory to2 = CopyInventory(to); moveAction(val, to2); return CountMoved(from, val); } public static List<ItemData> GetAllMoveableItems(Inventory from, Inventory to) { return GetAllMoveableItems(from, to, MoveAll); } public static void MoveAll(Inventory from, Inventory to) { to.MoveAll(from); } private static List<ItemData> CountMoved(Inventory from, Inventory fromCopy) { List<ItemData> list = new List<ItemData>(); foreach (ItemData item in from.m_inventory) { ItemData itemAt = fromCopy.GetItemAt(item.m_gridPos.x, item.m_gridPos.y); if (itemAt == null) { list.Add(item); } else if (item.m_stack > itemAt.m_stack) { ItemData val = item.Clone(); val.m_stack = item.m_stack - itemAt.m_stack; list.Add(val); } } return list; } public static Inventory CopyInventory(Inventory target) { //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0053: Expected O, but got Unknown return new Inventory(target.m_name, target.m_bkg, target.m_width, target.m_height) { m_inventory = new List<ItemData>(from x in target.GetAllItems() select x.Clone()) }; } public static bool AddItemToInventory(this Inventory target, ItemData item, int amount, Vector2i pos) { //IL_0006: 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_004e: Unknown result type (might be due to invalid IL or missing references) //IL_0054: Unknown result type (might be due to invalid IL or missing references) if (amount == 0) { return false; } ItemData itemAt = target.GetItemAt(pos.x, pos.y); if (itemAt != null) { if (!CanStack(itemAt, item)) { return false; } if (itemAt.m_stack + amount > itemAt.m_shared.m_maxStackSize) { return false; } } ItemData val = item.CloneDeeper(); val.m_stack = amount; return target.AddItem(val, amount, pos.x, pos.y); } public static ItemData CloneDeeper(this ItemData itemDrop) { ItemData val = itemDrop.Clone(); ref SharedData shared = ref val.m_shared; object? obj = memberwiseCloneMethod.Invoke(itemDrop.m_shared, null); shared = (SharedData)((obj is SharedData) ? obj : null); return val; } public static void PrintItem(string title, ItemData itemData) { } } public static class Log { private static ManualLogSource logSource; internal static void Init(ManualLogSource manualLogSource) { logSource = manualLogSource; } public static void LogCodeInstruction(object data) { } public static void LogDebug(string data) { } public static void LogError(string data) { if (logSource != null) { logSource.LogError((object)data); } else { Debug.LogError((object)data); } } public static void LogFatal(string data) { if (logSource != null) { logSource.LogFatal((object)data); } else { Debug.LogError((object)data); } } public static void LogInfo(string data) { if (logSource != null) { logSource.LogInfo((object)data); } else { Debug.Log((object)data); } } public static void LogWarning(string data) { if (logSource != null) { logSource.LogWarning((object)data); } else { Debug.LogWarning((object)data); } } } public static class ReflectionHelper { private const BindingFlags allFlags = (BindingFlags)(-1); public static bool IsType(this object target, string name) { return target.GetType().Name == name; } public static bool HasField(this object target, string name) { return target.GetType().GetField(name, (BindingFlags)(-1)) != null; } public static T GetField<T>(this object target, string name) { return (T)(target.GetType().GetField(name, (BindingFlags)(-1))?.GetValue(target)); } public static T InvokeMethod<T>(this object target, string name, params object[] parameter) { parameter = ((parameter.Length == 0) ? null : parameter); return (T)(target.GetType().GetMethod(name, (BindingFlags)(-1))?.Invoke(target, parameter)); } public static T InvokeStaticMethod<T>(string type, string name, params object[] parameter) { parameter = ((parameter.Length == 0) ? null : parameter); return (T)(Type.GetType(type)?.GetMethod(name, (BindingFlags)(-1))?.Invoke(null, parameter)); } } public class HumanoidExtend : MonoBehaviour { private static readonly ConditionalWeakTable<Inventory, HumanoidInventoryOwner> Humanoids = new ConditionalWeakTable<Inventory, HumanoidInventoryOwner>(); private Inventory inventory; private void Awake() { UpdateInventory(); } private void Start() { UpdateInventory(); } private void UpdateInventory() { Humanoid humanoid = default(Humanoid); if (!((Component)this).TryGetComponent<Humanoid>(ref humanoid)) { return; } inventory = humanoid.GetInventory(); if (inventory == null) { return; } foreach (Inventory inventory in inventory.GetInventories()) { Humanoids.TryAdd(inventory, (Inventory i) => new HumanoidInventoryOwner(humanoid, i)); } } private void OnDestroy() { if (inventory == null) { return; } foreach (Inventory inventory in inventory.GetInventories()) { Humanoids.Remove(inventory); } } public static bool GetHumanoid(Inventory inventory, out HumanoidInventoryOwner humanoid) { return Humanoids.TryGetValue(inventory, out humanoid); } } public class InventoryBlock { private static readonly Dictionary<Inventory, InventoryBlock> Inventories = new Dictionary<Inventory, InventoryBlock>(); public bool BlockAllSlots { get; set; } public bool BlockConsume { get; set; } public Dictionary<Vector2i, int> BlockedSlots { get; } = new Dictionary<Vector2i, int>(); public static InventoryBlock Get(Inventory inventory) { if (Inventories.TryGetValue(inventory, out var value)) { return value; } InventoryBlock inventoryBlock = new InventoryBlock(); Inventories.Add(inventory, inventoryBlock); return inventoryBlock; } public void BlockSlot(Vector2i slot) { //IL_0000: 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_0037: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_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_0027: Unknown result type (might be due to invalid IL or missing references) if (CanBlockSlot(slot)) { if (BlockedSlots.ContainsKey(slot)) { BlockedSlots[slot]++; } else { BlockedSlots[slot] = 1; } } } public void ReleaseSlot(Vector2i slot) { //IL_0000: 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_001e: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0021: 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_0037: Unknown result type (might be due to invalid IL or missing references) //IL_0046: Unknown result type (might be due to invalid IL or missing references) if (CanBlockSlot(slot) && BlockedSlots.ContainsKey(slot)) { BlockedSlots[slot]--; if (BlockedSlots[slot] <= 0) { BlockedSlots.Remove(slot); } } } public void ReleaseBlockedSlots() { BlockedSlots.Clear(); BlockAllSlots = false; BlockConsume = false; } public bool IsSlotBlocked(Vector2i slot) { //IL_0016: Unknown result type (might be due to invalid IL or missing references) if (!BlockConsume && !BlockAllSlots) { return BlockedSlots.ContainsKey(slot); } return true; } public bool IsAnySlotBlocked() { if (!BlockConsume && !BlockAllSlots) { return BlockedSlots.Count > 0; } return true; } private static bool CanBlockSlot(Vector2i slot) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0009: Unknown result type (might be due to invalid IL or missing references) if (slot.x >= 0) { return slot.y >= 0; } return false; } } public static class InventoryHandler { public static void RPC_RequestItemAddResponse(long sender, ZDOID containerId, ZPackage package) { HandleRPC(new RequestChestAddResponse(package), (RequestChestAddResponse p) => GetSourceInventory(p.SourceID), RPC_RequestItemAddResponse); } public static void RPC_RequestItemRemoveResponse(long sender, ZDOID containerId, ZPackage package) { HandleRPC(new RequestChestRemoveResponse(package), (RequestChestRemoveResponse p) => GetTargetInventory(p.SourceID), RPC_RequestItemRemoveResponse); } public static void RPC_RequestDropResponse(long sender, ZDOID containerId, ZPackage package) { HandleRPC(new RequestDropResponse(package), RPC_RequestDropResponse); } public static void RPC_RequestItemConsumeResponse(long sender, ZDOID containerId, ZPackage package) { HandleRPC(new RequestConsumeResponse(package), RPC_RequestItemConsumeResponse); } public static void RPC_RequestItemMoveResponse(long sender, ZDOID containerId, ZPackage package) { HandleRPC(new RequestMoveResponse(package), RPC_RequestItemMoveResponse); } private static void HandleRPC<T>(T package, Func<T, Inventory> inventory, Container container, Action<Inventory, Container, T> handle) where T : IPackage { CallRPC(handle.Method.Name, package, delegate { handle(inventory(package), container, package); }); } private static void HandleRPC<T>(T package, Func<T, Inventory> inventory, Action<Inventory, T> handle) where T : IPackage { CallRPC(handle.Method.Name, package, delegate { handle(inventory(package), package); }); } private static void HandleRPC<T>(T package, Action<T> handle) where T : IPackage { CallRPC(handle.Method.Name, package, delegate { handle(package); }); } private static void CallRPC(string timerName, IPackage package, Action action) { action?.Invoke(); } public static void RPC_RequestItemRemoveResponse(Inventory inventory, RequestChestRemoveResponse response) { //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_0017: 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_00d9: Unknown result type (might be due to invalid IL or missing references) //IL_00e0: Expected O, but got Unknown //IL_003a: 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_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) Vector2i toPos = PackageHandler.GetPackage<RequestChestRemove>(response.SourceID).toPos; InventoryBlock.Get(inventory).ReleaseSlot(toPos); InventoryPreview.RemovePackage(response); if (response.Success && toPos.x >= 0 && toPos.y >= 0) { if (!inventory.AddItemToInventory(response.responseItem, response.Amount, toPos)) { int num = response.Amount; ItemData itemAt = inventory.GetItemAt(toPos.x, toPos.y); if (itemAt != null && InventoryHelper.CanStack(response.responseItem, itemAt)) { int maxStackSize = itemAt.m_shared.m_maxStackSize; int stack = itemAt.m_stack; int num2 = maxStackSize - stack; itemAt.m_stack += num2; num -= num2; } DropItem(response.responseItem, num); } } else if (response.responseItem != null) { Inventory val = new Inventory("tmp", (Sprite)null, 1, 1); val.AddItem(response.responseItem); inventory.MoveItemToThis(val, response.responseItem); ItemData itemAt2 = val.GetItemAt(0, 0); if (itemAt2 != null) { DropItem(itemAt2, itemAt2.m_stack); } } UpdateGUIAfterPlayerMove(GetTargetInventory(response.SourceID)); } private static void RPC_RequestDropResponse(RequestDropResponse response) { //IL_001e: Unknown result type (might be due to invalid IL or missing references) DropItem(response.responseItem, response.responseItem?.m_stack ?? 0); UpdateGUIAfterPlayerMove(response.sender); } private static void UpdateGUIAfterPlayerMove(ZDOID sender) { //IL_0018: 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) if (Object.op_Implicit((Object)(object)InventoryGui.instance) && Object.op_Implicit((Object)(object)Player.m_localPlayer) && sender == ((Character)Player.m_localPlayer).GetZDOID()) { InventoryGui.instance.UpdateCraftingPanel(false); } } private static void UpdateGUIAfterPlayerMove(Inventory inventory) { if (Object.op_Implicit((Object)(object)InventoryGui.instance) && Object.op_Implicit((Object)(object)Player.m_localPlayer) && ((Humanoid)Player.m_localPlayer).GetInventory().GetInventories().Contains(inventory)) { InventoryGui.instance.UpdateCraftingPanel(false); } } public static void DropItem(ItemData item, int amount) { if (amount > 0 && item != null) { DropItem(Player.m_localPlayer, item, amount); } } private static void DropItem(Player player, ItemData item, int amount) { //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_001b: 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_003e: 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_0048: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Unknown result type (might be due to invalid IL or missing references) //IL_0073: 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) Transform transform = ((Component)player).transform; ItemDrop val = ItemDrop.DropItem(item, amount, transform.position + transform.forward + transform.up, transform.rotation); val.OnPlayerDrop(); ((Component)val).GetComponent<Rigidbody>().velocity = (transform.forward + Vector3.up) * 5f; ((Character)player).m_zanim.SetTrigger("interact"); ((Humanoid)player).m_dropEffects.Create(transform.position, Quaternion.identity, (Transform)null, 1f, -1); ItemData itemData = val.m_itemData; ((Character)player).Message((MessageType)1, "$msg_dropped " + itemData.m_shared.m_name, itemData.m_stack, itemData.GetIcon()); } public static void RPC_RequestItemAddResponse(Inventory inventory, RequestChestAddResponse response) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0014: 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) Vector2i inventoryPos = response.inventoryPos; ItemData switchItem = response.switchItem; InventoryBlock.Get(inventory).ReleaseSlot(inventoryPos); InventoryPreview.RemovePackage(response); if (switchItem != null && !inventory.AddItemToInventory(switchItem, switchItem.m_stack, inventoryPos)) { DropItem(switchItem, switchItem.m_stack); } UpdateGUIAfterPlayerMove(GetSourceInventory(response.SourceID)); } public static void RPC_RequestItemConsumeResponse(RequestConsumeResponse response) { Player localPlayer = Player.m_localPlayer; InventoryBlock.Get(((Humanoid)localPlayer).GetInventory()).BlockConsume = false; if (response.item != null && ((Humanoid)localPlayer).CanConsumeItem(response.item, false)) { if (Object.op_Implicit((Object)(object)response.item.m_shared.m_consumeStatusEffect)) { ((Character)localPlayer).m_seman.AddStatusEffect(response.item.m_shared.m_consumeStatusEffect, true, 0, 0f); } if ((double)response.item.m_shared.m_food > 0.0) { localPlayer.EatFood(response.item); } } } public static void RPC_RequestItemMoveResponse(RequestMoveResponse response) { InventoryPreview.RemovePackage(response); } internal static Inventory GetSourceInventory(int id) { return PackageHandler.GetPackage<IRequest>(id)?.SourceInventory; } internal static Inventory GetTargetInventory(int id) { return PackageHandler.GetPackage<IRequest>(id)?.TargetInventory; } } public abstract class InventoryOwner { public abstract ZNetView ZNetView { get; } public abstract Inventory Inventory { get; } public virtual bool IsValid() { if (Object.op_Implicit((Object)(object)ZNetView) && ZNetView.HasOwner()) { return Inventory != null; } return false; } public static InventoryOwner GetOwner(Inventory inventory) { if (inventory == null) { return null; } if (HumanoidExtend.GetHumanoid(inventory, out var humanoid)) { return humanoid; } if (ContainerExtend.GetContainer(inventory, out var container)) { return container; } return null; } public static InventoryOwner GetOwner(ItemData item) { if (item == null) { return null; } if (InventoryPatch.InventoryOfItem.TryGetValue(item, out var value)) { return GetOwner(value); } return null; } public string GetDescription() { if (!IsValid()) { return "-"; } return $"{Inventory.GetName()} ({GetType().Name}), is owner: {ZNetView.IsOwner()}"; } } public class ContainerInventoryOwner : InventoryOwner { public Container Container { get; } public bool IsItemDrawer { get; } public override ZNetView ZNetView => Container.m_nview; public override Inventory Inventory => Container.GetInventory(); public ContainerInventoryOwner(Container container) { Container = container; IsItemDrawer = ItemDrawerCompat.IsItemDrawer(Container); } } public class HumanoidInventoryOwner : InventoryOwner { private readonly Inventory inventory; public Humanoid Humanoid { get; } public override ZNetView ZNetView => ((Character)Humanoid).m_nview; public override Inventory Inventory => inventory; public HumanoidInventoryOwner(Humanoid humanoid, Inventory inventory) { Humanoid = humanoid; this.inventory = inventory; } } public static class InventoryPreview { public static readonly ConditionalWeakTable<Inventory, List<IRequest>> PackageChanges = new ConditionalWeakTable<Inventory, List<IRequest>>(); public static readonly ConditionalWeakTable<Inventory, List<IRequest>> ToRemovePackages = new ConditionalWeakTable<Inventory, List<IRequest>>(); private static WaitForSeconds removeQueuedPackagesDelay = new WaitForSeconds(0.2f); public static void AddPackage(IRequest package) { package.RequestID = PackageHandler.AddPackage(package); AppendPackage(package.SourceInventory, package); AppendPackage(package.TargetInventory, package); } private static void AppendPackage(Inventory inventory, IRequest package) { if (PackageChanges.TryGetValue(inventory, out var value)) { if (!value.Contains(package)) { value.Add(package); } Log.LogDebug($"InventoryPreview: Appended package {package.RequestID} to inventory {inventory.m_name}, total packages: {value.Count}"); return; } PackageChanges.Add(inventory, new List<IRequest> { package }); Inventory obj = inventory; obj.m_onChanged = (Action)Delegate.Combine(obj.m_onChanged, (Action)delegate { RemoveQueuedPackages(inventory); }); Log.LogDebug($"InventoryPreview: Added package {package.RequestID} to inventory {inventory.m_name}, total packages: 1 (new)"); } public static void RemovePackage(IResponse package) { RemovePackage(InventoryHandler.GetSourceInventory(package.SourceID), package); RemovePackage(InventoryHandler.GetTargetInventory(package.SourceID), package); PackageHandler.RemovePackage(package.SourceID); } private static void RemovePackage(Inventory inventory, IResponse package) { if (inventory == null) { return; } InventoryOwner owner = InventoryOwner.GetOwner(inventory); IRequest request = null; if (PackageChanges.TryGetValue(inventory, out var value)) { request = value.Find((IRequest p) => p.RequestID == package.SourceID); } if (request != null) { if (ToRemovePackages.TryGetValue(inventory, out var value2)) { value2.Add(request); } else { ToRemovePackages.Add(inventory, new List<IRequest> { request }); } if (owner != null && owner.IsValid() && owner.ZNetView.IsOwner()) { RemoveQueuedPackages(inventory); } else if (!package.Success) { ((MonoBehaviour)ThreadingHelper.Instance).StartCoroutine(RemoveQueuedPackagesDelayed(inventory)); } } } private static void RemoveQueuedPackages(Inventory inventory) { if (!ToRemovePackages.TryGetValue(inventory, out var value) || value.Count <= 0) { return; } foreach (IRequest item in new List<IRequest>(value)) { if (PackageChanges.TryGetValue(inventory, out var value2)) { value2.Remove(item); } value.Remove(item); Log.LogDebug($"InventoryPreview: Removed package {item.RequestID} from inventory {inventory.m_name}, total packages: {value.Count}"); } } private static IEnumerator RemoveQueuedPackagesDelayed(Inventory inventory) { yield return removeQueuedPackagesDelay; RemoveQueuedPackages(inventory); } public static bool GetChanges(Inventory inventory, out SlotPreview preview) { //IL_00da: Unknown result type (might be due to invalid IL or missing references) //IL_00df: Unknown result type (might be due to invalid IL or missing references) //IL_00e3: Unknown result type (might be due to invalid IL or missing references) //IL_00e8: Unknown result type (might be due to invalid IL or missing references) //IL_0155: Unknown result type (might be due to invalid IL or missing references) //IL_00f5: Unknown result type (might be due to invalid IL or missing references) //IL_010c: Unknown result type (might be due to invalid IL or missing references) //IL_0128: 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_00a8: Unknown result type (might be due to invalid IL or missing references) //IL_00b7: Unknown result type (might be due to invalid IL or missing references) //IL_029c: Unknown result type (might be due to invalid IL or missing references) //IL_02b3: Unknown result type (might be due to invalid IL or missing references) //IL_01ff: Unknown result type (might be due to invalid IL or missing references) //IL_021b: Unknown result type (might be due to invalid IL or missing references) //IL_0232: Unknown result type (might be due to invalid IL or missing references) //IL_0249: Unknown result type (might be due to invalid IL or missing references) if (inventory == null) { preview = null; return false; } if (PackageChanges.TryGetValue(inventory, out var value)) { preview = new SlotPreview(inventory); foreach (IRequest item3 in value) { if (item3 is RequestChestAdd requestChestAdd) { if (requestChestAdd.dragItem != null) { ItemData item = null; if (requestChestAdd.allowSwitch) { item = item3.TargetInventory.GetItemAt(requestChestAdd.toPos.x, requestChestAdd.toPos.y); } if (inventory == item3.SourceInventory) { preview.Add(requestChestAdd.dragItem.m_gridPos, item); } if (inventory == item3.TargetInventory) { preview.Remove(requestChestAdd.toPos, item); preview.Add(requestChestAdd.toPos, requestChestAdd.dragItem); } } } else if (item3 is RequestChestRemove requestChestRemove) { Vector2i fromPos = requestChestRemove.fromPos; Vector2i toPos = requestChestRemove.toPos; if (inventory == item3.SourceInventory) { preview.Remove(fromPos, requestChestRemove.item, requestChestRemove.dragAmount); preview.Add(fromPos, requestChestRemove.switchItem); } if (inventory == item3.TargetInventory) { preview.Add(toPos, requestChestRemove.item, requestChestRemove.dragAmount); } } else { if (!(item3 is RequestMove requestMove) || (preview.GetSlot(requestMove.fromPos, out var item2) && requestMove.itemHash != ((item2 != null) ? new int?(StringExtensionMethods.GetStableHashCode(item2.PrefabName())) : null))) { continue; } ItemData itemAt = requestMove.TargetInventory.GetItemAt(requestMove.toPos.x, requestMove.toPos.y); if (itemAt != null && !InventoryHelper.CanStack(requestMove.item, itemAt)) { if (requestMove.dragAmount == requestMove.item.m_stack) { preview.Remove(requestMove.fromPos, requestMove.item, requestMove.dragAmount); preview.Remove(requestMove.toPos, itemAt, itemAt.m_stack); preview.Add(requestMove.fromPos, itemAt, itemAt.m_stack); preview.Add(requestMove.toPos, requestMove.item, requestMove.dragAmount); } } else { int amount = Mathf.Max(0, requestMove.dragAmount); if (itemAt != null) { amount = Mathf.Min(itemAt.m_shared.m_maxStackSize - itemAt.m_stack, requestMove.dragAmount); } preview.Remove(requestMove.fromPos, requestMove.item, amount); preview.Add(requestMove.toPos, requestMove.item, amount); } } } return preview.HasChanges(); } preview = null; return false; } } public static class InventoryIgnore { public static bool IgnoreInventory(this InventoryOwner owner) { if (OdinShip.IsOdinShipInstalled() && owner is ContainerInventoryOwner containerInventoryOwner && containerInventoryOwner.Container.IsOdinShipContainer()) { return true; } if (owner == null || !Object.op_Implicit((Object)(object)owner.ZNetView) || owner.ZNetView.GetZDO() == null) { return false; } return owner.ZNetView.GetZDO().GetBool("MUC_Ignore", false); } public static bool IgnoreInventory(this Container container) { return InventoryOwner.GetOwner(container.GetInventory()).IgnoreInventory(); } } public static class ItemDrawerCompat { private static Type drawerContainerType; private static FieldRef<object, ItemData> drawerField_item; static ItemDrawerCompat() { if (Chainloader.PluginInfos.ContainsKey("mkz.itemdrawers")) { drawerContainerType = AccessTools.TypeByName("DrawerContainer, itemdrawers"); drawerField_item = AccessTools.FieldRefAccess<ItemData>(drawerContainerType, "_item"); } } public static bool IsItemDrawer(Container container) { if (drawerContainerType != null) { return Object.op_Implicit((Object)(object)((Component)container).GetComponent(drawerContainerType)); } return false; } [HarmonyPatch("DrawerContainer, itemdrawers", "OnInventoryChanged")] [HarmonyPrefix] public static void UpdateItemOfDrawer(Container __instance) { if (__instance.m_inventory.m_inventory.Count != 0 && __instance.m_inventory.m_inventory[0] != null) { drawerField_item.Invoke((object)__instance) = __instance.m_inventory.m_inventory[0].Clone(); } } [HarmonyPrefix] [HarmonyPatch(typeof(Inventory), "AddItem", new Type[] { typeof(ItemData) })] [HarmonyPatch(typeof(Inventory), "AddItem", new Type[] { typeof(ItemData), typeof(int), typeof(int), typeof(int) })] [HarmonyPriority(700)] public static bool PreventItemAdd(Inventory __instance, ItemData item) { if (InventoryOwner.GetOwner(__instance) is ContainerInventoryOwner containerInventoryOwner && containerInventoryOwner.IsItemDrawer) { ItemData val = drawerField_item.Invoke((object)containerInventoryOwner.Container); if (val != null && val.PrefabName() != item?.PrefabName()) { Log.LogInfo("PreventItemAdd: " + val.PrefabName() + " != " + item?.PrefabName()); return false; } } return true; } [HarmonyPatch(typeof(Inventory), "CanAddItem", new Type[] { typeof(ItemData), typeof(int) })] [HarmonyPostfix] public static void CanAddItem(Inventory __instance, ref bool __result, ItemData item) { if (__result && InventoryOwner.GetOwner(__instance) is ContainerInventoryOwner containerInventoryOwner && containerInventoryOwner.IsItemDrawer) { ItemData val = drawerField_item.Invoke((object)containerInventoryOwner.Container); __result = val == null || val.PrefabName() == item?.PrefabName(); } } [HarmonyPatch("DrawerContainer, itemdrawers", "AddItem")] [HarmonyTranspiler] public static IEnumerable<CodeInstruction> CloneItemBeforeAssignmentTranspiler(IEnumerable<CodeInstruction> instructions) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Expected O, but got Unknown //IL_0051: Unknown result type (might be due to invalid IL or missing references) //IL_0057: Expected O, but got Unknown //IL_0085: Unknown result type (might be due to invalid IL or missing references) //IL_008b: Expected O, but got Unknown return new CodeMatcher(instructions, (ILGenerator)null).MatchForward(false, (CodeMatch[])(object)new CodeMatch[2] { new CodeMatch((OpCode?)OpCodes.Ldfld, (object)AccessTools.Field(typeof(ItemDrop), "m_itemData"), (string)null), new CodeMatch((OpCode?)OpCodes.Stfld, (object)AccessTools.Field(drawerContainerType, "_item"), (string)null) }).Advance(1).InsertAndAdvance((CodeInstruction[])(object)new CodeInstruction[1] { new CodeInstruction(OpCodes.Call, (object)AccessTools.Method(typeof(InventoryHelper), "CloneDeeper", (Type[])null, (Type[])null)) }) .InstructionEnumeration(); } } public static class OdinShip { public static bool IsOdinShipInstalled() { if (!Chainloader.PluginInfos.ContainsKey("marlthon.OdinShipPlus")) { return Chainloader.PluginInfos.ContainsKey("marlthon.OdinShip"); } return true; } public static bool IsOdinShipContainer(this Container container) { return ((object)container).GetType().FullName == "OdinShip.ShipContainer"; } } public static class QuickStackPatch { [HarmonyPatch("QuickStack.QuickStackPlugin, QuickStack", "StackToMany")] [HarmonyTranspiler] public static IEnumerable<CodeInstruction> QuickStackPatchTranspiler(IEnumerable<CodeInstruction> instructions) { //IL_0002: 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_0022: Expected O, but got Unknown //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Expected O, but got Unknown return new CodeMatcher(instructions, (ILGenerator)null).MatchForward(false, (CodeMatch[])(object)new CodeMatch[2] { new CodeMatch((OpCode?)OpCodes.Ldloc_S, (object)null, (string)null), new CodeMatch((Func<CodeInstruction, bool>)((CodeInstruction i) => i.IsVirtCall("ZNetView", "ClaimOwnership")), (string)null) }).RemoveInstructions(9).InstructionEnumeration(); } } [BepInPlugin("com.maxsch.valheim.MultiUserChest", "MultiUserChest", "0.6.0")] [BepInIncompatibility("aedenthorn.QuickStore")] [BepInIncompatibility("aedenthorn.SimpleSort")] [BepInIncompatibility("org.bepinex.plugins.valheim.quick_stack")] [NetworkCompatibility(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] public class Plugin : BaseUnityPlugin { public const string ModName = "MultiUserChest"; public const string ModGuid = "com.maxsch.valheim.MultiUserChest"; public const string ModVersion = "0.6.0"; private static Harmony harmony = new Harmony("com.maxsch.valheim.MultiUserChest"); public static Plugin Instance { get; private set; } private void Awake() { Instance = this; Log.Init(((BaseUnityPlugin)this).Logger); harmony.PatchAll(); ((MonoBehaviour)this).InvokeRepeating("UpdateAccessedContainer", 0f, 0.1f); } private void Start() { ApplyModPatches(); } internal static void ApplyModPatches() { if (Chainloader.PluginInfos.ContainsKey("mkz.itemdrawers")) { harmony.PatchAll(typeof(ItemDrawerCompat)); } } private void UpdateAccessedContainer() { //IL_0088: Unknown result type (might be due to invalid IL or missing references) //IL_0069: Unknown result type (might be due to invalid IL or missing references) if (Object.op_Implicit((Object)(object)Player.m_localPlayer) && ((Character)Player.m_localPlayer).m_nview.IsValid() && Object.op_Implicit((Object)(object)InventoryGui.instance)) { Container currentContainer = InventoryGui.instance.m_currentContainer; if (Object.op_Implicit((Object)(object)currentContainer) && currentContainer.m_nview.IsValid()) { ((Character)Player.m_localPlayer).m_nview.GetZDO().Set("accessed-container", currentContainer.m_nview.GetZDO().m_uid); } else { ((Character)Player.m_localPlayer).m_nview.GetZDO().Set("accessed-container", ZDOID.None); } } } } public static class PackageHandler { private static readonly Dictionary<int, IPackage> Packages = new Dictionary<int, IPackage>(); private static readonly Random Random = new Random(); private static int total; public static int AddPackage(IPackage package) { int randomId = GetRandomId(); Packages.Add(randomId, package); return randomId; } public static void RemovePackage(int id) { Packages.Remove(id); } private static int GetRandomId() { return Random.Next(int.MinValue, int.MaxValue); } public static bool GetPackage<T>(int id, out T package) where T : IPackage { if (Packages.TryGetValue(id, out var value)) { package = (T)value; return true; } package = default(T); return false; } public static T GetPackage<T>(int id) where T : IPackage { if (Packages.TryGetValue(id, out var value)) { return (T)value; } return default(T); } } } namespace MultiUserChest.Patches { [HarmonyPatch] public static class ContainerPatch { public const string ItemMoveRPC = "MUC_RequestItemMove"; public const string ItemMoveResponseRPC = "MUC_RequestItemMoveResponse"; public const string ItemAddRPC = "MUC_RequestItemAdd"; public const string ItemAddResponseRPC = "MUC_RequestItemAddResponse"; public const string ItemRemoveRPC = "MUC_RequestItemRemove"; public const string ItemRemoveResponseRPC = "MUC_RequestItemRemoveResponse"; public const string ItemConsumeRPC = "MUC_RequestItemConsume"; public const string ItemConsumeResponseRPC = "MUC_RequestItemConsumeResponse"; public const string ItemDropRPC = "MUC_RequestItemDrop"; public const string ItemDropResponseRPC = "MUC_RequestItemDropResponse"; [HarmonyPatch(typeof(Container), "Awake")] [HarmonyPostfix] public static void ContainerAwakePatch(Container __instance) { ((Component)__instance).gameObject.AddComponent<ContainerExtend>(); if (!__instance.IgnoreInventory() && !Object.op_Implicit((Object)(object)__instance.m_nview)) { __instance.m_nview = (Object.op_Implicit((Object)(object)__instance.m_rootObjectOverride) ? ((Component)__instance.m_rootObjectOverride).GetComponent<ZNetView>() : ((Component)__instance).GetComponent<ZNetView>()); } } [HarmonyPatch(typeof(Container), "RPC_RequestOpen")] [HarmonyPrefix] public static bool ContainerRPC_RequestOpenPatch(Container __instance, long uid, long playerID) { //IL_007e: Unknown result type (might be due to invalid IL or missing references) if (__instance.IgnoreInventory() || !__instance.m_nview.IsOwner()) { return true; } if (!__instance.CheckAccess(playerID)) { __instance.m_nview.InvokeRPC(uid, "OpenRespons", new object[1] { false }); return false; } if (IsContainerInUse(__instance, uid)) { __instance.m_nview.InvokeRPC(uid, "OpenRespons", new object[1] { true }); return false; } ZDOMan.instance.ForceSendZDO(uid, __instance.m_nview.GetZDO().m_uid); __instance.m_nview.GetZDO().SetOwner(uid); __instance.m_nview.InvokeRPC(uid, "OpenRespons", new object[1] { true }); return false; } [HarmonyPatch(typeof(Container), "RPC_RequestStack")] [HarmonyPrefix] public static bool ContainerRPC_RequestStackPatch(Container __instance, long uid, long playerID) { //IL_007e: Unknown result type (might be due to invalid IL or missing references) if (__instance.IgnoreInventory() || !__instance.m_nview.IsOwner()) { return true; } if (!__instance.CheckAccess(playerID)) { __instance.m_nview.InvokeRPC(uid, "RPC_StackResponse", new object[1] { false }); return false; } if (IsContainerInUse(__instance, uid)) { __instance.m_nview.InvokeRPC(uid, "RPC_StackResponse", new object[1] { true }); return false; } ZDOMan.instance.ForceSendZDO(uid, __instance.m_nview.GetZDO().m_uid); __instance.m_nview.GetZDO().SetOwner(uid); __instance.m_nview.InvokeRPC(uid, "RPC_StackResponse", new object[1] { true }); return false; } private static bool IsContainerInUse(Container container, long playerId) { bool flag = container.IsInUse(); bool flag2 = Object.op_Implicit((Object)(object)container.m_wagon) && container.m_wagon.InUse(); bool flag3 = playerId == ZNet.GetUID(); if (flag || flag2) { return !flag3; } return false; } [HarmonyPatch(typeof(Container), "UpdateUseVisual")] [HarmonyPostfix] public static void ContainerUpdateUseVisualPatch(Container __instance) { if (!__instance.IgnoreInventory() && __instance.m_nview.IsValid() && Object.op_Implicit((Object)(object)Player.m_localPlayer) && Object.op_Implicit((Object)(object)InventoryGui.instance)) { bool flag = (Object)(object)__instance == (Object)(object)InventoryGui.instance.m_currentContainer || IsContainerInUse(__instance); if (Object.op_Implicit((Object)(object)__instance.m_open)) { __instance.m_open.SetActive(flag); } if (Object.op_Implicit((Object)(object)__instance.m_closed)) { __instance.m_closed.SetActive(!flag); } } } private static bool IsContainerInUse(Container container) { //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Unknown result type (might be due to invalid IL or missing references) ZDOID containerId = container.m_nview.GetZDO().m_uid; return Player.GetAllPlayers().Any((Player p) => (Object)(object)p != (Object)(object)Player.m_localPlayer && ((Character)p).m_nview.IsValid() && ((Character)p).m_nview.GetZDO().GetZDOID("accessed-container") == containerId); } } [HarmonyPatch] public static class GamePatches { [HarmonyPatch(typeof(Game), "Start")] [HarmonyPostfix] public static void GameStartPatch() { RegisterRPCs(); } public static void RegisterRPCs() { ZRoutedRpc.instance.Register<ZDOID, ZPackage>("MUC_RequestItemMove", (Action<long, ZDOID, ZPackage>)ContainerRPCHandler.RPC_RequestItemMove); ZRoutedRpc.instance.Register<ZDOID, ZPackage>("MUC_RequestItemAdd", (Action<long, ZDOID, ZPackage>)ContainerRPCHandler.RPC_RequestItemAdd); ZRoutedRpc.instance.Register<ZDOID, ZPackage>("MUC_RequestItemRemove", (Action<long, ZDOID, ZPackage>)ContainerRPCHandler.RPC_RequestItemRemove); ZRoutedRpc.instance.Register<ZDOID, ZPackage>("MUC_RequestItemConsume", (Action<long, ZDOID, ZPackage>)ContainerRPCHandler.RPC_RequestItemConsume); ZRoutedRpc.instance.Register<ZDOID, ZPackage>("MUC_RequestItemDrop", (Action<long, ZDOID, ZPackage>)ContainerRPCHandler.RPC_RequestDrop); ZRoutedRpc.instance.Register<ZDOID, ZPackage>("MUC_RequestItemMoveResponse", (Action<long, ZDOID, ZPackage>)InventoryHandler.RPC_RequestItemMoveResponse); ZRoutedRpc.instance.Register<ZDOID, ZPackage>("MUC_RequestItemAddResponse", (Action<long, ZDOID, ZPackage>)InventoryHandler.RPC_RequestItemAddResponse); ZRoutedRpc.instance.Register<ZDOID, ZPackage>("MUC_RequestItemRemoveResponse", (Action<long, ZDOID, ZPackage>)InventoryHandler.RPC_RequestItemRemoveResponse); ZRoutedRpc.instance.Register<ZDOID, ZPackage>("MUC_RequestItemConsumeResponse", (Action<long, ZDOID, ZPackage>)InventoryHandler.RPC_RequestItemConsumeResponse); ZRoutedRpc.instance.Register<ZDOID, ZPackage>("MUC_RequestItemDropResponse", (Action<long, ZDOID, ZPackage>)InventoryHandler.RPC_RequestDropResponse); } public static void InvokeRPC(ZNetView netView, string rpc, IPackage package) { //IL_001f: Unknown result type (might be due to invalid IL or missing references) ZRoutedRpc.instance.InvokeRoutedRPC(netView.m_zdo.GetOwner(), rpc, new object[2] { netView.m_zdo.m_uid, package.WriteToPackage() }); } } [HarmonyPatch] public static class HumanoidPatch { [HarmonyPatch(typeof(Humanoid), "Awake")] [HarmonyPostfix] public static void HumanoidAwakePatch(Humanoid __instance) { ((Component)__instance).gameObject.AddComponent<HumanoidExtend>(); } } [HarmonyPatch] public static class InventoryGuiPatch { [HarmonyPatch(typeof(InventoryGui), "Update")] [HarmonyPostfix] public static void InventoryGuiUpdatePatch(InventoryGui __instance) { if (Object.op_Implicit((Object)(object)__instance.m_currentContainer) && Object.op_Implicit((Object)(object)__instance.m_currentContainer.m_nview) && __instance.m_currentContainer.m_nview.IsValid()) { __instance.m_currentContainer.CheckForChanges(); } } [HarmonyPatch(typeof(InventoryGui), "OnRightClickItem")] [HarmonyPrefix] public static bool InventoryGuiOnRightClickItemPatch(InventoryGui __instance, InventoryGrid grid, ItemData item) { Player localPlayer = Player.m_localPlayer; if (item == null || !Object.op_Implicit((Object)(object)localPlayer)) { return true; } if (grid.GetInventory() == ((Humanoid)localPlayer).GetInventory()) { return true; } if (!Object.op_Implicit((Object)(object)__instance.m_currentContainer) || __instance.m_currentContainer.IsOwner()) { return true; } if (InventoryBlock.Get(((Humanoid)localPlayer).GetInventory()).BlockConsume) { return false; } if (((Humanoid)localPlayer).CanConsumeItem(item, false)) { InventoryBlock.Get(((Humanoid)localPlayer).GetInventory()).BlockConsume = true; RequestConsume package = new RequestConsume(item); GamePatches.InvokeRPC(__instance.m_currentContainer.m_nview, "MUC_RequestItemConsume", package); } return false; } [HarmonyPatch(typeof(InventoryGui), "UpdateContainer")] [HarmonyTranspiler] public static IEnumerable<CodeInstruction> ChangeOwnerCheck(IEnumerable<CodeInstruction> instructions) { //IL_0002: 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_0022: Expected O, but got Unknown //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Expected O, but got Unknown //IL_006c: Unknown result type (might be due to invalid IL or missing references) //IL_0072: Expected O, but got Unknown //IL_00a0: Unknown result type (might be due to invalid IL or missing references) //IL_00a6: Expected O, but got Unknown return new CodeMatcher(instructions, (ILGenerator)null).MatchForward(true, (CodeMatch[])(object)new CodeMatch[3] { new CodeMatch((OpCode?)OpCodes.Ldarg_0, (object)null, (string)null), new CodeMatch((Func<CodeInstruction, bool>)((CodeInstruction i) => i.opcode == OpCodes.Ldfld && ((FieldInfo)i.operand).Name == "m_currentContainer"), (string)null), new CodeMatch((Func<CodeInstruction, bool>)((CodeInstruction i) => i.opcode == OpCodes.Callvirt && ((MethodInfo)i.operand).Name == "IsOwner"), (string)null) }).RemoveInstructions(1).Insert((CodeInstruction[])(object)new CodeInstruction[1] { new CodeInstruction(OpCodes.Call, (object)AccessTools.Method(typeof(InventoryGuiPatch), "CanOpenContainer", (Type[])null, (Type[])null)) }) .InstructionEnumeration(); } public static bool CanOpenContainer(Container container) { if (container.IgnoreInventory()) { return container.IsOwner(); } return true; } [HarmonyPatch(typeof(InventoryGui), "OnDropOutside")] [HarmonyPrefix] public static void InventoryGuiOnDropOutsidePatch(InventoryGui __instance, ref bool __runOriginal) { //IL_0071: 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) if (!__runOriginal || !Object.op_Implicit((Object)(object)__instance.m_dragGo)) { return; } if (((Humanoid)Player.m_localPlayer).GetInventory().GetInventories().Contains(__instance.m_dragInventory)) { Log.LogDebug("Drop item from own inventory"); return; } bool flag = Object.op_Implicit((Object)(object)__instance.m_currentContainer) && __instance.m_currentContainer.IsOwner(); if (!(!Object.op_Implicit((Object)(object)__instance.m_currentContainer) || flag)) { RequestDrop package = new RequestDrop(__instance.m_dragItem.m_gridPos, __instance.m_dragAmount, ((Character)Player.m_localPlayer).GetZDOID()); GamePatches.InvokeRPC(__instance.m_currentContainer.m_nview, "MUC_RequestItemDrop", package); __instance.SetupDragItem((ItemData)null, (Inventory)null, 1); __runOriginal = false; } } [HarmonyPatch(typeof(Inventory), "Load")] [HarmonyPostfix] public static void InventorySelectSameItemAfterLoad(Inventory __instance) { if (Object.op_Implicit((Object)(object)InventoryGui.instance) && InventoryGui.instance.m_dragItem != null && Object.op_Implicit((Object)(object)InventoryGui.instance.m_currentContainer) && InventoryGui.instance.m_currentContainer.GetInventory() == __instance && InventoryGui.instance.m_dragInventory != null && InventoryGui.instance.m_dragInventory == __instance) { ItemData dragItem = InventoryGui.instance.m_dragItem; ItemData itemAt = __instance.GetItemAt(dragItem.m_gridPos.x, dragItem.m_gridPos.y); if (itemAt == null) { InventoryGui.instance.SetupDragItem((ItemData)null, (Inventory)null, 1); return; } int dragAmount = Mathf.Min(itemAt.m_stack, InventoryGui.instance.m_dragAmount); InventoryGui.instance.m_dragAmount = dragAmount; InventoryGui.instance.m_dragItem = itemAt; } } [HarmonyPatch(typeof(InventoryGrid), "UpdateInventory")] [HarmonyPostfix] public static void InventoryGridUpdateInventoryPatch(InventoryGrid __instance) { //IL_0028: Unknown result type (might be due to invalid IL or missing references) if (!InventoryPreview.GetChanges(__instance.m_inventory, out var preview)) { return; } foreach (Element element in __instance.m_elements) { if (preview.GetSlot(element.m_pos, out var item)) { if (item == null) { ShowNoItem(element); } else { ShowItem(__instance, element, item); } } } } private static void ShowItem(InventoryGrid inventoryGrid, Element element, ItemData item) { //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_018e: Unknown result type (might be due to invalid IL or missing references) //IL_0194: Invalid comparison between Unknown and I4 //IL_011e: Unknown result type (might be due to invalid IL or missing references) //IL_0117: Unknown result type (might be due to invalid IL or missing references) //IL_0276: Unknown result type (might be due to invalid IL or missing references) //IL_023c: Unknown result type (might be due to invalid IL or missing references) //IL_02bf: Unknown result type (might be due to invalid IL or missing references) //IL_02ad: Unknown result type (might be due to invalid IL or missing references) if (item?.m_shared == null) { return; } int stack = item.m_stack; int maxStackSize = item.m_shared.m_maxStackSize; ((Behaviour)element.m_icon).enabled = stack > 0; element.m_icon.sprite = item.GetIcon(); ((Graphic)element.m_icon).color = Color.white; ((Behaviour)element.m_amount).enabled = stack > 0 && maxStackSize > 1; element.m_amount.text = $"{stack}/{maxStackSize}"; bool flag = item.m_shared.m_useDurability && item.m_durability < item.GetMaxDurability(); ((Component)element.m_durability).gameObject.SetActive(flag); if (flag) { if ((double)item.m_durability <= 0.0) { element.m_durability.SetValue(1f); element.m_durability.SetColor((Color)(((double)Mathf.Sin(Time.time * 10f) > 0.0) ? Color.red : new Color(0f, 0f, 0f, 0f))); } else { element.m_durability.SetValue(item.GetDurabilityPercentage()); element.m_durability.ResetColor(); } } ((Behaviour)element.m_equiped).enabled = false; ((Behaviour)element.m_queued).enabled = false; ((Behaviour)element.m_noteleport).enabled = !item.m_shared.m_teleportable && !ZoneSystem.instance.GetGlobalKey((GlobalKeys)29); if ((int)item.m_shared.m_itemType == 2 && ((double)item.m_shared.m_food > 0.0 || (double)item.m_shared.m_foodStamina > 0.0 || (double)item.m_shared.m_foodEitr > 0.0)) { ((Behaviour)element.m_food).enabled = true; if ((double)item.m_shared.m_food < (double)item.m_shared.m_foodEitr / 2.0 && (double)item.m_shared.m_foodStamina < (double)item.m_shared.m_foodEitr / 2.0) { ((Graphic)element.m_food).color = inventoryGrid.m_foodEitrColor; } else if ((double)item.m_shared.m_foodStamina < (double)item.m_shared.m_food / 2.0) { ((Graphic)element.m_food).color = inventoryGrid.m_foodHealthColor; } else if ((double)item.m_shared.m_food < (double)item.m_shared.m_foodStamina / 2.0) { ((Graphic)element.m_food).color = inventoryGrid.m_foodStaminaColor; } else { ((Graphic)element.m_food).color = Color.white; } } else { ((Behaviour)element.m_food).enabled = false; } ((Behaviour)element.m_quality).enabled = item.m_shared.m_maxQuality > 1; if (item.m_shared.m_maxQuality > 1) { element.m_quality.text = item.m_quality.ToString(); } } private static void ShowNoItem(Element element) { ((Component)element.m_durability).gameObject.SetActive(false); ((Behaviour)element.m_icon).enabled = false; ((Behaviour)element.m_amount).enabled = false; ((Behaviour)element.m_quality).enabled = false; ((Behaviour)element.m_equiped).enabled = false; ((Behaviour)element.m_queued).enabled = false; ((Behaviour)element.m_noteleport).enabled = false; ((Behaviour)element.m_food).enabled = false; element.m_tooltip.m_text = ""; element.m_tooltip.m_topic = ""; } } [HarmonyPatch] public static class InventoryPatch { public static readonly ConditionalWeakTable<ItemData, Inventory> InventoryOfItem = new ConditionalWeakTable<ItemData, Inventory>(); private static readonly WeakReference<ItemData> LastRemovedItem = new WeakReference<ItemData>(null); private static bool allowItemSwap = true; [HarmonyPatch(typeof(Inventory), "AddItem", new Type[] { typeof(ItemData), typeof(int), typeof(int), typeof(int) })] [HarmonyPrefix] [HarmonyPriority(100)] public static void AddItem1Prefix(Inventory __instance, ref bool __runOriginal, ItemData item, int amount, int x, int y, ref bool __result) { //IL_000c: Unknown result type (might be due to invalid IL or missing references) if (__runOriginal && InterceptAddItem(__instance, item, amount, new Vector2i(x, y), out var successfulAdded)) { __result = successfulAdded; __runOriginal = false; } } [HarmonyPatch(typeof(Inventory), "AddItem", new Type[] { typeof(ItemData) })] [HarmonyPrefix] [HarmonyPriority(100)] public static void AddItem2Prefix(Inventory __instance, ref bool __runOriginal, ItemData item, ref bool __result) { //IL_000f: Unknown result type (might be due to invalid IL or missing references) if (__runOriginal && InterceptAddItem(__instance, item, item.m_stack, new Vector2i(-1, -1), out var successfulAdded)) { __result = successfulAdded; __runOriginal = false; } } [HarmonyPatch(typeof(Inventory), "RemoveItem", new Type[] { typeof(ItemData) })] [HarmonyPrefix] [HarmonyPriority(100)] public static void RemoveItemPrefix(Inventory __instance, ref bool __runOriginal, ref bool __result) { if (__runOriginal) { InventoryOwner owner = InventoryOwner.GetOwner(__instance); if (!owner.IgnoreInventory() && owner != null && owner.IsValid() && !owner.ZNetView.IsOwner()) { __result = false; __runOriginal = false; } } } [HarmonyPatch(typeof(Inventory), "RemoveItem", new Type[] { typeof(ItemData) })] [HarmonyPostfix] public static void RemoveItemPostfix(Inventory __instance, ItemData item, ref bool __result) { if (__result) { LastRemov