Please disclose if any significant portion of your mod was created using AI tools by adding the 'AI Generated' category. Failing to do so may result in the mod being removed from Thunderstore.
Decompiled source of MultiUserChest v0.6.1
MultiUserChest.dll
Decompiled a year 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.1")] [assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("0.6.1.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.1")] [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.1"; 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(); } private void Start() { ApplyModPatches(); } internal static void ApplyModPatches() { if (Chainloader.PluginInfos.ContainsKey("mkz.itemdrawers")) { harmony.PatchAll(typeof(ItemDrawerCompat)); } } } 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] 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) { LastRemovedItem.SetTarget(item); } else { LastRemovedItem.SetTarget(null); } } [HarmonyPatch(typeof(Inventory), "MoveAll")] [HarmonyPrefix] [HarmonyPriority(800)] public static void MoveAllPrefix() { allowItemSwap = false; } [HarmonyPatch(typeof(Inventory), "MoveAll")] [HarmonyPostfix] [HarmonyPriority(0)] public static void MoveAllPostfix() { allowItemSwap = true; } [HarmonyPatch(typeof(Inventory), "Changed")] [HarmonyPostfix] public static void AddItemPostfix(Inventory __instance) { foreach (Inventory inventory in __instance.GetInventories()) { AssignItemsOfInventory(inventory); } if (LastRemovedItem.TryGetTarget(out var target) && InventoryOwner.GetOwner(target)?.Inventory == __instance) { LastRemovedItem.SetTarget(null); } } [HarmonyPatch(typeof(Inventory), "AddItem", new Type[] { typeof(ItemData), typeof(int), typeof(int), typeof(int) })] [HarmonyWrapSafe] [HarmonyTranspiler] public static IEnumerable<CodeInstruction> RemoveLogging(IEnumerable<CodeInstruction> instructions) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Expected O, but got Unknown //IL_0041: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Expected O, but got Unknown return new CodeMatcher(instructions, (ILGenerator)null).MatchForward(false, (CodeMatch[])(object)new CodeMatch[1] { new CodeMatch((Func<CodeInstruction, bool>)((CodeInstruction i) => CodeInstructionExtensions.Calls(i, AccessTools.Method(typeof(ZLog), "Log", (Type[])null, (Type[])null))), (string)null) }).SetInstruction(new CodeInstruction(OpCodes.Pop, (object)null)).Instructions(); } private static void AssignItemsOfInventory(Inventory inventory) { foreach (ItemData allItem in inventory.GetAllItems()) { InventoryOfItem.Remove(allItem); InventoryOfItem.Add(allItem, inventory); } } internal static bool InterceptAddItem(Inventory inventory, ItemData item, int amount, Vector2i pos,