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 ChestLink v1.0.0
plugins/ChestLink.dll
Decompiled 2 weeks ago
The result has been truncated due to the large size, download it to view full contents!
using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Linq; using System.Reflection; using System.Reflection.Emit; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Security.Cryptography; using System.Security.Permissions; using System.Text; using BepInEx; using BepInEx.Bootstrap; using BepInEx.Configuration; using BepInEx.Logging; using ChestLink.Compatibility; using ChestLink.Debug; using ChestLink.Networking; using ChestLink.SharedChests; using ChestLink.SharedChests.Patches; using ChestLink.Storage; using ChestLink.UI; using HarmonyLib; using Jotunn.Entities; using Jotunn.Managers; using Jotunn.Utils; using TMPro; using UnityEngine; using UnityEngine.EventSystems; using UnityEngine.Events; using UnityEngine.UI; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)] [assembly: AssemblyTitle("ChestLink")] [assembly: AssemblyDescription("Nearby Valheim chests in one linked storage view.")] [assembly: AssemblyCompany("TeamVibes")] [assembly: AssemblyProduct("ChestLink")] [assembly: ComVisible(false)] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("0.0.0.0")] namespace ChestLink { [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] [NetworkCompatibility(/*Could not decode attribute arguments.*/)] [BepInPlugin("com.chestlinkmod.valheim.chestlink", "ChestLink", "1.0.0")] public sealed class ChestLinkPlugin : BaseUnityPlugin { internal const string MucIgnoreZdoKey = "MUC_Ignore"; internal const string ExcludeZdoKey = "ChestLink_Exclude"; private Harmony _harmony; internal static ChestLinkPlugin Instance { get; private set; } internal static ManualLogSource Log { get; private set; } private void Awake() { //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Expected O, but got Unknown Instance = this; Log = ((BaseUnityPlugin)this).Logger; Settings.Init(); MultiUserChestCompat.Refresh(); ChestLinkTransactions.Initialize(); ItemClassificationExporter.Initialize(); ChestLink.SharedChests.Log.Init(Log); _harmony = new Harmony("com.chestlinkmod.valheim.chestlink"); _harmony.PatchAll(); Log.LogInfo((object)("ChestLink 1.0.0 loaded. owner-request backend=" + SharedTransfers.Backend + "; bulk coordinator=TransactionsV9; build=release-1.0.0.")); } private void OnDestroy() { StorageSessionManager.End("plugin destroyed"); Harmony harmony = _harmony; if (harmony != null) { harmony.UnpatchSelf(); } } } internal static class Settings { internal static ConfigEntry<bool> Enabled { get; private set; } internal static ConfigEntry<float> DiscoveryRadius { get; private set; } internal static ConfigEntry<int> MaxContainers { get; private set; } internal static ConfigEntry<int> MaxCombinedSlots { get; private set; } internal static ConfigEntry<bool> PreferSameBuilding { get; private set; } internal static ConfigEntry<float> StructureJoinTolerance { get; private set; } internal static ConfigEntry<float> ChestFloorAttachHeight { get; private set; } internal static ConfigEntry<float> ChestStructureAttachDistance { get; private set; } internal static ConfigEntry<bool> RequireSameBuildingRoof { get; private set; } internal static ConfigEntry<float> BuildingRoofSearchHeight { get; private set; } internal static ConfigEntry<bool> ShowContainerDividers { get; private set; } internal static ConfigEntry<bool> ShowChestLabels { get; private set; } internal static ConfigEntry<bool> ColorCodeChestBorders { get; private set; } internal static ConfigEntry<float> ChestBorderThickness { get; private set; } internal static ConfigEntry<float> FavoriteBorderOpacity { get; private set; } internal static ConfigEntry<float> ScrollRowsPerTick { get; private set; } internal static ConfigEntry<string> StorageSortCategoryOrder { get; private set; } internal static ConfigEntry<bool> DebugLogging { get; private set; } internal static void Init() { //IL_0058: Unknown result type (might be due to invalid IL or missing references) //IL_0062: Expected O, but got Unknown //IL_0093: Unknown result type (might be due to invalid IL or missing references) //IL_009d: Expected O, but got Unknown //IL_00d1: Unknown result type (might be due to invalid IL or missing references) //IL_00db: Expected O, but got Unknown //IL_0138: Unknown result type (might be due to invalid IL or missing references) //IL_0142: Expected O, but got Unknown //IL_017a: Unknown result type (might be due to invalid IL or missing references) //IL_0184: Expected O, but got Unknown //IL_01bc: Unknown result type (might be due to invalid IL or missing references) //IL_01c6: Expected O, but got Unknown //IL_0223: Unknown result type (might be due to invalid IL or missing references) //IL_022d: Expected O, but got Unknown //IL_02d4: Unknown result type (might be due to invalid IL or missing references) //IL_02de: Expected O, but got Unknown //IL_0316: Unknown result type (might be due to invalid IL or missing references) //IL_0320: Expected O, but got Unknown //IL_0358: Unknown result type (might be due to invalid IL or missing references) //IL_0362: Expected O, but got Unknown Enabled = ((BaseUnityPlugin)ChestLinkPlugin.Instance).Config.Bind<bool>("General", "Enabled", true, "Enable ChestLink."); DiscoveryRadius = ((BaseUnityPlugin)ChestLinkPlugin.Instance).Config.Bind<float>("Discovery", "Radius", 30f, new ConfigDescription("Fallback radius in meters around the chest you opened. Same-building detection takes priority when the opened chest can be assigned to a structure.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 100f), Array.Empty<object>())); MaxContainers = ((BaseUnityPlugin)ChestLinkPlugin.Instance).Config.Bind<int>("Discovery", "MaxContainers", 64, new ConfigDescription("Maximum linked containers in one session. 0 = unlimited.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 512), Array.Empty<object>())); MaxCombinedSlots = ((BaseUnityPlugin)ChestLinkPlugin.Instance).Config.Bind<int>("Discovery", "MaxCombinedSlots", 1000, new ConfigDescription("Maximum real physical chest slots exposed by one linked-storage session. 0 = unlimited.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 10000), Array.Empty<object>())); PreferSameBuilding = ((BaseUnityPlugin)ChestLinkPlugin.Instance).Config.Bind<bool>("Discovery", "PreferSameBuilding", true, "Prefer containers attached to the same physically connected structure as the opened chest. If the anchor cannot be assigned to a structure, ChestLink falls back to Radius."); StructureJoinTolerance = ((BaseUnityPlugin)ChestLinkPlugin.Instance).Config.Bind<float>("Discovery", "StructureJoinTolerance", 0.35f, new ConfigDescription("Maximum gap in meters between structural build-piece bounds for them to count as physically connected to the same building.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.05f, 1.5f), Array.Empty<object>())); ChestFloorAttachHeight = ((BaseUnityPlugin)ChestLinkPlugin.Instance).Config.Bind<float>("Discovery", "ChestFloorAttachHeight", 1.25f, new ConfigDescription("Maximum vertical distance in meters from the bottom of a chest to a structural floor directly beneath it when assigning the chest to a building.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.1f, 3f), Array.Empty<object>())); ChestStructureAttachDistance = ((BaseUnityPlugin)ChestLinkPlugin.Instance).Config.Bind<float>("Discovery", "ChestStructureAttachDistance", 0.45f, new ConfigDescription("Fallback distance in meters for attaching a chest to a nearby structural build piece when no floor attachment is found.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.05f, 2f), Array.Empty<object>())); RequireSameBuildingRoof = ((BaseUnityPlugin)ChestLinkPlugin.Instance).Config.Bind<bool>("Discovery", "RequireSameBuildingRoof", true, "When same-building discovery is active, require the chest to have a Roof-tagged piece from the same structural cluster above it. This prevents outdoor chests next to a wall/floor from joining the building."); BuildingRoofSearchHeight = ((BaseUnityPlugin)ChestLinkPlugin.Instance).Config.Bind<float>("Discovery", "BuildingRoofSearchHeight", 15f, new ConfigDescription("Maximum vertical distance in meters above a chest to search for a same-cluster Roof piece.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(2f, 30f), Array.Empty<object>())); ShowContainerDividers = ((BaseUnityPlugin)ChestLinkPlugin.Instance).Config.Bind<bool>("UI", "ShowContainerDividers", true, "Show a subtle divider between physical source chests in the future linked-storage grid."); ShowChestLabels = ((BaseUnityPlugin)ChestLinkPlugin.Instance).Config.Bind<bool>("UI", "ShowChestLabels", false, "Show a very small chest-name tag on the first visible slot of each physical chest group."); ColorCodeChestBorders = ((BaseUnityPlugin)ChestLinkPlugin.Instance).Config.Bind<bool>("UI", "ColorCodeChestBorders", true, "Color physical-chest group borders by vanilla chest material/tier. Unknown or modded containers use the nearest vanilla slot-capacity tier."); ChestBorderThickness = ((BaseUnityPlugin)ChestLinkPlugin.Instance).Config.Bind<float>("UI", "ChestBorderThickness", 2f, new ConfigDescription("Thickness of the subtle border drawn around physical chest slot groups.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 5f), Array.Empty<object>())); FavoriteBorderOpacity = ((BaseUnityPlugin)ChestLinkPlugin.Instance).Config.Bind<float>("UI", "FavoriteBorderOpacity", 0.3f, new ConfigDescription("Opacity of the dashed ITEM/SLOT favorite border. 0.30 is intentionally subtle.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.05f, 1f), Array.Empty<object>())); ScrollRowsPerTick = ((BaseUnityPlugin)ChestLinkPlugin.Instance).Config.Bind<float>("UI", "ScrollRowsPerTick", 1f, new ConfigDescription("How many linked-storage rows one mouse-wheel notch moves. 1 = exactly one row per notch.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 5f), Array.Empty<object>())); StorageSortCategoryOrder = ((BaseUnityPlugin)ChestLinkPlugin.Instance).Config.Bind<string>("Sorting", "CategoryOrder", "RawMeat,VegetablesFruit,CookedMeat,PreparedFood,OvenPrep,FoodIngredients,MeadBase,MeadPotions,Weapons,Armor,Ammo,Tools,UtilityGear,BuildingCrafting,RawMaterials,RefinedMetals,HidesLeather,Seeds,RareMaterials,MouldsCasts,Valuables,Trophies,Misc", "Physical SORT category priority. Manual item overrides live in ChestLink.SortOverrides.cfg beside the main config and always win over automatic classification."); if (StorageSortCategoryOrder.Value == "FoodMead,Ammo,Weapons,Armor,Tools,Materials,BuildingCrafting,Valuables,Trophies,Misc") { StorageSortCategoryOrder.Value = "RawMeat,VegetablesFruit,CookedMeat,PreparedFood,OvenPrep,FoodIngredients,MeadBase,MeadPotions,Weapons,Armor,Ammo,Tools,UtilityGear,BuildingCrafting,RawMaterials,RefinedMetals,HidesLeather,Seeds,RareMaterials,MouldsCasts,Valuables,Trophies,Misc"; } if (StorageSortCategoryOrder.Value == "RawMeat,VegetablesFruit,CookedMeat,PreparedFood,FoodIngredients,MeadPotions,Ammo,Weapons,Armor,Tools,BuildingCrafting,RawMaterials,RefinedMetals,HidesLeather,RareMaterials,Valuables,Trophies,Misc") { StorageSortCategoryOrder.Value = "RawMeat,VegetablesFruit,CookedMeat,PreparedFood,OvenPrep,FoodIngredients,MeadBase,MeadPotions,Weapons,Armor,Ammo,Tools,UtilityGear,BuildingCrafting,RawMaterials,RefinedMetals,HidesLeather,Seeds,RareMaterials,MouldsCasts,Valuables,Trophies,Misc"; } if (StorageSortCategoryOrder.Value == "RawMeat,VegetablesFruit,Seeds,CookedMeat,PreparedFood,OvenPrep,FoodIngredients,MeadBase,MeadPotions,Ammo,Weapons,Armor,Tools,BuildingCrafting,RawMaterials,RefinedMetals,HidesLeather,RareMaterials,MouldsCasts,Valuables,Trophies,Misc") { StorageSortCategoryOrder.Value = "RawMeat,VegetablesFruit,CookedMeat,PreparedFood,OvenPrep,FoodIngredients,MeadBase,MeadPotions,Weapons,Armor,Ammo,Tools,UtilityGear,BuildingCrafting,RawMaterials,RefinedMetals,HidesLeather,Seeds,RareMaterials,MouldsCasts,Valuables,Trophies,Misc"; } DebugLogging = ((BaseUnityPlugin)ChestLinkPlugin.Instance).Config.Bind<bool>("Debug", "Logging", false, "Log storage scans and correlated shared request registration, owner routing, quantities, replies and completion. Pending/blocked warnings are rate-limited; failures and session readiness always log."); } } public static class MyPluginInfo { public const string PLUGIN_GUID = "com.chestlinkmod.valheim.chestlink"; public const string PLUGIN_NAME = "ChestLink"; public const string PLUGIN_VERSION = "1.0.0"; } } namespace ChestLink.SharedChests { 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 static class ContainerRPCHandler { private static readonly Dictionary<string, byte[]> Replies = new Dictionary<string, byte[]>(); private static ZNet replySession; public static void RPC_RequestItemAdd(long sender, ZDOID containerId, ZPackage package) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) HandleRPC(containerId, sender, "ChestLink_Shared_RequestItemAddResponse", RequestItemAdd, new RequestChestAdd(package)); } public static void RPC_RequestItemRemove(long sender, ZDOID containerId, ZPackage package) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) HandleRPC(containerId, sender, "ChestLink_Shared_RequestItemRemoveResponse", RequestItemRemove, new RequestChestRemove(package)); } public static void RPC_RequestItemConsume(long sender, ZDOID containerId, ZPackage package) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) HandleRPC(containerId, sender, "ChestLink_Shared_RequestItemConsumeResponse", RequestItemConsume, new RequestConsume(package)); } public static void RPC_RequestItemMove(long sender, ZDOID containerId, ZPackage package) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) HandleRPC(containerId, sender, "ChestLink_Shared_RequestItemMoveResponse", RequestItemMove, new RequestMove(package)); } public static void RPC_RequestDrop(long sender, ZDOID containerId, ZPackage package) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) HandleRPC(containerId, sender, "ChestLink_Shared_RequestItemDropResponse", RequestDrop, new RequestDrop(package)); } private unsafe 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_02c3: Unknown result type (might be due to invalid IL or missing references) //IL_0410: 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) //IL_0055: Unknown result type (might be due to invalid IL or missing references) //IL_00ce: Unknown result type (might be due to invalid IL or missing references) //IL_0157: Unknown result type (might be due to invalid IL or missing references) //IL_010b: Unknown result type (might be due to invalid IL or missing references) //IL_0137: Unknown result type (might be due to invalid IL or missing references) //IL_0141: Unknown result type (might be due to invalid IL or missing references) //IL_0147: Expected O, but got Unknown //IL_0439: Unknown result type (might be due to invalid IL or missing references) //IL_047f: Unknown result type (might be due to invalid IL or missing references) //IL_048a: Unknown result type (might be due to invalid IL or missing references) //IL_0490: Expected O, but got Unknown if ((Object)(object)replySession != (Object)(object)ZNet.instance) { Replies.Clear(); replySession = ZNet.instance; } IRequest request = input as IRequest; string[] obj = new string[7] { target.ToString(), ":", null, null, null, null, null }; ZDOID val = containerId; obj[2] = ((object)(*(ZDOID*)(&val))/*cast due to .constrained prefix*/).ToString(); obj[3] = ":"; obj[4] = rpcInvoke; obj[5] = ":"; obj[6] = (request?.RequestID).ToString(); string key = string.Concat(obj); if (request == null || request.RequestID <= 0) { return; } PackageHandler.Trace(request, "owner-receive", containerId, ZDOMan.GetSessionID(), "requester=" + target + " rpc=" + rpcInvoke); if (Replies.TryGetValue(key, out var value)) { PackageHandler.Trace(request, "owner-replay", containerId, ZDOMan.GetSessionID(), "requester=" + target); ZRoutedRpc.instance.InvokeRoutedRPC(target, rpcInvoke, new object[2] { containerId, (object)new ZPackage(value) }); return; } ZDO zDO = ZDOMan.instance.GetZDO(containerId); ZNetView val2 = ((zDO != null) ? ZNetScene.instance.FindInstance(zDO) : null); bool flag = false; TResponse val3; if (!Object.op_Implicit((Object)(object)val2) || !val2.IsOwner()) { if (!Object.op_Implicit((Object)(object)val2)) { Log.LogWarning(input.GetType().Name + ": not handling RPC, ZNetView instance is null"); } else if (!val2.IsOwner()) { Log.LogWarning(input.GetType().Name + ": not handling RPC, ZNetView instance is not owner"); } val3 = FallbackResponse<TResponse>(input as IRequest); } else { Container componentInChildren = ((Component)val2).GetComponentInChildren<Container>(); if (Object.op_Implicit((Object)(object)componentInChildren)) { try { if (!ChestState.Refresh(componentInChildren, "owner-request:" + request.RequestID)) { throw new InvalidOperationException("Chest awaiting synchronization"); } ChestLinkTransactions.BeginSharedEvidence(PackageHandler.JournalId(target, request.RequestID), componentInChildren, requester: false); flag = true; } catch (Exception ex) { Log.LogError($"[Shared] owner-preflight-rejected utc={DateTime.UtcNow:O} peer={ZDOMan.GetSessionID()} requester={target} request={request.RequestID} chest={containerId} noChestMutation=true: {ex}"); } val3 = (flag ? Execute(componentInChildren.GetInventory(), input, message) : FallbackResponse<TResponse>(request)); if (flag) { ChestState.VerifyPersisted(componentInChildren, "owner-reply:" + request.RequestID); } } else { Log.LogWarning(input.GetType().Name + ": not handling RPC, Container component not found on " + ((Object)val2).name); val3 = FallbackResponse<TResponse>(input as IRequest); } } input.PrintDebug(); val3.PrintDebug(); val3.SourceID = request.RequestID; byte[] array = val3.WriteToPackage().GetArray(); Replies[key] = array; if (flag) { try { ChestLinkTransactions.SharedReplyEvidence(PackageHandler.JournalId(target, request.RequestID), array); } catch (Exception ex2) { Log.LogError($"[Shared] reply-evidence-failed request={request.RequestID} chest={containerId} requester={target}; outcome retained in memory, journal preserved: {ex2}"); return; } } PackageHandler.Trace(request, "owner-reply", containerId, ZDOMan.GetSessionID(), $"requester={target} success={val3.Success} bytes={array.Length}"); ZRoutedRpc.instance.InvokeRoutedRPC(target, rpcInvoke, new object[2] { containerId, (object)new ZPackage(array) }); } public unsafe static void ReceiptAck(long sender, ZDOID chest, int requestId) { //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_006e: Unknown result type (might be due to invalid IL or missing references) if (Settings.DebugLogging.Value) { Log.LogInfo($"[Shared] receipt-ack utc={DateTime.UtcNow:O} peer={ZDOMan.GetSessionID()} requester={sender} request={requestId} chest={chest}"); } if (Replies.Keys.Any(delegate(string k) { //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Unknown result type (might be due to invalid IL or missing references) string text = sender.ToString(); ZDOID val = chest; return k.StartsWith(text + ":" + ((object)(*(ZDOID*)(&val))/*cast due to .constrained prefix*/).ToString() + ":", StringComparison.Ordinal) && k.EndsWith(":" + requestId, StringComparison.Ordinal); })) { ChestLinkTransactions.FinishSharedEvidence(PackageHandler.JournalId(sender, requestId)); } } internal static TResponse Execute<TResponse, TInput>(Inventory inventory, TInput input, Func<Inventory, TInput, TResponse> action) where TResponse : IResponse, new() where TInput : IPackage { //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Expected O, but got Unknown //IL_0082: Unknown result type (might be due to invalid IL or missing references) //IL_0087: Unknown result type (might be due to invalid IL or missing references) //IL_0160: Unknown result type (might be due to invalid IL or missing references) //IL_0165: Unknown result type (might be due to invalid IL or missing references) int num = inventory.GetAllItems().Sum((ItemData x) => x.m_stack); Inventory val = new Inventory("ChestLink transit", (Sprite)null, 1, 1); ItemData val2 = ((input is RequestChestAdd requestChestAdd) ? requestChestAdd.dragItem : ((input is RequestChestRemove requestChestRemove) ? requestChestRemove.switchItem : null)); if (val2 != null) { ItemData val3 = val2.Clone(); val3.m_gridPos = Vector2i.zero; NetworkInventoryCommit.Items(val).Add(val3); } try { using NetworkInventoryCommit networkInventoryCommit = new NetworkInventoryCommit((IEnumerable<Inventory>)(object)new Inventory[2] { inventory, val }, "owner-request"); NetworkInventoryCommit.Items(val).Clear(); TResponse val4 = action(inventory, input); ItemData val5 = ((val4 is RequestChestAddResponse requestChestAddResponse) ? requestChestAddResponse.switchItem : ((val4 is RequestChestRemoveResponse requestChestRemoveResponse) ? requestChestRemoveResponse.responseItem : ((val4 is RequestConsumeResponse requestConsumeResponse) ? requestConsumeResponse.item : ((val4 is RequestDropResponse requestDropResponse) ? requestDropResponse.responseItem : null)))); if (val5 != null && val5.m_stack > 0) { ItemData val6 = val5.Clone(); val6.m_gridPos = Vector2i.zero; NetworkInventoryCommit.Items(val).Add(val6); } networkInventoryCommit.Validate("owner-request"); val4.WriteToPackage(); NetworkInventoryCommit.Serialize(inventory); networkInventoryCommit.Accept(); if (Settings.DebugLogging.Value) { Log.LogInfo(string.Format("[Shared] owner-executed utc={0:O} peer={1} request={2} type={3} success={4} chestBefore={5} chestAfter={6} returned={7} returnedCount={8}", DateTime.UtcNow, ZDOMan.GetSessionID(), (input as IRequest)?.RequestID, input.GetType().Name, val4.Success, num, inventory.GetAllItems().Sum((ItemData x) => x.m_stack), val5?.m_shared.m_name ?? "none", val5?.m_stack ?? 0)); } return val4; } catch (Exception ex) { Log.LogError($"[Shared] owner-rollback peer={ZDOMan.GetSessionID()} request={(input as IRequest)?.RequestID} type={input.GetType().Name}: {ex}"); return FallbackResponse<TResponse>(input as IRequest); } } private static TResponse FallbackResponse<TResponse>(IRequest request) where TResponse : IResponse, new() { //IL_0065: Unknown result type (might be due to invalid IL or missing references) //IL_005e: Unknown result type (might be due to invalid IL or missing references) //IL_006a: 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 && val is RequestChestAddResponse requestChestAddResponse) { requestChestAddResponse.switchItem = requestChestAdd.dragItem; requestChestAddResponse.inventoryPos = requestChestAdd.dragItem?.m_gridPos ?? Vector2i.zero; } else if (request is RequestChestRemove requestChestRemove && val is RequestChestRemoveResponse requestChestRemoveResponse) { requestChestRemoveResponse.responseItem = requestChestRemove.switchItem; } return val; } public static RequestChestAddResponse RequestItemAdd(this Inventory inventory, RequestChestAdd request) { //IL_0016: 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_0046: 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_00c2: 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) //IL_00af: 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_0042: Unknown result type (might be due to invalid IL or missing references) //IL_0089: Unknown result type (might be due to invalid IL or missing references) //IL_00d0: Unknown result type (might be due to invalid IL or missing references) //IL_00d5: 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: Unknown result type (might be due to invalid IL or missing references) //IL_0132: Unknown result type (might be due to invalid IL or missing references) //IL_01b2: Unknown result type (might be due to invalid IL or missing references) int num = request.dragItem.m_stack; List<Vector2i> list = new List<Vector2i>(); foreach (ItemData allItem in inventory.GetAllItems()) { if (InventoryHelper.CanStack(allItem, request.dragItem)) { list.Add(allItem.m_gridPos); } } for (int i = 0; i < inventory.GetHeight(); i++) { for (int j = 0; j < inventory.GetWidth(); j++) { if (inventory.GetItemAt(j, i) == null) { list.Add(new Vector2i(j, i)); } } } foreach (Vector2i item in list) { ItemData itemAt = inventory.GetItemAt(item.x, item.y); int val = ((itemAt == null) ? request.dragItem.m_shared.m_maxStackSize : (itemAt.m_shared.m_maxStackSize - itemAt.m_stack)); int num2 = Math.Min(num, val); if (num2 > 0 && inventory.AddItemToInventory(request.dragItem, num2, item)) { num -= num2; } if (num == 0) { break; } } ItemData val2 = ((num == 0) ? null : request.dragItem.Clone()); if (val2 != null) { val2.m_stack = num; } int num3 = request.dragItem.m_stack - num; return new RequestChestAddResponse(request.RequestID, num3 > 0, request.dragItem.m_gridPos, num3, val2); } public static RequestChestRemoveResponse RequestItemRemove(this Inventory inventory, RequestChestRemove request) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_012a: 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 || request.dragAmount <= 0 || request.item == null || NetworkInventoryCommit.Identity(itemAt) != NetworkInventoryCommit.Identity(request.item)) { Log.LogDebug("from is null"); return new RequestChestRemoveResponse(request.RequestID, success: false, 0, hasSwitched: false, request.switchItem); } 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 || request.expected == null || NetworkInventoryCommit.Identity(itemAt) != NetworkInventoryCommit.Identity(request.expected)) { 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_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0009: Unknown result type (might be due to invalid IL or missing references) //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_0017: 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_008a: 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 (request.dragAmount <= 0 || request.item == null || NetworkInventoryCommit.Identity(itemAt) != NetworkInventoryCommit.Identity(request.item)) { 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_0052: 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) //IL_008a: 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 || request.amount <= 0 || request.expected == null || NetworkInventoryCommit.Identity(itemAt) != NetworkInventoryCommit.Identity(request.expected)) { 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 static class PackageHandler { private static readonly Dictionary<int, IPackage> Packages = new Dictionary<int, IPackage>(); private static int nextId; private static readonly Dictionary<int, DateTime> Started = new Dictionary<int, DateTime>(); private static readonly Dictionary<int, string> Context = new Dictionary<int, string>(); private static int total; internal unsafe static void Trace(IRequest request, string phase, ZDOID chest, long owner, string detail = "") { //IL_0139: Unknown result type (might be due to invalid IL or missing references) //IL_013e: Unknown result type (might be due to invalid IL or missing references) //IL_0193: Unknown result type (might be due to invalid IL or missing references) //IL_0121: Unknown result type (might be due to invalid IL or missing references) //IL_0126: Unknown result type (might be due to invalid IL or missing references) //IL_0109: Unknown result type (might be due to invalid IL or missing references) //IL_010e: Unknown result type (might be due to invalid IL or missing references) ItemData val = ((request is RequestChestAdd requestChestAdd) ? requestChestAdd.dragItem : ((request is RequestChestRemove requestChestRemove) ? requestChestRemove.item : ((request is RequestMove requestMove) ? requestMove.item : ((request is RequestConsume requestConsume) ? requestConsume.expected : ((request is RequestDrop requestDrop) ? requestDrop.expected : null))))); int num = ((!(request is RequestChestAdd requestChestAdd2)) ? ((request is RequestChestRemove requestChestRemove2) ? requestChestRemove2.dragAmount : ((request is RequestMove requestMove2) ? requestMove2.dragAmount : ((request is RequestConsume) ? 1 : ((request is RequestDrop requestDrop2) ? requestDrop2.amount : (val?.m_stack ?? 0))))) : (requestChestAdd2.dragItem?.m_stack ?? 0)); string text = ((request is RequestChestAdd { toPos: var toPos }) ? ((object)(*(Vector2i*)(&toPos))/*cast due to .constrained prefix*/).ToString() : ((request is RequestChestRemove { toPos: var toPos2 }) ? ((object)(*(Vector2i*)(&toPos2))/*cast due to .constrained prefix*/).ToString() : ((request is RequestMove { toPos: var toPos3 }) ? ((object)(*(Vector2i*)(&toPos3))/*cast due to .constrained prefix*/).ToString() : "none"))); string text2 = string.Format("utc={0:O} peer={1} request={2} type={3} chest={4} owner={5} item={6} amount={7} to={8} slot={9} {10}", DateTime.UtcNow, ZDOMan.GetSessionID(), request.RequestID, request.GetType().Name, chest, owner, val?.m_shared.m_name ?? "none", num, text, ((object)Unsafe.As<Vector2i, Vector2i>(ref val?.m_gridPos)/*cast due to .constrained prefix*/).ToString() ?? "none", detail); if (phase == "registered" || phase == "send") { Context[request.RequestID] = text2; } if (Settings.DebugLogging.Value) { Log.LogInfo("[Shared] " + phase + " " + text2); } } internal static string PendingSummary() { DateTime value; string value2; return string.Join(" | ", Packages.Select((KeyValuePair<int, IPackage> p) => $"id={p.Key} age={(Started.TryGetValue(p.Key, out value) ? (DateTime.UtcNow - value).TotalSeconds : (-1.0)):0.0}s {(Context.TryGetValue(p.Key, out value2) ? value2 : p.Value.GetType().Name)}")); } public static int AddPackage(IPackage package) { //IL_0125: Unknown result type (might be due to invalid IL or missing references) //IL_0143: Unknown result type (might be due to invalid IL or missing references) //IL_013a: Unknown result type (might be due to invalid IL or missing references) int randomId = GetRandomId(); if (package is IRequest request) { request.RequestID = randomId; Container chest = (InventoryOwner.GetOwner(request.SourceInventory) as ContainerInventoryOwner)?.Container ?? (InventoryOwner.GetOwner(request.TargetInventory) as ContainerInventoryOwner)?.Container; ChestLinkTransactions.BeginSharedEvidence(JournalId(ZDOMan.GetSessionID(), randomId), chest, requester: true); } Packages.Add(randomId, package); Started[randomId] = DateTime.UtcNow; if (package is IRequest request2) { Container val = (InventoryOwner.GetOwner(request2.SourceInventory) as ContainerInventoryOwner)?.Container ?? (InventoryOwner.GetOwner(request2.TargetInventory) as ContainerInventoryOwner)?.Container; ZDOID? obj; if (val == null) { obj = null; } else { ZNetView nview = val.m_nview; obj = ((nview == null) ? ((ZDOID?)null) : nview.GetZDO()?.m_uid); } ? chest2 = ((??)obj) ?? ZDOID.None; long? obj2; if (val == null) { obj2 = null; } else { ZNetView nview2 = val.m_nview; if (nview2 == null) { obj2 = null; } else { ZDO zDO = nview2.GetZDO(); obj2 = ((zDO != null) ? new long?(zDO.GetOwner()) : ((long?)null)); } } long? num = obj2; Trace(request2, "registered", (ZDOID)chest2, num.GetValueOrDefault()); } Log.LogDebug($"PackageHandler: Added package {randomId}, total packages: {++total}"); return randomId; } public static void RemovePackage(int id) { if (Settings.DebugLogging.Value && Packages.ContainsKey(id)) { Log.LogInfo($"[Shared] completed utc={DateTime.UtcNow:O} peer={ZDOMan.GetSessionID()} request={id} elapsedMs={(Started.TryGetValue(id, out var value) ? (DateTime.UtcNow - value).TotalMilliseconds : (-1.0)):0}"); } Packages.Remove(id); Started.Remove(id); Context.Remove(id); Log.LogDebug($"PackageHandler: Removed package {id}, total packages: {--total}"); } private static int GetRandomId() { if (nextId == int.MaxValue) { throw new InvalidOperationException("Shared request ID limit reached; reconnect."); } return ++nextId; } internal static string JournalId(long peer, int id) { return peer + ":shared:" + id; } internal static void CompleteJournal(int id) { ChestLinkTransactions.FinishSharedEvidence(JournalId(ZDOMan.GetSessionID(), id)); } 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); } } public static class ContainerHandler { public static RequestChestAdd AddItemToChest(this Container container, ItemData item, Inventory sourceInventory, Vector2i to, ZDOID sender, int dragAmount = -1) { //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_0067: Unknown result type (might be due to invalid IL or missing references) //IL_0077: Unknown result type (might be due to invalid IL or missing references) //IL_007d: Unknown result type (might be due to invalid IL or missing references) //IL_00d9: Unknown result type (might be due to invalid IL or missing references) //IL_00f8: Unknown result type (might be due to invalid IL or missing references) //IL_00c4: Unknown result type (might be due to invalid IL or missing references) 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); } if (!ChestState.Refresh(container, "deposit-preflight")) { throw new InvalidOperationException("Chest is awaiting synchronization"); } 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()); InventoryPreview.AddPackage(requestChestAdd); InventoryBlock.Get(sourceInventory).BlockSlot(item.m_gridPos); sourceInventory.RemoveItem(item, dragAmount); if (container.m_nview.IsOwner()) { RequestChestAddResponse response = ContainerRPCHandler.Execute(container.GetInventory(), requestChestAdd, ContainerRPCHandler.RequestItemAdd); ChestState.VerifyPersisted(container, "local-deposit:" + requestChestAdd.RequestID); InventoryHandler.RPC_RequestItemAddResponse(sourceInventory, response); PackageHandler.CompleteJournal(requestChestAdd.RequestID); return null; } GamePatches.InvokeRPC(container.m_nview, "ChestLink_Shared_RequestItemAdd", requestChestAdd); return requestChestAdd; } internal static int PossibleDragAmount(Inventory inventoryTo, ItemData dragItem, Vector2i to, int dragAmount) { //IL_0025: 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_0043: Unknown result type (might be due to invalid IL or missing references) //IL_0049: Unknown result type (might be due to invalid IL or missing references) 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_002c: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_0085: 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_00c9: Unknown result type (might be due to invalid IL or missing references) //IL_00ce: 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) //IL_00af: Unknown result type (might be due to invalid IL or missing references) //IL_0140: Unknown result type (might be due to invalid IL or missing references) //IL_0112: 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) 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); } if (!ChestState.Refresh(container, "withdraw-preflight")) { throw new InvalidOperationException("Chest is awaiting synchronization"); } if (!container.GetInventory().ContainsItem(item)) { return null; } 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) && dragAmount != item.m_stack) { return new RequestChestRemove(Vector2i.zero, Vector2i.zero, 0, null, container.GetInventory(), destinationInventory); } InventoryPreview.AddPackage(requestChestRemove); InventoryBlock.Get(destinationInventory).BlockSlot(requestChestRemove.toPos); if (switchItem != null && !InventoryHelper.CanStack(item, switchItem)) { destinationInventory.RemoveItem(switchItem); } if (container.m_nview.IsOwner()) { RequestChestRemoveResponse response = ContainerRPCHandler.Execute(container.GetInventory(), requestChestRemove, ContainerRPCHandler.RequestItemRemove); ChestState.VerifyPersisted(container, "local-withdraw:" + requestChestRemove.RequestID); InventoryHandler.RPC_RequestItemRemoveResponse(destinationInventory, response); PackageHandler.CompleteJournal(requestChestRemove.RequestID); return null; } GamePatches.InvokeRPC(container.m_nview, "ChestLink_Shared_RequestItemRemove", requestChestRemove); return requestChestRemove; } public static void MoveItemInChest(this Container container, ItemData item, Vector2i toPos, int dragAmount) { //IL_0002: 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, "ChestLink_Shared_RequestItemMove", package); } } 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) { return i.opcode == OpCodes.Callvirt && i.operand is MethodInfo methodInfo && methodInfo.DeclaringType?.Name == declaringType && methodInfo.Name == name; } } public abstract class InventoryOwner { public abstract ZNetView ZNetView { get; } public abstract Inventory Inventory { get; } public virtual bool IsValid() { return Object.op_Implicit((Object)(object)ZNetView) && ZNetView.HasOwner() && Inventory != null; } 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 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_0001: 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_0046: 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_0029: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0032: 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_0001: 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_002d: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_0030: 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_0047: Unknown result type (might be due to invalid IL or missing references) //IL_0060: Unknown result type (might be due to invalid IL or missing references) 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_0017: Unknown result type (might be due to invalid IL or missing references) return BlockConsume || BlockAllSlots || BlockedSlots.ContainsKey(slot); } public bool IsAnySlotBlocked() { return BlockConsume || BlockAllSlots || BlockedSlots.Count > 0; } private static bool CanBlockSlot(Vector2i slot) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_000a: Unknown result type (might be due to invalid IL or missing references) return slot.x >= 0 && slot.y >= 0; } } public static class InventoryHandler { public static void RPC_RequestItemAddResponse(long sender, ZDOID containerId, ZPackage package) { //IL_0046: Unknown result type (might be due to invalid IL or missing references) //IL_00db: Unknown result type (might be due to invalid IL or missing references) RequestChestAddResponse requestChestAddResponse = new RequestChestAddResponse(package); if (Settings.DebugLogging.Value) { Log.LogInfo($"[Shared] reply-receive utc={DateTime.UtcNow:O} peer={ZDOMan.GetSessionID()} sender={sender} chest={containerId} request={requestChestAddResponse.SourceID} type=RequestChestAddResponse success={requestChestAddResponse.Success} pending={PackageHandler.GetPackage<IPackage>(requestChestAddResponse.SourceID) != null}"); } HandleRPC(requestChestAddResponse, (RequestChestAddResponse p) => GetSourceInventory(p.SourceID), RPC_RequestItemAddResponse); PackageHandler.CompleteJournal(requestChestAddResponse.SourceID); ZRoutedRpc.instance.InvokeRoutedRPC(sender, "ChestLink_Shared_ReceiptAck", new object[2] { containerId, requestChestAddResponse.SourceID }); } public static void RPC_RequestItemRemoveResponse(long sender, ZDOID containerId, ZPackage package) { //IL_0046: Unknown result type (might be due to invalid IL or missing references) //IL_00db: Unknown result type (might be due to invalid IL or missing references) RequestChestRemoveResponse requestChestRemoveResponse = new RequestChestRemoveResponse(package); if (Settings.DebugLogging.Value) { Log.LogInfo($"[Shared] reply-receive utc={DateTime.UtcNow:O} peer={ZDOMan.GetSessionID()} sender={sender} chest={containerId} request={requestChestRemoveResponse.SourceID} type=RequestChestRemoveResponse success={requestChestRemoveResponse.Success} pending={PackageHandler.GetPackage<IPackage>(requestChestRemoveResponse.SourceID) != null}"); } HandleRPC(requestChestRemoveResponse, (RequestChestRemoveResponse p) => GetTargetInventory(p.SourceID), RPC_RequestItemRemoveResponse); PackageHandler.CompleteJournal(requestChestRemoveResponse.SourceID); ZRoutedRpc.instance.InvokeRoutedRPC(sender, "ChestLink_Shared_ReceiptAck", new object[2] { containerId, requestChestRemoveResponse.SourceID }); } public static void RPC_RequestDropResponse(long sender, ZDOID containerId, ZPackage package) { //IL_00bc: 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) RequestDropResponse requestDropResponse = new RequestDropResponse(package); if (Settings.DebugLogging.Value) { Log.LogInfo($"[Shared] reply-receive utc={DateTime.UtcNow:O} peer={ZDOMan.GetSessionID()} sender={sender} chest={containerId} request={requestDropResponse.SourceID} type=RequestDropResponse success={requestDropResponse.Success} pending={PackageHandler.GetPackage<IPackage>(requestDropResponse.SourceID) != null}"); } HandleRPC(requestDropResponse, RPC_RequestDropResponse); PackageHandler.CompleteJournal(requestDropResponse.SourceID); ZRoutedRpc.instance.InvokeRoutedRPC(sender, "ChestLink_Shared_ReceiptAck", new object[2] { containerId, requestDropResponse.SourceID }); } public static void RPC_RequestItemConsumeResponse(long sender, ZDOID containerId, ZPackage package) { //IL_00bc: 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) RequestConsumeResponse requestConsumeResponse = new RequestConsumeResponse(package); if (Settings.DebugLogging.Value) { Log.LogInfo($"[Shared] reply-receive utc={DateTime.UtcNow:O} peer={ZDOMan.GetSessionID()} sender={sender} chest={containerId} request={requestConsumeResponse.SourceID} type=RequestConsumeResponse success={requestConsumeResponse.Success} pending={PackageHandler.GetPackage<IPackage>(requestConsumeResponse.SourceID) != null}"); } HandleRPC(requestConsumeResponse, RPC_RequestItemConsumeResponse); PackageHandler.CompleteJournal(requestConsumeResponse.SourceID); ZRoutedRpc.instance.InvokeRoutedRPC(sender, "ChestLink_Shared_ReceiptAck", new object[2] { containerId, requestConsumeResponse.SourceID }); } public static void RPC_RequestItemMoveResponse(long sender, ZDOID containerId, ZPackage package) { //IL_00bc: 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) RequestMoveResponse requestMoveResponse = new RequestMoveResponse(package); if (Settings.DebugLogging.Value) { Log.LogInfo($"[Shared] reply-receive utc={DateTime.UtcNow:O} peer={ZDOMan.GetSessionID()} sender={sender} chest={containerId} request={requestMoveResponse.SourceID} type=RequestMoveResponse success={requestMoveResponse.Success} pending={PackageHandler.GetPackage<IPackage>(requestMoveResponse.SourceID) != null}"); } HandleRPC(requestMoveResponse, RPC_RequestItemMoveResponse); PackageHandler.CompleteJournal(requestMoveResponse.SourceID); ZRoutedRpc.instance.InvokeRoutedRPC(sender, "ChestLink_Shared_ReceiptAck", new object[2] { containerId, requestMoveResponse.SourceID }); } 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) { Timer.Stop(timerName); package.PrintDebug(); if (!(package is IResponse response) || PackageHandler.GetPackage<IPackage>(response.SourceID) != null) { action?.Invoke(); } } public static void RPC_RequestItemRemoveResponse(Inventory inventory, RequestChestRemoveResponse response) { //IL_0029: 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_0035: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Unknown result type (might be due to invalid IL or missing references) //IL_0054: Unknown result type (might be due to invalid IL or missing references) //IL_0078: Unknown result type (might be due to invalid IL or missing references) //IL_0121: Unknown result type (might be due to invalid IL or missing references) //IL_0128: Expected O, but got Unknown //IL_0093: 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) if (PackageHandler.GetPackage<IPackage>(response.SourceID) == null || inventory == null) { return; } 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_0040: Unknown result type (might be due to invalid IL or missing references) if (PackageHandler.GetPackage<IPackage>(response.SourceID) != null) { PackageHandler.RemovePackage(response.SourceID); DropItem(response.responseItem, response.responseItem?.m_stack ?? 0); UpdateGUIAfterPlayerMove(response.sender); } } private static void UpdateGUIAfterPlayerMove(ZDOID sender) { //IL_0019: 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) 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_000b: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_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_0021: 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_0040: Unknown result type (might be due to invalid IL or missing references) //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_004a: 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) //IL_0077: Unknown result type (might be due to invalid IL or missing references) //IL_007c: Unknown result type (might be due to invalid IL or missing references) //IL_008a: Unknown result type (might be due to invalid IL or missing references) //IL_0090: Unknown result type (might be due to invalid IL or missing references) 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>().linearVelocity = (transform.forward + Vector3.up) * 5f; ((Character)player).m_zanim.SetTrigger("interact"); ((Humanoid)player).m_dropEffects.Create(transform.position, Quaternion.identity, (Transform)null, 1f, -1, default(ZDOID)); ItemData itemData = val.m_itemData; ((Character)player).Message((MessageType)1, "$msg_dropped " + itemData.m_shared.m_name, itemData.m_stack, itemData.GetIcon(), false); } public static void RPC_RequestItemAddResponse(Inventory inventory, RequestChestAddResponse response) { //IL_001c: 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_002f: 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) if (PackageHandler.GetPackage<IPackage>(response.SourceID) != null && inventory != null) { 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) { if (PackageHandler.GetPackage<IPackage>(response.SourceID) == null) { return; } PackageHandler.RemovePackage(response.SourceID); Player localPlayer = Player.m_localPlayer; InventoryBlock.Get(((Humanoid)localPlayer).GetInventory()).BlockConsume = false; if (response.item == null) { return; } if (!((Humanoid)localPlayer).CanConsumeItem(response.item, false)) { SharedTransfers.ReturnUnused(response.item); return; } 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, (short)(-1)); } 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 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 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 (inventory == null) { return; } 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 { ((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_012d: Unknown result type (might be due to invalid IL or missing references) //IL_0132: Unknown result type (might be due to invalid IL or missing references) //IL_0136: Unknown result type (might be due to invalid IL or missing references) //IL_013b: Unknown result type (might be due to invalid IL or missing references) //IL_01c4: Unknown result type (might be due to invalid IL or missing references) //IL_0150: Unknown result type (might be due to invalid IL or missing references) //IL_0168: Unknown result type (might be due to invalid IL or missing references) //IL_018b: Unknown result type (might be due to invalid IL or missing references) //IL_00c9: Unknown result type (might be due to invalid IL or missing references) //IL_00ec: Unknown result type (might be due to invalid IL or missing references) //IL_00fd: Unknown result type (might be due to invalid IL or missing references) //IL_0334: Unknown result type (might be due to invalid IL or missing references) //IL_034c: Unknown result type (might be due to invalid IL or missing references) //IL_0287: Unknown result type (might be due to invalid IL or missing references) //IL_02a4: Unknown result type (might be due to invalid IL or missing references) //IL_02bc: Unknown result type (might be due to invalid IL or missing references) //IL_02d4: 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 { fromPos: var fromPos, toPos: var toPos } requestChestRemove) { 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())) : ((int?)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 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 interface IRequest : IPackage { int RequestID { get; set; } Inventory SourceInventory { get; } Inventory TargetInventory { get; } } public class RequestConsume : IRequest, IPackage { public ItemData expected; public readonly int itemPosX; public readonly int itemPosY; public int RequestID { get; set; } public Inventory SourceInventory { get; set; } public Inventory TargetInventory { get; set; } public RequestConsume(ItemData item) { expected = item.Clone(); itemPosX = item.m_gridPos.x; itemPosY = item.m_gridPos.y; } public RequestConsume(ZPackage package) { RequestID = package.ReadInt(); expected = InventoryHelper.LoadItemFromPackage(package); itemPosX = package.ReadInt(); itemPosY = package.ReadInt(); } public ZPackage WriteToPackage() { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Expected O, but got Unknown ZPackage val = new ZPackage(); val.Write(RequestID); InventoryHelper.WriteItemToPackage(expected, val); val.Write(itemPosX); val.Write(itemPosY); return val; } public void PrintDebug() { Log.LogDebug("RequestConsume:"); Log.LogDebug($" itemPosX: {itemPosX}"); Log.LogDebug($" itemPosY: {itemPosY}"); } } public class RequestDrop : IRequest, IPackage { public ItemData expected; public readonly Vector2i targetContainerSlot; public readonly int amount; public readonly ZDOID sender; public int RequestID { get; set; } public Inventory SourceInventory { get; set; } public Inventory TargetInventory { get; set; } public RequestDrop(Vector2i targetContainerSlot, int amount, ZDOID sender) { //IL_0009: Unknown result type (might be due to invalid IL or missing references) //IL_000a: 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_0018: 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_0023: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_0040: Unknown result type (might be due to invalid IL or missing references) RequestID = package.ReadInt(); expected = InventoryHelper.LoadItemFromPackage(package); targetContainerSlot = package.ReadVector2i(); amount = package.ReadInt(); sender = package.ReadZDOID(); } public ZPackage WriteToPackage() { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Expected O, but got Unknown //IL_0023: 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) ZPackage val = new ZPackage(); val.Write(RequestID); InventoryHelper.WriteItemToPackage(expected, val); val.Write(targetContainerSlot); val.Write(amount); val.Write(sender); return val; } public void PrintDebug() { //IL_0012: 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) Log.LogDebug("RequestDrop:"); Log.LogDebug($" targetContainerSlot: {targetContainerSlot}"); Log.LogDebug($" amount: {amount}"); Log.LogDebug($" sender: {sender}"); } } 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) { SourceID = package.ReadInt(); 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_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Expected O, but got Unknown ZPackage val = new ZPackage(); val.Write(SourceID); InventoryHelper.WriteItemToPackage(item, val); val.Write(Success); val.Write(Amount); return val; } public void PrintDebug() { Log.LogDebug("RequestConsumeResponse:"); Log.LogDebug($" id: {SourceID}"); Log.LogDebug($" success: {Success}"); Log.LogDebug($" amount: {Amount}"); InventoryHelper.PrintItem("item", item); } } 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_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.responseItem = responseItem.ClampStackSize(); this.sender = sender; Success = success; Amount = amount; } public RequestDropResponse(ZPackage package) { //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) SourceID = package.ReadInt(); responseItem = InventoryHelper.LoadItemFromPackage(package); sender = package.ReadZDOID(); Success = package.ReadBool(); Amount = package.ReadInt(); } public RequestDropResponse() { responseItem = null; } public ZPackage WriteToPackage() { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Expected O, but got Unknown //IL_0023: Unknown result type (might be due to invalid IL or missing references) ZPackage val = new ZPackage(); val.Write(SourceID); InventoryHelper.WriteItemToPackage(responseItem, val); val.Write(sender); val.Write(Success); val.Write(Amount); return val; } public void PrintDebug() { //IL_0048: Unknown result type (might be due to invalid IL or missing references) Log.LogDebug("RequestDropResponse:"); Log.LogDebug($" Success: {Success}"); Log.LogDebug($" Amount: {Amount}"); Log.LogDebug($" sender: {sender}"); InventoryHelper.PrintItem("responseItem", responseItem); } } 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_0009: Unknown result type (might be due to invalid IL or missing references) //IL_000a: 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_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) RequestID = package.ReadInt(); toPos = package.ReadVector2i(); dragItem = InventoryHelper.LoadItemFromPackage(package); allowSwitch = package.ReadBool(); } public ZPackage WriteToPackage() { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Expected O, but got Unknown //IL_0016: 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 void PrintDebug() { //IL_002d: Unknown result type (might be due to invalid IL or missing references) Log.LogDebug("RequestItemAdd:"); Log.LogDebug($" id: {RequestID}"); Log.LogDebug($" toContainer: {toPos}"); Log.LogDebug($" allowSwitch: {allowSwitch}"); InventoryHelper.PrintItem("dragItem", dragItem); } } 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_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0007: 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 void PrintDebug() { Log.LogDebug("RequestRemoveResponse:"); Log.LogDebug($" id: {SourceID}"); Log.LogDebug($" success: {Success}"); Log.LogDebug($" amount: {Amount}"); Log.LogDebug($" hasSwitched: {hasSwitched}"); InventoryHelper.PrintItem("responseItem", responseItem); } } 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_0009: Unknown result type (might be due to invalid IL or missing references) //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_0011: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Unknown result type (might be due to invalid IL or missing references) //IL_0051: Unknown result type (might be due to invalid IL or missing references) 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_0017: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_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) RequestID = package.ReadInt(); fromPos = package.ReadVector2i(); toPos = package.ReadVector2i(); dragAmount = package.ReadInt(); switchItem = InventoryHelper.LoadItemFromPackage(package); item = InventoryHelper.LoadItemFromPackage(package); } public ZPackage WriteToPackage() { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Expected O, but got Unknown //IL_0016: 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) ZPackage val = new ZPackage(); val.Write(RequestID); val.Write(fromPos); val.Write(toPos); val.Write(dragAmount); InventoryHelper.WriteItemToPackage(switchItem, val); InventoryHelper.WriteItemToPackage(item, val); return val; } public void PrintDebug() { //IL_002d: 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) Log.LogDebug("RequestItemRemove:"); Log.LogDebug($" id: {RequestID}"); Log.LogDebug($" fromContainer: {fromPos}"); Log.LogDebug($" toInventory: {toPos}"); Log.LogDebug($" dragAmount: {dragAmount}"); InventoryHelper.PrintItem("switchItem", switchItem); } } public interface IResponse : IPackage { int SourceID { get; set; } bool Success { get; set; } int Amount { get; set; } } 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_0058: Unknown result type (might be due to invalid IL or missing references) //IL_005d: Unknown result type (might be due to invalid IL or missing references) //IL_0063: Unknown result type (might be due to invalid IL or missing references) //IL_0064: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Unknown result type (might be due to invalid IL or missing references) 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_0017: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_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) RequestID = package.ReadInt(); fromPos = package.ReadVector2i(); toPos = package.ReadVector2i(); itemHash = package.ReadInt(); dragAmount = package.ReadInt(); item = InventoryHelper.LoadItemFromPackage(package); } public ZPackage WriteToPackage() { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Expected O, but got Unknown //IL_0016: 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) ZPackage val = new ZPackage(); val.Write(RequestID); val.Write(fromPos); val.Write(toPos); val.Write(itemHash); val.Write(dragAmount); InventoryHelper.WriteItemToPackage(item, val); return val; } public void PrintDebug() { //IL_002d: 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) Log.LogDebug("RequestMove:"); Log.LogDebug($" RequestID: {RequestID}"); Log.LogDebug($" fromPos: {fromPos}"); Log.LogDebug($" toPos: {toPos}"); Log.LogDebug($" itemHash: {itemHash}"); Log.LogDebug($" dragAmount: {dragAmount}"); } } 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_0020: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_004b: 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, false); } else { inventory.AddItem(val); } hasChanges = true; } } public void Add(Vector2i pos, ItemData item) { //IL_0002: 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_0002: 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_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) //IL_0041: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Unknown result type (might be due to invalid IL or missing references) 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_0007: 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_0026: 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; } return itemAt.m_shared.m_name != item.m_shared.m_name || itemAt.m_stack != item.m_stack; } public bool HasChanges() { return hasChanges; } } 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_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Expected O, but got Unknown ZPackage val = new ZPackage(); val.Write(SourceID); val.Write(Success); val.Write(Amount); return val; } public void PrintDebug() { Log.LogDebug("RequestMoveResponse:"); Log.LogDebug($" SourceID: {SourceID}"); Log.LogDebug($" Success: {Success}"); Log.LogDebug($" Amount: {Amount}"); } } 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_0022: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Unknown result type (might be due to invalid IL or missing references) SourceID = sourceID; Success = success; Amount = amount; this.inventoryPos = inventoryPos; this.switchItem = switchItem.ClampStackSize(); } public RequestChestAddResponse(ZPackage package) { //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 = package.ReadInt(); inventoryPos = package.ReadVector2i(); Success = package.ReadBool(); Amount = package.ReadInt(); switchItem = InventoryHelper.LoadItemFromPackage(package); } public RequestChestAddResponse() { //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) SourceID = 0; Success = false; inventoryPos = new Vector2i(-1, -1); Amount = 0; switchItem = null; } public ZPackage WriteToPackage() { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Expected O, but got Unknown //IL_0016: 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 void PrintDebug() { //IL_002d: Unknown result type (might be due to invalid IL or missing references) Log.LogDebug("RequestChestAddResponse:"); Log.LogDebug($" id: {SourceID}"); Log.LogDebug($" inventoryPos: {inventoryPos}"); Log.LogDebug($" success: {Success}"); Log.LogDebug($" amount: {Amount}"); InventoryHelper.PrintItem("switchItem", switchItem); } } public interface IPackage { ZPackage WriteToPackage(); void PrintDebug(); } 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_0031: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Unknown result type (might be due to invalid IL or missing references) //IL_00ba: Unknown result type (might be due to