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 SwmarlyValheimQOL v2.0.15
SwmarlyValheimQOL.dll
Decompiled 2 months 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.Versioning; using System.Security; using System.Security.Permissions; using System.Threading; using BepInEx; using BepInEx.Bootstrap; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; using Jotunn.Extensions; using Jotunn.Utils; using Microsoft.CodeAnalysis; using TMPro; using UnityEngine; using UnityEngine.Events; using UnityEngine.UI; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")] [assembly: IgnoresAccessChecksTo("assembly_guiutils")] [assembly: IgnoresAccessChecksTo("assembly_utils")] [assembly: IgnoresAccessChecksTo("assembly_valheim")] [assembly: AssemblyCompany("SwmarlyValheimQOL")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("2.0.15.0")] [assembly: AssemblyInformationalVersion("2.0.15+6c1c2e7b89df8509a7476311d05186b40cfdb110")] [assembly: AssemblyProduct("SwmarlyValheimQOL")] [assembly: AssemblyTitle("SwmarlyValheimQOL")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("2.0.15.0")] [module: UnverifiableCode] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace SwmarlyValheimQOL { [HarmonyPatch(typeof(Game), "Start")] internal static class CurrencyRpcRegistrationPatch { [HarmonyPostfix] private static void Postfix() { CurrencyRpc.Register(); } } [HarmonyPatch(typeof(ZNet), "Start")] internal static class CurrencyZNetRegistrationPatch { [HarmonyPostfix] private static void Postfix() { CurrencyRpc.Register(); } } [HarmonyPatch(typeof(Player), "Update")] internal static class CurrencyRpcRetryPatch { private static void Postfix(Player __instance) { if (Plugin.IsLocalPlayer(__instance)) { CurrencyRpc.Update(); } } } internal static class CurrencyRpc { private sealed class PendingPickup { internal int RequestId; internal DateTime CreatedUtc; internal DateTime LastSentUtc; } private sealed class PendingPurchase { internal int RequestId; internal DateTime CreatedUtc; internal string ItemName; internal int Price; internal int Stack; } private sealed class CompletedResponse { internal bool IsPurchase; internal int RequestId; internal ZDOID DropId; internal bool Success; internal int Amount; internal int Balance; internal string ItemName; internal DateTime CompletedUtc; } private const int ProtocolVersion = 2; private const int MaxPackageBytes = 32768; private const int MaxItemNameLength = 256; private const int PickupRequestMessage = 1; private const int PurchaseRequestMessage = 2; private const int ResponseMessage = 3; private static readonly TimeSpan PendingExpiry = TimeSpan.FromSeconds(30.0); private static readonly TimeSpan CompletedExpiry = TimeSpan.FromSeconds(30.0); private static readonly Dictionary<ZDOID, PendingPickup> PendingPickups = new Dictionary<ZDOID, PendingPickup>(); private static PendingPurchase PendingPurchaseRequest; private static readonly Dictionary<string, CompletedResponse> CompletedResponses = new Dictionary<string, CompletedResponse>(); private static readonly object Sync = new object(); private const string CurrencyRpcName = "SwmarlyValheimQOL.Currency"; private static ZRoutedRpc RegisteredRoutedRpc; private static ZRoutedRpc FailedRoutedRpc; internal static bool IsReady => RegisteredRoutedRpc == ZRoutedRpc.instance; internal static bool Register() { ZRoutedRpc instance = ZRoutedRpc.instance; if (instance == null) { return false; } if (RegisteredRoutedRpc == instance) { return true; } try { instance.Register<ZPackage>("SwmarlyValheimQOL.Currency", (Action<long, ZPackage>)ReceiveRouted); RegisteredRoutedRpc = instance; FailedRoutedRpc = null; return true; } catch (Exception ex) { RegisteredRoutedRpc = null; if (FailedRoutedRpc != instance) { FailedRoutedRpc = instance; Plugin.LogWarning("Currency RPC registration failed; coin pickup will remain safely on the ground until it is available: " + ex.Message); } return false; } } internal static void Reset() { lock (Sync) { PendingPickups.Clear(); PendingPurchaseRequest = null; CompletedResponses.Clear(); RegisteredRoutedRpc = null; FailedRoutedRpc = null; } } internal static bool TryRequestPickup(ItemDrop drop) { //IL_005f: Unknown result type (might be due to invalid IL or missing references) //IL_0064: Unknown result type (might be due to invalid IL or missing references) //IL_0085: 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_0105: Unknown result type (might be due to invalid IL or missing references) //IL_010a: Unknown result type (might be due to invalid IL or missing references) //IL_0111: Unknown result type (might be due to invalid IL or missing references) //IL_0118: Unknown result type (might be due to invalid IL or missing references) //IL_011f: Unknown result type (might be due to invalid IL or missing references) //IL_0120: Unknown result type (might be due to invalid IL or missing references) //IL_012b: Expected O, but got Unknown //IL_0147: 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) if (!Register() || (Object)(object)drop == (Object)null || (Object)(object)drop.m_nview == (Object)null || !drop.m_nview.IsValid() || drop.m_nview.GetZDO() == null || ZRoutedRpc.instance == null || (Object)(object)ZNet.instance == (Object)null) { return false; } DateTime utcNow = DateTime.UtcNow; ZDOID uid = drop.m_nview.GetZDO().m_uid; bool flag = false; int num; lock (Sync) { PrunePending(utcNow); if (PendingPickups.TryGetValue(uid, out var value)) { num = value.RequestId; if (utcNow - value.LastSentUtc >= TimeSpan.FromSeconds(1.0)) { value.LastSentUtc = utcNow; flag = true; } } else { num = ContainerPatch.NextRequestId(); PendingPickups[uid] = new PendingPickup { RequestId = num, CreatedUtc = utcNow, LastSentUtc = utcNow }; flag = true; } } if (!flag) { return true; } ZPackage val = new ZPackage(); val.Write(2); val.Write(1); val.Write(num); val.Write(uid); if (SendToServer(val)) { return true; } lock (Sync) { if (PendingPickups.TryGetValue(uid, out var value2) && value2.RequestId == num) { PendingPickups.Remove(uid); } } return false; } internal static void Update() { //IL_008c: Unknown result type (might be due to invalid IL or missing references) //IL_00dd: Unknown result type (might be due to invalid IL or missing references) //IL_00e2: Unknown result type (might be due to invalid IL or missing references) //IL_00e9: Unknown result type (might be due to invalid IL or missing references) //IL_00f0: 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_0100: Unknown result type (might be due to invalid IL or missing references) //IL_010f: Expected O, but got Unknown if (!Register() || ZRoutedRpc.instance == null || (Object)(object)ZNet.instance == (Object)null) { return; } DateTime utcNow = DateTime.UtcNow; List<KeyValuePair<ZDOID, int>> list = new List<KeyValuePair<ZDOID, int>>(); lock (Sync) { PrunePending(utcNow); foreach (KeyValuePair<ZDOID, PendingPickup> pendingPickup in PendingPickups) { if (!(utcNow - pendingPickup.Value.LastSentUtc < TimeSpan.FromSeconds(1.0))) { pendingPickup.Value.LastSentUtc = utcNow; list.Add(new KeyValuePair<ZDOID, int>(pendingPickup.Key, pendingPickup.Value.RequestId)); } } } foreach (KeyValuePair<ZDOID, int> item in list) { ZPackage val = new ZPackage(); val.Write(2); val.Write(1); val.Write(item.Value); val.Write(item.Key); SendToServer(val); } } internal static bool TryRequestPurchase(TradeItem item) { //IL_0137: Unknown result type (might be due to invalid IL or missing references) //IL_013c: 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_014a: Unknown result type (might be due to invalid IL or missing references) //IL_0151: Unknown result type (might be due to invalid IL or missing references) //IL_0162: Unknown result type (might be due to invalid IL or missing references) //IL_016e: Unknown result type (might be due to invalid IL or missing references) //IL_017f: Expected O, but got Unknown if (!Register() || item == null || (Object)(object)item.m_prefab == (Object)null || string.IsNullOrEmpty(((Object)item.m_prefab).name) || ((Object)item.m_prefab).name.Length > 256 || item.m_price <= 0 || item.m_stack <= 0 || ZRoutedRpc.instance == null || (Object)(object)ZNet.instance == (Object)null) { return false; } DateTime utcNow = DateTime.UtcNow; int num; lock (Sync) { PrunePending(utcNow); if (PendingPurchaseRequest != null && PendingPurchaseRequest.ItemName == ((Object)item.m_prefab).name && PendingPurchaseRequest.Price == item.m_price && PendingPurchaseRequest.Stack == item.m_stack) { num = PendingPurchaseRequest.RequestId; PendingPurchaseRequest.CreatedUtc = utcNow; } else { num = ContainerPatch.NextRequestId(); PendingPurchaseRequest = new PendingPurchase { RequestId = num, CreatedUtc = utcNow, ItemName = ((Object)item.m_prefab).name, Price = item.m_price, Stack = item.m_stack }; } } ZPackage val = new ZPackage(); val.Write(2); val.Write(2); val.Write(num); val.Write(((Object)item.m_prefab).name); val.Write(item.m_price); val.Write(item.m_stack); if (SendToServer(val)) { return true; } lock (Sync) { if (PendingPurchaseRequest != null && PendingPurchaseRequest.RequestId == num) { PendingPurchaseRequest = null; } } return false; } private static bool SendToServer(ZPackage package) { try { if (RegisteredRoutedRpc != ZRoutedRpc.instance || ZRoutedRpc.instance == null) { return false; } ZRoutedRpc.instance.InvokeRoutedRPC(ZRoutedRpc.instance.GetServerPeerID(), "SwmarlyValheimQOL.Currency", new object[1] { package }); return true; } catch (Exception ex) { Plugin.LogWarning("Currency request could not be sent: " + ex.Message); return false; } } private static void ReceiveRouted(long sender, ZPackage package) { if (!IsSafePackage(package)) { return; } int pos = package.GetPos(); try { package.SetPos(0); if (package.ReadInt() == 2) { int num = package.ReadInt(); package.SetPos(0); switch (num) { case 1: HandlePickupRequest(sender, package); break; case 2: HandlePurchaseRequest(sender, package); break; case 3: HandleResponse(sender, package); break; } } } catch (Exception ex) { Plugin.LogWarning("Currency routed message failed safely: " + ex.Message); } finally { package.SetPos(pos); } } private static void HandlePickupRequest(long sender, ZPackage package) { //IL_0219: Unknown result type (might be due to invalid IL or missing references) //IL_021a: 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_004f: Unknown result type (might be due to invalid IL or missing references) //IL_00ca: Unknown result type (might be due to invalid IL or missing references) //IL_00d6: 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) if ((Object)(object)ZNet.instance == (Object)null || !ZNet.instance.IsServer()) { return; } if (!TryReadPickup(package, out var requestId, out var dropId)) { Respond(sender, purchase: false, requestId, dropId, success: false, 0, 0, null); return; } if (TryGetCompleted(sender, purchase: false, requestId, out var response)) { Respond(sender, response); return; } Player val = ContainerRPCHandler.FindSenderPlayer(sender); ItemDrop val2 = FindDrop(dropId); bool flag = (Object)(object)val != (Object)null && (Object)(object)val2 != (Object)null && val2.m_itemData?.m_shared != null && val2.m_itemData.m_shared.m_name == "$item_coins" && val2.m_itemData.m_stack > 0 && val2.m_itemData.m_stack <= 99999 && Vector3.SqrMagnitude(((Component)val).transform.position - ((Component)val2).transform.position) <= 16f; int amount = (flag ? val2.m_itemData.m_stack : 0); int num = ((!((Object)(object)val == (Object)null)) ? Plugin.GetPocketCoins(val) : 0); if (flag) { ZNetView nview = val2.m_nview; ZDO val3 = ((nview != null) ? nview.GetZDO() : null); int result; if (val3 == null || val3.GetBool("SwmarlyValheimQOL_CoinDropConsumed", false)) { flag = false; amount = 0; } else if (!QolCore.TryAddCoins(num, amount, out result) || val.m_customData == null || (Object)(object)ZNetScene.instance == (Object)null) { flag = false; amount = 0; } else { int coins = num; Plugin.SetPocketCoins(val, result); if (Plugin.GetPocketCoins(val) != result) { Plugin.SetPocketCoins(val, coins); flag = false; amount = 0; } else { try { val3.Set("SwmarlyValheimQOL_CoinDropConsumed", true); ZNetScene.instance.Destroy(((Component)val2).gameObject); num = result; } catch (Exception ex) { val3.Set("SwmarlyValheimQOL_CoinDropConsumed", false); Plugin.SetPocketCoins(val, coins); flag = false; amount = 0; Plugin.LogWarning("Currency pickup rollback completed after the coin drop could not be destroyed: " + ex.Message); } } } } RespondAndCache(sender, new CompletedResponse { IsPurchase = false, RequestId = requestId, DropId = dropId, Success = flag, Amount = amount, Balance = num, CompletedUtc = DateTime.UtcNow }); } private static void HandlePurchaseRequest(long sender, ZPackage package) { //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_01e1: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)ZNet.instance == (Object)null || !ZNet.instance.IsServer()) { return; } if (!TryReadPurchase(package, out var requestId, out var itemName, out var price, out var stack)) { Respond(sender, purchase: true, requestId, default(ZDOID), success: false, 0, 0, null); return; } if (TryGetCompleted(sender, purchase: true, requestId, out var response)) { Respond(sender, response); return; } Player val = ContainerRPCHandler.FindSenderPlayer(sender); Trader trader = null; TradeItem trade = null; bool num = (Object)(object)val != (Object)null && TryFindTrade(val, itemName, price, stack, out trader, out trade); Inventory val2 = ((val != null) ? ((Humanoid)val).GetInventory() : null); int num2 = ((!((Object)(object)val == (Object)null)) ? Plugin.GetPocketCoins(val) : 0); int num3 = ((val2 != null) ? val2.CountItems("$item_coins", -1, true) : 0); object obj; if (trade == null) { obj = null; } else { ItemDrop prefab = trade.m_prefab; obj = ((prefab != null) ? ((Component)prefab).GetComponent<ItemDrop>() : null); } ItemDrop val3 = (ItemDrop)obj; string text = val3?.m_itemData?.m_shared?.m_name; bool flag = num && val2 != null && (Object)(object)trade?.m_prefab != (Object)null && val3?.m_itemData?.m_shared != null && !string.IsNullOrEmpty(text) && price > 0 && stack > 0 && QolCore.AddCoins(num3, num2) >= price && val2.CanAddItem(((Component)val3).gameObject, stack); if (flag) { int num4 = Math.Min(num3, price); int amount = price - num4; int num5 = RemoveCoinsFromInventory(val2, num4); flag = num5 == num4; if (flag) { int num6 = val2.CountItems(text, -1, true); ItemData obj2 = val2.AddItem(((Object)trade.m_prefab).name, stack, trade.m_prefab.m_itemData.m_quality, trade.m_prefab.m_itemData.m_variant, 0L, string.Empty, new Vector2i(-1, -1), false, false, true); int num7 = Math.Max(0, val2.CountItems(text, -1, true) - num6); flag = obj2 != null && num7 == stack; if (flag) { num2 = QolCore.RemoveCoins(num2, amount); Plugin.SetPocketCoins(val, num2); try { trader.OnBought(trade); } catch (Exception ex) { Plugin.LogWarning("Currency purchase completed but Trader.OnBought failed: " + ex.Message); } } else { if (num7 > 0) { val2.RemoveItem(text, num7, -1, true); } RestoreCurrency(val, val2, num5, num2); } } else { RestoreCurrency(val, val2, num5, num2); } } if (!flag) { num2 = ((!((Object)(object)val == (Object)null)) ? Plugin.GetPocketCoins(val) : 0); } RespondAndCache(sender, new CompletedResponse { IsPurchase = true, RequestId = requestId, Success = flag, Amount = (flag ? stack : 0), Balance = num2, ItemName = (flag ? itemName : null), CompletedUtc = DateTime.UtcNow }); } private static bool TryFindTrade(Player player, string itemName, int price, int stack, out Trader trader, out TradeItem trade) { //IL_0075: Unknown result type (might be due to invalid IL or missing references) //IL_0080: Unknown result type (might be due to invalid IL or missing references) //IL_0085: Unknown result type (might be due to invalid IL or missing references) trader = null; trade = null; if ((Object)(object)player == (Object)null || string.IsNullOrEmpty(itemName) || itemName.Length > 256) { return false; } FieldInfo fieldInfo = AccessTools.Field(typeof(Trader), "m_items"); if (fieldInfo == null) { Plugin.LogWarning("Currency purchase rejected: Trader.m_items was not found in this Valheim build."); return false; } Trader[] array = Object.FindObjectsOfType<Trader>(); foreach (Trader val in array) { if ((Object)(object)val == (Object)null || Vector3.SqrMagnitude(((Component)val).transform.position - ((Component)player).transform.position) > 100f || !(fieldInfo.GetValue(val) is IList list)) { continue; } foreach (object item in list) { TradeItem val2 = (TradeItem)((item is TradeItem) ? item : null); if (val2 != null && !((Object)(object)val2.m_prefab == (Object)null) && !(((Object)val2.m_prefab).name != itemName) && val2.m_price == price && val2.m_stack == stack) { trader = val; trade = val2; return true; } } } return false; } private static int RemoveCoinsFromInventory(Inventory inventory, int amount) { if (inventory == null || amount <= 0) { return 0; } int num = inventory.CountItems("$item_coins", -1, true); inventory.RemoveItem("$item_coins", amount, -1, true); return Math.Max(0, num - inventory.CountItems("$item_coins", -1, true)); } private static void RestoreCurrency(Player player, Inventory inventory, int inventoryCoins, int originalPocket) { if (inventory != null && inventoryCoins > 0 && (Object)(object)ObjectDB.instance != (Object)null) { GameObject itemPrefab = ObjectDB.instance.GetItemPrefab("Coins"); if ((Object)(object)itemPrefab != (Object)null) { inventory.AddItem(itemPrefab, inventoryCoins); } } if ((Object)(object)player != (Object)null) { Plugin.SetPocketCoins(player, originalPocket); } } private static ItemDrop FindDrop(ZDOID dropId) { //IL_001b: Unknown result type (might be due to invalid IL or missing references) if (ZDOMan.instance == null || (Object)(object)ZNetScene.instance == (Object)null) { return null; } ZDO zDO = ZDOMan.instance.GetZDO(dropId); ZNetView val = ((zDO == null) ? null : ZNetScene.instance.FindInstance(zDO)); object obj; if (!((Object)(object)val == (Object)null)) { obj = ((Component)val).GetComponent<ItemDrop>(); if (obj == null) { return ((Component)val).GetComponentInChildren<ItemDrop>(); } } else { obj = null; } return (ItemDrop)obj; } private static bool TryReadPickup(ZPackage package, out int requestId, out ZDOID dropId) { //IL_0004: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Unknown result type (might be due to invalid IL or missing references) requestId = 0; dropId = default(ZDOID); if (!IsSafePackage(package)) { return false; } try { if (package.ReadInt() != 2) { return false; } if (package.ReadInt() != 1) { return false; } requestId = package.ReadInt(); dropId = package.ReadZDOID(); return QolCore.IsValidOperationId(requestId); } catch { return false; } } private static bool TryReadPurchase(ZPackage package, out int requestId, out string itemName, out int price, out int stack) { requestId = 0; itemName = null; price = 0; stack = 0; if (!IsSafePackage(package)) { return false; } try { if (package.ReadInt() != 2) { return false; } if (package.ReadInt() != 2) { return false; } requestId = package.ReadInt(); itemName = package.ReadString(); price = package.ReadInt(); stack = package.ReadInt(); return QolCore.IsValidOperationId(requestId) && !string.IsNullOrEmpty(itemName) && itemName.Length <= 256; } catch { return false; } } private static bool IsSafePackage(ZPackage package) { if (package != null && package.GetArray() != null) { return package.GetArray().Length <= 32768; } return false; } private static bool TryGetCompleted(long sender, bool purchase, int requestId, out CompletedResponse response) { lock (Sync) { PruneCompleted(DateTime.UtcNow); string completedKey = GetCompletedKey(sender, purchase, requestId); if (CompletedResponses.TryGetValue(completedKey, out response)) { return true; } } response = null; return false; } private static void RespondAndCache(long sender, CompletedResponse response) { lock (Sync) { PruneCompleted(DateTime.UtcNow); CompletedResponses[GetCompletedKey(sender, response.IsPurchase, response.RequestId)] = response; } Respond(sender, response); } private static string GetCompletedKey(long sender, bool purchase, int requestId) { return sender + ":" + (purchase ? "purchase" : "pickup") + ":" + requestId; } private static void PruneCompleted(DateTime now) { foreach (string item in new List<string>(CompletedResponses.Keys)) { if (QolCore.IsExpired(now, CompletedResponses[item].CompletedUtc, CompletedExpiry)) { CompletedResponses.Remove(item); } } } private static void PrunePending(DateTime now) { //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0024: 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) foreach (ZDOID item in new List<ZDOID>(PendingPickups.Keys)) { if (PendingPickups.TryGetValue(item, out var value) && QolCore.IsExpired(now, value.CreatedUtc, PendingExpiry)) { PendingPickups.Remove(item); } } if (PendingPurchaseRequest != null && QolCore.IsExpired(now, PendingPurchaseRequest.CreatedUtc, PendingExpiry)) { PendingPurchaseRequest = null; } } private static void Respond(long sender, bool purchase, int requestId, ZDOID dropId, bool success, int amount, int balance, string itemName) { //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) Respond(sender, new CompletedResponse { IsPurchase = purchase, RequestId = requestId, DropId = dropId, Success = success, Amount = amount, Balance = balance, ItemName = itemName, CompletedUtc = DateTime.UtcNow }); } private static void Respond(long sender, CompletedResponse response) { //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_000e: Expected O, but got Unknown //IL_0036: Unknown result type (might be due to invalid IL or missing references) if (ZRoutedRpc.instance != null) { ZPackage val = new ZPackage(); val.Write(2); val.Write(3); val.Write(response.IsPurchase); val.Write(response.RequestId); val.Write(response.DropId); val.Write(response.Success); val.Write(response.Amount); val.Write(response.Balance); val.Write(response.ItemName ?? string.Empty); if (RegisteredRoutedRpc == ZRoutedRpc.instance) { ZRoutedRpc.instance.InvokeRoutedRPC(sender, "SwmarlyValheimQOL.Currency", new object[1] { val }); } } } private static void HandleResponse(long sender, ZPackage package) { //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_0113: Unknown result type (might be due to invalid IL or missing references) //IL_0131: Unknown result type (might be due to invalid IL or missing references) //IL_0155: Unknown result type (might be due to invalid IL or missing references) if (!IsTrustedServerResponse(sender) || !IsSafePackage(package)) { return; } try { if (package.ReadInt() != 2 || package.ReadInt() != 3) { return; } bool flag = package.ReadBool(); int num = package.ReadInt(); ZDOID val = package.ReadZDOID(); bool flag2 = package.ReadBool(); int num2 = package.ReadInt(); int num3 = package.ReadInt(); string text = package.ReadString(); if (!QolCore.IsValidOperationId(num) || num2 < 0 || num3 < 0 || (text?.Length ?? 0) > 256) { return; } Player localPlayer = Player.m_localPlayer; if ((Object)(object)localPlayer == (Object)null) { return; } if (flag) { lock (Sync) { if (PendingPurchaseRequest == null || PendingPurchaseRequest.RequestId != num) { return; } PendingPurchaseRequest = null; } if (flag2) { UpdatePurchaseUi(localPlayer, num3); } return; } lock (Sync) { if (!PendingPickups.TryGetValue(val, out var value) || value.RequestId != num) { return; } PendingPickups.Remove(val); } if (!flag2) { return; } Plugin.SetPocketCoins(localPlayer, num3); ItemDrop val2 = FindDrop(val); if ((Object)(object)val2 != (Object)null && (Object)(object)ZNetScene.instance != (Object)null) { ZNetScene.instance.Destroy(((Component)val2).gameObject); } if (num2 > 0 && (Object)(object)ObjectDB.instance != (Object)null) { GameObject itemPrefab = ObjectDB.instance.GetItemPrefab("Coins"); ItemDrop val3 = ((itemPrefab != null) ? itemPrefab.GetComponent<ItemDrop>() : null); if (val3?.m_itemData != null) { ((Character)localPlayer).ShowPickupMessage(val3.m_itemData, num2); } } } catch (Exception ex) { Log.LogWarning("Rejected malformed currency response: " + ex.Message); } } private static void UpdatePurchaseUi(Player player, int balance) { Plugin.SetPocketCoins(player, balance); StoreGui val = Object.FindObjectOfType<StoreGui>(); MethodInfo methodInfo = AccessTools.Method(typeof(StoreGui), "FillList", (Type[])null, (Type[])null); if ((Object)(object)val != (Object)null && methodInfo != null) { try { methodInfo.Invoke(val, null); } catch (Exception ex) { Plugin.LogWarning("Currency purchase UI refresh failed: " + ex.Message); } } InventoryGui instance = InventoryGui.instance; if (instance != null) { instance.UpdateCraftingPanel(false); } } private static bool IsTrustedServerResponse(long sender) { if ((Object)(object)ZNet.instance == (Object)null) { return false; } if (ZNet.instance.IsServer()) { if (sender != 0L) { return sender == ZNet.GetUID(); } return true; } if (ZRoutedRpc.instance != null) { return sender == ZRoutedRpc.instance.GetServerPeerID(); } return false; } } public class ContainerExtend : MonoBehaviour { private static readonly ConditionalWeakTable<Inventory, ContainerInventoryOwner> Containers = new ConditionalWeakTable<Inventory, ContainerInventoryOwner>(); private Container container; private Inventory inventory; private float nextRegistrationAttempt; private void Awake() { if (((Component)this).TryGetComponent<Container>(ref container)) { TryRegister(); nextRegistrationAttempt = Time.unscaledTime + 0.25f; } } private void Update() { if (Object.op_Implicit((Object)(object)container) && (inventory == null || !Containers.TryGetValue(inventory, out var value) || value == null || !((Object)(object)value.Container == (Object)(object)container)) && !(Time.unscaledTime < nextRegistrationAttempt)) { nextRegistrationAttempt = Time.unscaledTime + 0.25f; TryRegister(); } } private bool TryRegister() { if (!Object.op_Implicit((Object)(object)container)) { return false; } Inventory val = container.GetInventory(); if (val == null) { return false; } if (inventory != null && inventory != val) { Containers.Remove(inventory); } inventory = val; if (Containers.TryGetValue(val, out var value)) { if (value != null && (Object)(object)value.Container == (Object)(object)container) { return true; } Containers.Remove(val); } Containers.Add(val, new ContainerInventoryOwner(container)); return true; } private void OnDestroy() { if (inventory != null) { Containers.Remove(inventory); inventory = null; } } internal static bool EnsureRegistered(Container container) { if (!Object.op_Implicit((Object)(object)container)) { return false; } ContainerExtend component = ((Component)container).GetComponent<ContainerExtend>(); if ((Object)(object)component != (Object)null) { return component.TryRegister(); } return false; } public static bool GetContainer(Inventory inventory, out ContainerInventoryOwner container) { if (inventory == null) { container = null; return false; } return Containers.TryGetValue(inventory, out container); } } public static class ContainerHandler { public static RequestChestAdd AddItemToChest(this Container container, ItemData item, Inventory sourceInventory, Vector2i to, ZDOID sender, int dragAmount = -1) { //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_004e: Unknown result type (might be due to invalid IL or missing references) //IL_0054: Unknown result type (might be due to invalid IL or missing references) //IL_0090: Unknown result type (might be due to invalid IL or missing references) //IL_009f: Unknown result type (might be due to invalid IL or missing references) //IL_00b7: Unknown result type (might be due to invalid IL or missing references) if (!Object.op_Implicit((Object)(object)container) || !Object.op_Implicit((Object)(object)container.m_nview) || !container.m_nview.HasOwner() || sourceInventory == null || item == null) { return new RequestChestAdd(Vector2i.zero, 0, null, null, null); } dragAmount = PossibleDragAmount(container.GetInventory(), item, to, dragAmount); ItemData itemAt = container.GetInventory().GetItemAt(to.x, to.y); bool flag = itemAt != null && dragAmount != item.m_stack && !InventoryHelper.CanStack(itemAt, item); if (dragAmount <= 0 || flag || !sourceInventory.ContainsItem(item)) { return new RequestChestAdd(Vector2i.zero, 0, null, null, null); } RequestChestAdd requestChestAdd = new RequestChestAdd(to, dragAmount, item, sourceInventory, container.GetInventory()); InventoryBlock.Get(sourceInventory).BlockSlot(item.m_gridPos); InventoryPreview.AddPackage(requestChestAdd); if (container.m_nview.IsOwner()) { RequestChestAddResponse response = container.GetInventory().RequestItemAdd(requestChestAdd); InventoryHandler.RPC_RequestItemAddResponse(sourceInventory, response); return null; } GamePatches.InvokeRPC(container.m_nview, "MUC_RequestItemAdd", requestChestAdd); return requestChestAdd; } internal static int PossibleDragAmount(Inventory inventoryTo, ItemData dragItem, Vector2i to, int dragAmount) { //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_004e: Unknown result type (might be due to invalid IL or missing references) //IL_0054: Unknown result type (might be due to invalid IL or missing references) if (inventoryTo == null || dragItem == null || dragItem.m_shared == null || dragItem.m_stack <= 0) { return 0; } dragAmount = ((dragAmount >= 0) ? Mathf.Min(Mathf.Max(0, 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_0028: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_004e: Unknown result type (might be due to invalid IL or missing references) //IL_006b: Unknown result type (might be due to invalid IL or missing references) //IL_0070: Unknown result type (might be due to invalid IL or missing references) //IL_0063: 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_008a: Unknown result type (might be due to invalid IL or missing references) //IL_00d4: Unknown result type (might be due to invalid IL or missing references) //IL_00b4: Unknown result type (might be due to invalid IL or missing references) //IL_00b9: 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() || destinationInventory == null || item == null) { return new RequestChestRemove(Vector2i.zero, Vector2i.zero, 0, null, Object.op_Implicit((Object)(object)container) ? container.GetInventory() : null, destinationInventory); } dragAmount = PossibleDragAmount(destinationInventory, item, to, dragAmount); if (dragAmount <= 0 || InventoryBlock.Get(destinationInventory).IsSlotBlocked(to)) { return new RequestChestRemove(Vector2i.zero, Vector2i.zero, 0, null, container.GetInventory(), destinationInventory); } RequestChestRemove requestChestRemove = new RequestChestRemove(item.m_gridPos, to, dragAmount, switchItem, container.GetInventory(), destinationInventory); if (switchItem != null && !InventoryHelper.CanStack(item, switchItem) && dragAmount != item.m_stack) { return new RequestChestRemove(Vector2i.zero, Vector2i.zero, 0, null, container.GetInventory(), destinationInventory); } InventoryBlock.Get(destinationInventory).BlockSlot(requestChestRemove.toPos); InventoryPreview.AddPackage(requestChestRemove); if (container.m_nview.IsOwner()) { RequestChestRemoveResponse response = container.GetInventory().RequestItemRemove(requestChestRemove); InventoryHandler.RPC_RequestItemRemoveResponse(destinationInventory, response); return null; } GamePatches.InvokeRPC(container.m_nview, "MUC_RequestItemRemove", requestChestRemove); return requestChestRemove; } public static void MoveItemInChest(this Container container, ItemData item, Vector2i toPos, int dragAmount) { //IL_001e: 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) && item != null && dragAmount > 0) { RequestMove package = new RequestMove(item, toPos, dragAmount, container.GetInventory()); InventoryPreview.AddPackage(package); GamePatches.InvokeRPC(container.m_nview, "MUC_RequestItemMove", package); } } } public static class ContainerRPCHandler { private sealed class CompletedRequest { public IResponse Response; public DateTime CompletedUtc; } private static readonly Dictionary<string, CompletedRequest> CompletedRequests = new Dictionary<string, CompletedRequest>(); private static readonly object CompletedSync = new object(); private static readonly TimeSpan CompletedExpiry = TimeSpan.FromSeconds(30.0); 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) TryHandle(sender, containerId, package, "MUC_RequestItemAddResponse", (ZPackage p) => new RequestChestAdd(p), RequestItemAdd); } 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) TryHandle(sender, containerId, package, "MUC_RequestItemRemoveResponse", (ZPackage p) => new RequestChestRemove(p), RequestItemRemove); } 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) TryHandle(sender, containerId, package, "MUC_RequestItemConsumeResponse", (ZPackage p) => new RequestConsume(p), RequestItemConsume); } 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) TryHandle(sender, containerId, package, "MUC_RequestItemMoveResponse", (ZPackage p) => new RequestMove(p), RequestItemMove); } 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) TryHandle(sender, containerId, package, "MUC_RequestItemDropResponse", (ZPackage p) => new RequestDrop(p), RequestDrop); } private static void TryHandle<TResponse, TInput>(long sender, ZDOID containerId, ZPackage package, string rpcInvoke, Func<ZPackage, TInput> parse, Func<Inventory, TInput, TResponse> message) where TResponse : IResponse, new() where TInput : IPackage { //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_007b: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Unknown result type (might be due to invalid IL or missing references) if (!Plugin.QolOwnsMultiUserChests() || !IsSafePackage(package)) { return; } try { TInput input = parse(package); AttachSender(sender, input); HandleRPC(containerId, sender, rpcInvoke, message, input); } catch (Exception ex) { Log.LogWarning($"Rejected malformed chest request for {containerId}: {ex.Message}"); if (ZRoutedRpc.instance != null) { TResponse val = new TResponse { SourceID = TryReadRequestId(package) }; ZRoutedRpc.instance.InvokeRoutedRPC(sender, rpcInvoke, new object[2] { containerId, val.WriteToPackage() }); } } } private static int TryReadRequestId(ZPackage package) { if (package == null) { return 0; } int pos = package.GetPos(); try { package.SetPos(0); if (package.ReadInt() != 2) { return 0; } return package.ReadInt(); } catch { return 0; } finally { package.SetPos(pos); } } private static bool IsSafePackage(ZPackage package) { if (package != null && package.GetArray() != null) { return package.GetArray().Length <= 131072; } return false; } private static void AttachSender<TInput>(long sender, TInput input) where TInput : IPackage { if (input is IRequest request) { request.SenderID = sender; } if (input is RequestConsume requestConsume) { requestConsume.SenderID = sender; } if (input is RequestDrop requestDrop) { requestDrop.SenderID = sender; } } internal static Player FindSenderPlayer(long sender) { //IL_0062: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)ZNet.instance == (Object)null || (Object)(object)ZNetScene.instance == (Object)null) { return null; } if (!ZNet.instance.IsDedicated() && sender == ZNet.GetUID()) { return Player.m_localPlayer; } foreach (ZNetPeer peer in ZNet.instance.m_peers) { if (peer != null && peer.m_uid == sender) { GameObject val = ZNetScene.instance.FindInstance(peer.m_characterID); ZNetView val2 = (((Object)(object)val == (Object)null) ? null : val.GetComponent<ZNetView>()); return Object.op_Implicit((Object)(object)val2) ? ((Component)val2).GetComponent<Player>() : null; } } return null; } private static bool ValidateSender(long sender, Container container, IPackage input, out Player player) { //IL_0050: Unknown result type (might be due to invalid IL or missing references) //IL_005b: Unknown result type (might be due to invalid IL or missing references) //IL_0060: Unknown result type (might be due to invalid IL or missing references) //IL_00db: Unknown result type (might be due to invalid IL or missing references) //IL_00e0: Unknown result type (might be due to invalid IL or missing references) player = FindSenderPlayer(sender); if ((Object)(object)player == (Object)null || (Object)(object)container == (Object)null || (Object)(object)container.m_nview == (Object)null || !container.m_nview.IsValid() || container.GetInventory() == null || ((Humanoid)player).GetInventory() == null) { return false; } if (Vector3.SqrMagnitude(((Component)player).transform.position - ((Component)container).transform.position) > 225f) { return false; } if (input is IRequest) { Inventory inventory = ((Humanoid)player).GetInventory(); if (input is RequestChestAdd requestChestAdd) { requestChestAdd.SourceInventory = inventory; } if (input is RequestChestRemove requestChestRemove) { requestChestRemove.TargetInventory = inventory; } if (input is RequestMove requestMove) { requestMove.SourceInventory = container.GetInventory(); requestMove.TargetInventory = container.GetInventory(); } } if (input is RequestDrop requestDrop) { requestDrop.sender = ((Character)player).GetZDOID(); } if (input is RequestDrop requestDrop2) { requestDrop2.ServerPlayer = player; } return true; } private static void HandleRPC<TResponse, TInput>(ZDOID containerId, long target, string rpcInvoke, Func<Inventory, TInput, TResponse> message, TInput input) where TResponse : IResponse, new() where TInput : IPackage { //IL_0082: 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_0060: Unknown result type (might be due to invalid IL or missing references) //IL_014e: 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) if ((Object)(object)ZNet.instance == (Object)null || !ZNet.instance.IsServer() || ZDOMan.instance == null || (Object)(object)ZNetScene.instance == (Object)null || ZRoutedRpc.instance == null) { return; } int requestId = GetRequestId(input); if (requestId != 0 && TryGetCompleted<TResponse>(target, containerId, requestId, out var response)) { ZRoutedRpc.instance.InvokeRoutedRPC(target, rpcInvoke, new object[2] { containerId, response.WriteToPackage() }); return; } ZDO zDO = ZDOMan.instance.GetZDO(containerId); ZNetView val = ((zDO != null) ? ZNetScene.instance.FindInstance(zDO) : null); TResponse response2; if (!Object.op_Implicit((Object)(object)val)) { response2 = FallbackResponse<TResponse>(input); } else { Container componentInChildren = ((Component)val).GetComponentInChildren<Container>(); if (Object.op_Implicit((Object)(object)componentInChildren) && ValidateSender(target, componentInChildren, input, out var _)) { InventoryPatch.AuthoritativeMutation = true; try { response2 = message(componentInChildren.GetInventory(), input); } finally { InventoryPatch.AuthoritativeMutation = false; } } else { Log.LogWarning($"{input.GetType().Name}: rejected sender {target} or missing Container on {((Object)val).name}"); response2 = FallbackResponse<TResponse>(input); } } if (requestId != 0) { CacheCompleted(target, containerId, requestId, response2); } ZRoutedRpc.instance.InvokeRoutedRPC(target, rpcInvoke, new object[2] { containerId, response2.WriteToPackage() }); } private static int GetRequestId(IPackage input) { if (input is IRequest request) { return request.RequestID; } if (input is RequestConsume requestConsume) { return requestConsume.RequestID; } if (input is RequestDrop requestDrop) { return requestDrop.RequestID; } return 0; } private unsafe static string GetRequestKey(long sender, ZDOID containerId, int requestId) { //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Unknown result type (might be due to invalid IL or missing references) string[] obj = new string[5] { sender.ToString(), ":", null, null, null }; ZDOID val = containerId; obj[2] = ((object)(*(ZDOID*)(&val))/*cast due to .constrained prefix*/).ToString(); obj[3] = ":"; obj[4] = requestId.ToString(); return string.Concat(obj); } private static bool TryGetCompleted<TResponse>(long sender, ZDOID containerId, int requestId, out TResponse response) where TResponse : IResponse, new() { //IL_001b: Unknown result type (might be due to invalid IL or missing references) lock (CompletedSync) { PruneCompleted(DateTime.UtcNow); string requestKey = GetRequestKey(sender, containerId, requestId); if (CompletedRequests.TryGetValue(requestKey, out var value) && value.Response is TResponse val) { response = val; return true; } } response = default(TResponse); return false; } private static void CacheCompleted<TResponse>(long sender, ZDOID containerId, int requestId, TResponse response) where TResponse : IResponse, new() { //IL_0020: Unknown result type (might be due to invalid IL or missing references) lock (CompletedSync) { PruneCompleted(DateTime.UtcNow); CompletedRequests[GetRequestKey(sender, containerId, requestId)] = new CompletedRequest { Response = response, CompletedUtc = DateTime.UtcNow }; } } private static void PruneCompleted(DateTime now) { foreach (string item in new List<string>(CompletedRequests.Keys)) { if (QolCore.IsExpired(now, CompletedRequests[item].CompletedUtc, CompletedExpiry)) { CompletedRequests.Remove(item); } } } internal static void ClearCompleted() { lock (CompletedSync) { CompletedRequests.Clear(); } } private static TResponse FallbackResponse<TResponse>(IPackage input) where TResponse : IResponse, new() { //IL_0052: 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_0057: Unknown result type (might be due to invalid IL or missing references) TResponse val = new TResponse { SourceID = GetRequestId(input) }; if (input is RequestChestAdd requestChestAdd && val is RequestChestAddResponse requestChestAddResponse) { requestChestAddResponse.switchItem = requestChestAdd.dragItem; requestChestAddResponse.inventoryPos = requestChestAdd.dragItem?.m_gridPos ?? Vector2i.zero; } else if (input is RequestChestRemove requestChestRemove && val is RequestChestRemoveResponse requestChestRemoveResponse) { requestChestRemoveResponse.responseItem = requestChestRemove.switchItem; } return val; } public static RequestChestAddResponse RequestItemAdd(this Inventory inventory, RequestChestAdd request) { //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_00d5: Unknown result type (might be due to invalid IL or missing references) if (inventory == null || request == null) { return new RequestChestAddResponse(0, success: false, Vector2i.zero, 0, null); } if (request.dragItem == null || request.SourceInventory == null || !ValidateSourceItem(request)) { return new RequestChestAddResponse(request.RequestID, success: false, Vector2i.zero, 0, request.dragItem); } int stack = request.dragItem.m_stack; ItemData itemAt = request.SourceInventory.GetItemAt(request.dragItem.m_gridPos.x, request.dragItem.m_gridPos.y); ItemData val = ((itemAt != null) ? itemAt.Clone() : null); ItemData itemAt2 = request.SourceInventory.GetItemAt(request.dragItem.m_gridPos.x, request.dragItem.m_gridPos.y); if (itemAt2 == null || !request.SourceInventory.RemoveItem(itemAt2, stack)) { return new RequestChestAddResponse(request.RequestID, success: false, request.dragItem.m_gridPos, 0, null); } RequestChestAddResponse requestChestAddResponse = ((request.toPos.x < 0 || request.toPos.y < 0) ? AddToAnySlot(inventory, request) : AddToSlot(inventory, request)); int num = (requestChestAddResponse.Success ? Mathf.Max(0, stack - requestChestAddResponse.Amount) : stack); if (requestChestAddResponse.Success && requestChestAddResponse.ReturnToSource && requestChestAddResponse.switchItem != null) { if (!RestoreSource(request.SourceInventory, requestChestAddResponse.switchItem, requestChestAddResponse.switchItem.m_stack)) { DropItemAtOwner(request.SourceInventory, requestChestAddResponse.switchItem, requestChestAddResponse.switchItem.m_stack); } requestChestAddResponse.ReturnToSource = false; } if (num > 0 && !RestoreSource(request.SourceInventory, val, num)) { DropItemAtOwner(request.SourceInventory, val, num); } return requestChestAddResponse; } private static bool ValidateSourceItem(RequestChestAdd request) { if (!QolCore.ValidSlot(request.dragItem.m_gridPos.x, request.dragItem.m_gridPos.y, request.SourceInventory.m_width, request.SourceInventory.m_height)) { return false; } ItemData itemAt = request.SourceInventory.GetItemAt(request.dragItem.m_gridPos.x, request.dragItem.m_gridPos.y); if (itemAt == null || itemAt.m_shared == null || request.dragItem.m_shared == null || request.dragItem.m_stack <= 0) { return false; } if (request.allowSwitch && request.dragItem.m_stack != itemAt.m_stack) { return false; } if (ItemIdentityMatches(itemAt, request.dragItem) && itemAt.m_stack >= request.dragItem.m_stack) { return QolCore.ValidAmount(request.dragItem.m_stack, itemAt.m_stack, itemAt.m_shared.m_maxStackSize); } return false; } private static bool RestoreSource(Inventory sourceInventory, ItemData original, int amount) { if (sourceInventory == null || original == null || amount <= 0) { return false; } original.m_stack = amount; return sourceInventory.AddItem(original, amount, original.m_gridPos.x, original.m_gridPos.y, false); } private static bool DropItemAtOwner(Inventory inventory, ItemData item, int amount) { //IL_005b: Unknown result type (might be due to invalid IL or missing references) //IL_0061: Unknown result type (might be due to invalid IL or missing references) //IL_0066: Unknown result type (might be due to invalid IL or missing references) //IL_006c: Unknown result type (might be due to invalid IL or missing references) //IL_0071: 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) if (inventory == null || item == null || amount <= 0) { return false; } InventoryOwner owner = InventoryOwner.GetOwner(inventory); Transform val = null; if (owner is ContainerInventoryOwner containerInventoryOwner) { Container container = containerInventoryOwner.Container; val = ((container != null) ? ((Component)container).transform : null); } if (owner is HumanoidInventoryOwner humanoidInventoryOwner) { Humanoid humanoid = humanoidInventoryOwner.Humanoid; val = ((humanoid != null) ? ((Component)humanoid).transform : null); } if ((Object)(object)val == (Object)null) { return false; } ItemDrop val2 = ItemDrop.DropItem(item, amount, val.position + val.forward + val.up, val.rotation); if ((Object)(object)val2 == (Object)null) { return false; } val2.OnPlayerDrop(); return true; } private static RequestChestAddResponse AddToSlot(Inventory inventory, RequestChestAdd request) { //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_007a: Unknown result type (might be due to invalid IL or missing references) //IL_00e8: Unknown result type (might be due to invalid IL or missing references) //IL_00d1: Unknown result type (might be due to invalid IL or missing references) //IL_00d6: 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) { if (removedItem != null) { inventory.AddItem(removedItem, removedItem.m_stack, request.toPos.x, request.toPos.y, false); } stackSpace = 0; return new RequestChestAddResponse(request.RequestID, success: false, request.dragItem.m_gridPos, 0, null); } bool flag2 = removedItem != null; if (!flag || stackSpace != request.dragItem.m_stack) { ItemData val = request.dragItem.Clone(); val.m_stack = request.dragItem.m_stack - stackSpace; removedItem = (flag2 ? removedItem : val); } if (removedItem != null) { removedItem.m_gridPos = request.dragItem.m_gridPos; } return new RequestChestAddResponse(request.RequestID, flag, request.dragItem.m_gridPos, stackSpace, removedItem, flag2); } private static bool CanStack(Inventory inventory, RequestChestAdd request, out int stackSpace, out ItemData removedItem) { ItemData itemAt = inventory.GetItemAt(request.toPos.x, request.toPos.y); removedItem = null; if (itemAt == null) { stackSpace = request.dragItem.m_stack; return true; } if (InventoryHelper.CanStack(itemAt, request.dragItem)) { stackSpace = Mathf.Min(itemAt.m_shared.m_maxStackSize - itemAt.m_stack, request.dragItem.m_stack); return true; } if (request.allowSwitch) { inventory.RemoveItem(itemAt, itemAt.m_stack); removedItem = itemAt; stackSpace = request.dragItem.m_stack; return true; } stackSpace = 0; return false; } private static RequestChestAddResponse AddToAnySlot(Inventory inventory, RequestChestAdd request) { //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_000e: Expected O, but got Unknown //IL_00c0: Unknown result type (might be due to invalid IL or missing references) //IL_0056: Unknown result type (might be due to invalid IL or missing references) Inventory val = new Inventory("tmp", (Sprite)null, 1, 1); val.AddItem(request.dragItem.Clone(), request.dragItem.m_stack, 0, 0, false); inventory.MoveItemToThis(val, val.GetItemAt(0, 0)); ItemData itemAt = val.GetItemAt(0, 0); if (itemAt == null) { return new RequestChestAddResponse(request.RequestID, success: true, request.dragItem.m_gridPos, request.dragItem.m_stack, null); } ItemData val2 = request.dragItem.Clone(); int num = request.dragItem.m_stack - itemAt.m_stack; val2.m_stack -= num; bool success = itemAt.m_stack != request.dragItem.m_stack; return new RequestChestAddResponse(request.RequestID, success, request.dragItem.m_gridPos, num, val2); } public static RequestChestRemoveResponse RequestItemRemove(this Inventory inventory, RequestChestRemove request) { //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_005e: 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_01bc: Unknown result type (might be due to invalid IL or missing references) //IL_01cc: Unknown result type (might be due to invalid IL or missing references) //IL_028d: Unknown result type (might be due to invalid IL or missing references) //IL_02b3: Unknown result type (might be due to invalid IL or missing references) //IL_032a: Unknown result type (might be due to invalid IL or missing references) //IL_02c5: Unknown result type (might be due to invalid IL or missing references) //IL_033a: Unknown result type (might be due to invalid IL or missing references) //IL_0340: Unknown result type (might be due to invalid IL or missing references) //IL_02ed: Unknown result type (might be due to invalid IL or missing references) //IL_036b: Unknown result type (might be due to invalid IL or missing references) //IL_0393: Unknown result type (might be due to invalid IL or missing references) if (inventory == null || request == null) { return new RequestChestRemoveResponse(0, success: false, 0, hasSwitched: false, null); } Vector2i fromPos = request.fromPos; int dragAmount = request.dragAmount; ItemData itemAt = inventory.GetItemAt(request.fromPos.x, request.fromPos.y); if (itemAt == null || request.TargetInventory == null || request.item == null || !ItemIdentityMatches(itemAt, request.item) || !QolCore.ValidSlot(fromPos.x, fromPos.y, inventory.m_width, inventory.m_height) || !QolCore.ValidAmount(dragAmount, itemAt.m_stack, itemAt.m_shared?.m_maxStackSize ?? 0)) { Log.LogDebug("from is null"); return new RequestChestRemoveResponse(request.RequestID, success: false, 0, hasSwitched: false, null); } if (!QolCore.ValidSlot(request.toPos.x, request.toPos.y, request.TargetInventory.m_width, request.TargetInventory.m_height)) { return new RequestChestRemoveResponse(request.RequestID, success: false, 0, hasSwitched: false, null); } ItemData itemAt2 = request.TargetInventory.GetItemAt(request.toPos.x, request.toPos.y); if (request.switchItem != null && !ItemsMatch(itemAt2, request.switchItem)) { return new RequestChestRemoveResponse(request.RequestID, success: false, 0, hasSwitched: false, null); } if (itemAt2 != null && !InventoryHelper.CanStack(itemAt, itemAt2) && request.switchItem == null) { return new RequestChestRemoveResponse(request.RequestID, success: false, 0, hasSwitched: false, null); } int num = Mathf.Min(itemAt.m_stack, dragAmount); ItemData val = itemAt.Clone(); val.m_stack = num; if (itemAt2 == null || InventoryHelper.CanStack(itemAt, itemAt2)) { if (!inventory.RemoveItem(itemAt, num)) { return new RequestChestRemoveResponse(request.RequestID, success: false, 0, hasSwitched: false, null); } if (!request.TargetInventory.AddItemToInventory(val, num, request.toPos)) { if (!inventory.AddItemToInventory(itemAt, num, fromPos)) { DropItemAtOwner(inventory, itemAt, num); } return new RequestChestRemoveResponse(request.RequestID, success: false, 0, hasSwitched: false, null); } return new RequestChestRemoveResponse(request.RequestID, success: true, num, hasSwitched: false, val, targetApplied: true); } if (dragAmount != itemAt.m_stack || itemAt2 == null || request.switchItem == null) { return new RequestChestRemoveResponse(request.RequestID, success: false, 0, hasSwitched: false, null); } ItemData val2 = itemAt.Clone(); ItemData val3 = itemAt2.Clone(); if (!request.TargetInventory.RemoveItem(itemAt2, itemAt2.m_stack) || !inventory.RemoveItem(itemAt, itemAt.m_stack)) { if (request.TargetInventory.GetItemAt(request.toPos.x, request.toPos.y) == null) { request.TargetInventory.AddItemToInventory(val3, val3.m_stack, request.toPos); } return new RequestChestRemoveResponse(request.RequestID, success: false, 0, hasSwitched: false, null); } if (!inventory.AddItemToInventory(val3, val3.m_stack, fromPos)) { if (!inventory.AddItemToInventory(val2, val2.m_stack, fromPos)) { DropItemAtOwner(inventory, val2, val2.m_stack); } if (!request.TargetInventory.AddItemToInventory(val3, val3.m_stack, request.toPos)) { DropItemAtOwner(request.TargetInventory, val3, val3.m_stack); } return new RequestChestRemoveResponse(request.RequestID, success: false, 0, hasSwitched: false, null); } if (!request.TargetInventory.AddItemToInventory(val, num, request.toPos)) { ItemData itemAt3 = inventory.GetItemAt(fromPos.x, fromPos.y); if (itemAt3 != null) { inventory.RemoveItem(itemAt3, itemAt3.m_stack); } if (!inventory.AddItemToInventory(val2, val2.m_stack, fromPos)) { DropItemAtOwner(inventory, val2, val2.m_stack); } if (!request.TargetInventory.AddItemToInventory(val3, val3.m_stack, request.toPos)) { DropItemAtOwner(request.TargetInventory, val3, val3.m_stack); } return new RequestChestRemoveResponse(request.RequestID, success: false, 0, hasSwitched: false, null); } return new RequestChestRemoveResponse(request.RequestID, success: true, num, hasSwitched: true, val, targetApplied: true); } private static bool ItemsMatch(ItemData actual, ItemData expected) { if (actual == null || expected == null || actual.m_shared == null || expected.m_shared == null) { return false; } if (ItemIdentityMatches(actual, expected)) { return actual.m_stack == expected.m_stack; } return false; } private static bool ItemIdentityMatches(ItemData actual, ItemData expected) { if (actual == null || expected == null || actual.m_shared == null || expected.m_shared == null) { return false; } if (actual.PrefabName() != expected.PrefabName() || actual.m_quality != expected.m_quality || actual.m_variant != expected.m_variant || actual.m_crafterID != expected.m_crafterID || actual.m_crafterName != expected.m_crafterName || actual.m_worldLevel != expected.m_worldLevel || actual.m_pickedUp != expected.m_pickedUp || !Mathf.Approximately(actual.m_durability, expected.m_durability)) { return false; } if ((actual.m_customData?.Count ?? 0) != (expected.m_customData?.Count ?? 0)) { return false; } if (actual.m_customData != null) { foreach (KeyValuePair<string, string> customDatum in actual.m_customData) { if (customDatum.Key == null || expected.m_customData == null || !expected.m_customData.TryGetValue(customDatum.Key, out var value) || value != customDatum.Value) { return false; } } } return true; } public static RequestConsumeResponse RequestItemConsume(this Inventory inventory, RequestConsume request) { //IL_007d: Unknown result type (might be due to invalid IL or missing references) //IL_0083: Invalid comparison between Unknown and I4 if (inventory == null || request == null || request.item == null || !QolCore.ValidSlot(request.itemPosX, request.itemPosY, inventory.m_width, inventory.m_height)) { return new RequestConsumeResponse(request?.RequestID ?? 0, null, success: false, 0); } ItemData itemAt = inventory.GetItemAt(request.itemPosX, request.itemPosY); if (itemAt == null || !ItemIdentityMatches(itemAt, request.item) || itemAt.m_shared == null || itemAt.m_stack <= 0 || (int)itemAt.m_shared.m_itemType != 2) { return new RequestConsumeResponse(request.RequestID, null, success: false, 0); } inventory.RemoveOneItem(itemAt); ItemData val = itemAt.Clone(); val.m_stack = 1; return new RequestConsumeResponse(request.RequestID, val, success: true, 1); } public static RequestMoveResponse RequestItemMove(this Inventory inventory, RequestMove request) { //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_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_0025: 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_003a: Unknown result type (might be due to invalid IL or missing references) //IL_0040: Unknown result type (might be due to invalid IL or missing references) //IL_0059: Unknown result type (might be due to invalid IL or missing references) //IL_005f: Unknown result type (might be due to invalid IL or missing references) //IL_00e0: Unknown result type (might be due to invalid IL or missing references) if (inventory == null || request == null) { return new RequestMoveResponse(0, success: false, 0); } Vector2i fromPos = request.fromPos; Vector2i toPos = request.toPos; int dragAmount = request.dragAmount; ItemData itemAt = inventory.GetItemAt(fromPos.x, fromPos.y); if (itemAt == null || !QolCore.ValidSlot(fromPos.x, fromPos.y, inventory.m_width, inventory.m_height) || !QolCore.ValidSlot(toPos.x, toPos.y, inventory.m_width, inventory.m_height) || !QolCore.ValidAmount(dragAmount, itemAt.m_stack, itemAt.m_shared?.m_maxStackSize ?? 0)) { return new RequestMoveResponse(request.RequestID, success: false, 0); } if (request.item == null || !ItemIdentityMatches(itemAt, request.item) || StringExtensionMethods.GetStableHashCode(itemAt.PrefabName()) != request.itemHash) { return new RequestMoveResponse(request.RequestID, success: false, 0); } int movedAmount; bool success = InventoryHelper.MoveItem(inventory, itemAt, dragAmount, toPos, out movedAmount); return new RequestMoveResponse(request.RequestID, success, movedAmount); } public static RequestDropResponse RequestDrop(this Inventory inventory, RequestDrop request) { //IL_005d: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Unknown result type (might be due to invalid IL or missing references) //IL_0058: Unknown result type (might be due to invalid IL or missing references) //IL_0080: Unknown result type (might be due to invalid IL or missing references) //IL_00c3: 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_0134: 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_0156: Unknown result type (might be due to invalid IL or missing references) //IL_015b: Unknown result type (might be due to invalid IL or missing references) //IL_0161: Unknown result type (might be due to invalid IL or missing references) //IL_0166: Unknown result type (might be due to invalid IL or missing references) //IL_016c: Unknown result type (might be due to invalid IL or missing references) //IL_0186: Unknown result type (might be due to invalid IL or missing references) //IL_01f9: Unknown result type (might be due to invalid IL or missing references) //IL_01d0: Unknown result type (might be due to invalid IL or missing references) //IL_01d5: Unknown result type (might be due to invalid IL or missing references) //IL_01e3: Unknown result type (might be due to invalid IL or missing references) //IL_01e9: Unknown result type (might be due to invalid IL or missing references) //IL_01a3: Unknown result type (might be due to invalid IL or missing references) if (inventory == null || request == null || request.item == null || request.amount <= 0 || !QolCore.ValidSlot(request.targetContainerSlot.x, request.targetContainerSlot.y, inventory.m_width, inventory.m_height)) { return new RequestDropResponse(request?.RequestID ?? 0, null, (ZDOID)(((??)request?.sender) ?? default(ZDOID)), success: false, 0); } if ((Object)(object)request.ServerPlayer == (Object)null) { return new RequestDropResponse(request.RequestID, null, request.sender, success: false, 0); } ItemData itemAt = inventory.GetItemAt(request.targetContainerSlot.x, request.targetContainerSlot.y); if (itemAt == null || !ItemIdentityMatches(itemAt, request.item)) { return new RequestDropResponse(request.RequestID, null, request.sender, success: false, 0); } if (!QolCore.ValidAmount(request.amount, itemAt.m_stack, itemAt.m_shared?.m_maxStackSize ?? 0)) { return new RequestDropResponse(request.RequestID, null, request.sender, success: false, 0); } int amount = request.amount; ItemData val = itemAt.Clone(); val.m_stack = amount; if (amount == 0 || !inventory.RemoveItem(itemAt, amount)) { return new RequestDropResponse(request.RequestID, null, request.sender, success: false, 0); } Transform transform = ((Component)request.ServerPlayer).transform; ItemDrop val2 = ItemDrop.DropItem(val, amount, transform.position + transform.forward + transform.up, transform.rotation); if ((Object)(object)val2 == (Object)null) { if (!inventory.AddItemToInventory(val, amount, request.targetContainerSlot)) { DropItemAtOwner(inventory, val, amount); } return new RequestDropResponse(request.RequestID, null, request.sender, success: false, 0); } val2.OnPlayerDrop(); if (((Humanoid)request.ServerPlayer).m_dropEffects != null) { ((Humanoid)request.ServerPlayer).m_dropEffects.Create(transform.position, Quaternion.identity, (Transform)null, 1f, -1, default(ZDOID)); } return new RequestDropResponse(request.RequestID, null, request.sender, success: true, amount); } } public interface IPackage { ZPackage WriteToPackage(); } public interface IRequest : IPackage { int RequestID { get; set; } long SenderID { get; set; } Inventory SourceInventory { get; } Inventory TargetInventory { get; } } public interface IResponse : IPackage { int SourceID { get; set; } bool Success { get; set; } int Amount { get; set; } } public class RequestChestAdd : IRequest, IPackage { public readonly Vector2i toPos; public readonly ItemData dragItem; public readonly bool allowSwitch; public int RequestID { get; set; } public long SenderID { get; set; } public Inventory SourceInventory { get; internal set; } public Inventory TargetInventory { get; internal set; } public RequestChestAdd(Vector2i toPos, int dragAmount, ItemData dragItem, Inventory sourceInventory, Inventory targetInventory) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) this.toPos = toPos; if (dragItem != null) { this.dragItem = dragItem.Clone(); this.dragItem.m_stack = Mathf.Min(dragAmount, this.dragItem.m_stack); allowSwitch = dragAmount == dragItem.m_stack; } SourceInventory = sourceInventory; TargetInventory = targetInventory; } public RequestChestAdd(ZPackage package) { //IL_001a: 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) ContainerPatch.ReadProtocolVersion(package); RequestID = package.ReadInt(); toPos = package.ReadVector2i(); dragItem = InventoryHelper.LoadItemFromPackage(package); allowSwitch = package.ReadBool(); } public ZPackage WriteToPackage() { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Expected O, but got Unknown //IL_001a: Unknown result type (might be due to invalid IL or missing references) ZPackage val = new ZPackage(); ContainerPatch.WriteProtocolVersion(val); val.Write(RequestID); val.Write(toPos); InventoryHelper.WriteItemToPackage(dragItem, val); val.Write(allowSwitch); return val; } } public class RequestChestAddResponse : IPackage, IResponse { public Vector2i inventoryPos; public ItemData switchItem; public int SourceID { get; set; } public bool Success { get; set; } public int Amount { get; set; } public bool ReturnToSource { get; set; } public RequestChestAddResponse(int sourceID, bool success, Vector2i inventoryPos, int amount, ItemData switchItem) { //IL_0024: 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) SourceID = sourceID; Success = success; Amount = amount; ReturnToSource = false; this.inventoryPos = inventoryPos; this.switchItem = switchItem.ClampStackSize(); } public RequestChestAddResponse(int sourceID, bool success, Vector2i inventoryPos, int amount, ItemData switchItem, bool returnToSource) : this(sourceID, success, inventoryPos, amount, switchItem) { //IL_0003: Unknown result type (might be due to invalid IL or missing references) ReturnToSource = returnToSource; } public RequestChestAddResponse(ZPackage package) { //IL_001a: 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) ContainerPatch.ReadProtocolVersion(package); SourceID = package.ReadInt(); inventoryPos = package.ReadVector2i(); Success = package.ReadBool(); Amount = package.ReadInt(); ReturnToSource = package.ReadBool(); switchItem = InventoryHelper.LoadItemFromPackage(package); } public RequestChestAddResponse() { //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Unknown result type (might be due to invalid IL or missing references) SourceID = 0; Success = false; inventoryPos = new Vector2i(-1, -1); Amount = 0; ReturnToSource = false; switchItem = null; } public ZPackage WriteToPackage() { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Expected O, but got Unknown //IL_001a: Unknown result type (might be due to invalid IL or missing references) ZPackage val = new ZPackage(); ContainerPatch.WriteProtocolVersion(val); val.Write(SourceID); val.Write(inventoryPos); val.Write(Success); val.Write(Amount); val.Write(ReturnToSource); InventoryHelper.WriteItemToPackage(switchItem, val); return val; } } public class RequestChestRemove : IRequest, IPackage { public readonly Vector2i fromPos; public readonly Vector2i toPos; public readonly int dragAmount; public readonly ItemData switchItem; public readonly ItemData item; public int RequestID { get; set; } public long SenderID { get; set; } public Inventory SourceInventory { get; internal set; } public Inventory TargetInventory { get; internal set; } public RequestChestRemove(Vector2i fromPos, Vector2i toPos, int dragAmount, ItemData switchItem, Inventory sourceInventory, Inventory targetInventory) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0049: Unknown result type (might be due to invalid IL or missing references) //IL_004f: Unknown result type (might be due to invalid IL or missing references) this.fromPos = fromPos; this.toPos = toPos; this.dragAmount = dragAmount; this.switchItem = ((switchItem != null) ? switchItem.Clone() : null); SourceInventory = sourceInventory; TargetInventory = targetInventory; object obj; if (sourceInventory == null) { obj = null; } else { ItemData itemAt = sourceInventory.GetItemAt(fromPos.x, fromPos.y); obj = ((itemAt != null) ? itemAt.Clone() : null); } item = (ItemData)obj; } public RequestChestRemove(ZPackage package) { //IL_001a: 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_0026: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Unknown result type (might be due to invalid IL or missing references) ContainerPatch.ReadProtocolVersion(package); RequestID = package.ReadInt(); fromPos = package.ReadVector2i(); toPos = package.ReadVector2i(); dragAmount = package.ReadInt(); switchItem = InventoryHelper.LoadItemFromPackage(package); item = InventoryHelper.LoadItemFromPackage(package); } public ZPackage WriteToPackage() { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Expected O, but got Unknown //IL_001a: 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) ZPackage val = new ZPackage(); ContainerPatch.WriteProtocolVersion(val); val.Write(RequestID); val.Write(fromPos); val.Write(toPos); val.Write(dragAmount); InventoryHelper.WriteItemToPackage(switchItem, val); InventoryHelper.WriteItemToPackage(item, val); return val; } } public class RequestChestRemoveResponse : IPackage, IResponse { public ItemData responseItem; public bool hasSwitched; public int SourceID { get; set; } public bool Success { get; set; } public int Amount { get; set; } public bool TargetApplied { get; set; } public RequestChestRemoveResponse(int sourceID, bool success, int amount, bool hasSwitched, ItemData responseItem, bool targetApplied = false) { SourceID = sourceID; Success = success; Amount = amount; TargetApplied = targetApplied; this.hasSwitched = hasSwitched; this.responseItem = responseItem.ClampStackSize(); } public RequestChestRemoveResponse(ZPackage package) { ContainerPatch.ReadProtocolVersion(package); SourceID = package.ReadInt(); Success = package.ReadBool(); Amount = package.ReadInt(); TargetApplied = package.ReadBool(); hasSwitched = package.ReadBool(); responseItem = InventoryHelper.LoadItemFromPackage(package); } public RequestChestRemoveResponse() { Success = false; Amount = 0; TargetApplied = false; hasSwitched = false; responseItem = null; } public ZPackage WriteToPackage() { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Expected O, but got Unknown ZPackage val = new ZPackage(); ContainerPatch.WriteProtocolVersion(val); val.Write(SourceID); val.Write(Success); val.Write(Amount); val.Write(TargetApplied); val.Write(hasSwitched); InventoryHelper.WriteItemToPackage(responseItem, val); return val; } } public class RequestConsume : IPackage { public readonly int itemPosX; public readonly int itemPosY; public readonly ItemData item; public int RequestID { get; set; } public long SenderID { get; set; } public RequestConsume(ItemData item) { RequestID = ContainerPatch.NextRequestId(); if (item == null) { itemPosX = -1; itemPosY = -1; this.item = null; } else { itemPosX = item.m_gridPos.x; itemPosY = item.m_gridPos.y; this.item = item.Clone(); } } public RequestConsume(ZPackage package) { ContainerPatch.ReadProtocolVersion(package); RequestID = package.ReadInt(); itemPosX = package.ReadInt(); itemPosY = package.ReadInt(); item = InventoryHelper.LoadItemFromPackage(package); } public ZPackage WriteToPackage() { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Expected O, but got Unknown ZPackage val = new ZPackage(); ContainerPatch.WriteProtocolVersion(val); val.Write(RequestID); val.Write(itemPosX); val.Write(itemPosY); InventoryHelper.WriteItemToPackage(item, val); return val; } } public class RequestConsumeResponse : IPackage, IResponse { public readonly ItemData item; public int SourceID { get; set; } public bool Success { get; set; } public int Amount { get; set; } public RequestConsumeResponse(ZPackage package) { ContainerPatch.ReadProtocolVersion(package); SourceID = package.ReadInt(); item = InventoryHelper.LoadItemFromPackage(package); Success = package.ReadBool(); Amount = package.ReadInt(); } public RequestConsumeResponse(ItemData item, bool success, int amount) : this(0, item, success, amount) { } public RequestConsumeResponse(int sourceID, ItemData item, bool success, int amount) { SourceID = sourceID; this.item = item.ClampStackSize(); Success = success; Amount = amount; } public RequestConsumeResponse() { item = null; } public ZPackage WriteToPackage() { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Expected O, but got Unknown ZPackage val = new ZPackage(); ContainerPatch.WriteProtocolVersion(val); val.Write(SourceID); InventoryHelper.WriteItemToPackage(item, val); val.Write(Success); val.Write(Amount); return val; } } public class RequestDrop : IPackage { public readonly Vector2i targetContainerSlot; public readonly int amount; public readonly ItemData item; public ZDOID sender; public int RequestID { get; set; } public long SenderID { get; set; } internal Player ServerPlayer { get; set; } public RequestDrop(Vector2i targetContainerSlot, int amount, ZDOID sender, ItemData item = null) { //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_0020: 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) RequestID = ContainerPatch.NextRequestId(); this.targetContainerSlot = targetContainerSlot; this.amount = amount; this.sender = sender; this.item = ((item != null) ? item.Clone() : null); } public RequestDrop(ZPackage package) { //IL_001a: 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_0032: 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) ContainerPatch.ReadProtocolVersion(package); RequestID = package.ReadInt(); targetContainerSlot = package.ReadVector2i(); amount = package.ReadInt(); sender = package.ReadZDOID(); item = InventoryHelper.LoadItemFromPackage(package); } public ZPackage WriteToPackage() { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Expected O, but got Unknown //IL_001a: 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) ZPackage val = new ZPackage(); ContainerPatch.WriteProtocolVersion(val); val.Write(RequestID); val.Write(targetContainerSlot); val.Write(amount); val.Write(sender); InventoryHelper.WriteItemToPackage(item, val); return val; } } public class RequestDropResponse : IPackage, IResponse { public readonly ItemData responseItem; public readonly ZDOID sender; public int SourceID { get; set; } public bool Success { get; set; } public int Amount { get; set; } public RequestDropResponse(ItemData responseItem, ZDOID sender, bool success, int amount) : this(0, responseItem, sender, success, amount) { }//IL_0003: Unknown result type (might be due to invalid IL or missing references) public RequestDropResponse(int sourceID, ItemData responseItem, ZDOID sender, bool success, int amount) { //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Unknown result type (might be due to invalid IL or missing references) SourceID = sourceID; this.responseItem = responseItem.ClampStackSize(); this.sender = sender; Success = success; Amount = amount; } public RequestDropResponse(ZPackage package) { //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Unknown result type (might be due to invalid IL or missing references) ContainerPatch.ReadProtocolVersion(package); SourceID = package.ReadInt(); responseItem = InventoryHelper.LoadItemFromPackage(package); sender = package.ReadZDOID(); Success = package.ReadBool(); Amount = package.ReadInt(); } public RequestDropResponse() { responseItem = null; } public ZPackage WriteToPackage() { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Expected O, but got Unknown //IL_0026: Unknown result type (might be due to invalid IL or missing references) ZPackage val = new ZPackage(); ContainerPatch.WriteProtocolVersion(val); val.Write(SourceID); InventoryHelper.WriteItemToPackage(responseItem, val); val.Write(sender); val.Write(Success); val.Write(Amount); return val; } } public class RequestMove : IRequest, IPackage { public readonly Vector2i fromPos; public readonly Vector2i toPos; public readonly int itemHash; public readonly int dragAmount; public readonly ItemData item; public int RequestID { get; set; } public long SenderID { get; set; } public Inventory SourceInventory { get; internal set; } public Inventory TargetInventory { get; internal set; } public RequestMove(ItemData itemToMove, Vector2i toPos, int dragAmount, Inventory inventory) { //IL_0055: Unknown result type (might be due to invalid IL or missing references) //IL_005a: Unknown result type (might be due to invalid IL or missing references) //IL_0060: Unknown result type (might be due to invalid IL or missing references) //IL_0061: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Unknown result type (might be due to invalid IL or missing references) if (itemToMove == null) { Log.LogWarning("Item is null"); fromPos = new Vector2i(-1, -1); this.toPos = new Vector2i(-1, -1); itemHash = 0; this.dragAmount = 0; item = null; } 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_001a: 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_0026: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Unknown result type (might be due to invalid IL or missing references) ContainerPatch.ReadProtocolVersion(package); RequestID = package.ReadInt(); fromPos = package.ReadVector2i(); toPos = package.ReadVector2i(); itemHash = package.ReadInt(); dragAmount = package.ReadInt(); item = InventoryHelper.LoadItemFromPackage(package); } public ZPackage WriteToPackage() { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Expected O, but got Unknown //IL_001a: 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) ZPackage val = new ZPackage(); ContainerPatch.WriteProtocolVersion(val); val.Write(RequestID); val.Write(fromPos); val.Write(toPos); val.Write(itemHash); val.Write(dragAmount); InventoryHelper.WriteItemToPackage(item, val); return val; } } public class RequestMoveResponse : IPackage, IResponse { public int SourceID { get; set; } public bool Success { get; set; } public int Amount { get; set; } public RequestMoveResponse(int sourceID, bool success, int amount) { SourceID = sourceID; Success = success; Amount = amount; } public RequestMoveResponse() { SourceID = 0; Success = false; Amount = 0; } public RequestMoveResponse(ZPackage package) { ContainerPatch.ReadProtocolVersion(package); SourceID = package.ReadInt(); Success = package.ReadBool(); Amount = package.ReadInt(); } public ZPackage WriteToPackage() { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Expected O, but got Unknown //IL_000b: 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_0023: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Expected O, but got Unknown ZPackage val = new ZPackage(); ContainerPatch.WriteProtocolVersion(val); val.Write(SourceID); val.Write(Success); val.Write(Amount); return val; } } public class SlotPreview { private Inventory originalInventory; private Inventory inventory; private bool hasChanges; public SlotPreview(Inventory inventory) { originalInventory = inventory; this.inventory = InventoryHelper.CopyInventory(inventory); } public void Add(Vector2i pos, ItemData item, int amount) { //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Unknown result type (might be due to invalid IL or missing references) if (item != null && amount != 0) { ItemData val = item.Clone(); val.m_stack = amount; if (pos.x >= 0 && pos.y >= 0) { inventory.AddItem(val, amount, pos.x, pos.y, false); } else { inventory.AddItem(val); } hasChanges = true; } } public void Add(Vector2i pos, ItemData item) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) Add(pos, item, item?.m_stack ?? 0); } public void Remove(Vector2i pos, ItemData item) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) Remove(pos, item, item?.m_stack ?? 0); } public void Remove(Vector2i pos, ItemData item, int amount) { //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Unknown result type (might be due to invalid IL or missing references) if (item != null && amount != 0 && inventory.GetItemAt(pos.x, pos.y) != null) { inventory.RemoveItem(inventory.GetItemAt(pos.x, pos.y), amount); hasChanges = true; } } public bool GetSlot(Vector2i pos, out ItemData item) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Unknown result type (might be due to invalid IL or missing references) ItemData itemAt = originalInventory.GetItemAt(pos.x, pos.y); item = inventory.GetItemAt(pos.x, pos.y); if (itemAt == null && item == null) { return false; } if (itemAt == null || item == null) { return true; } if (!(itemAt.m_shared.m_name != item.m_shared.m_name)) { return itemAt.m_stack != item.m_stack; } return true; } public bool HasChanges() { return hasChanges; } } public static class ConditionalWeakTableExtension { public static void TryAdd<TKey, TValue>(this ConditionalWeakTable<TKey, TValue> table, TKey key, ConditionalWeakTable<TKey, TValue>.CreateValueCallback createCallback) where TKey : class where TValue : class { table.GetValue(key, createCallback); } } public static class InventoryHelper { public delegate void MoveAction(Inventory from, Inventory to); private const int MaxCustomDataEntries = 64; private const int MaxSerializedStringLength = 4096; private static MethodBase memberwiseCloneMethod = AccessTools.Method(typeof(object), "MemberwiseClone", (Type[])null, (Type[])null); public static ItemData LoadItemFromPackage(ZPackage pkg) { //IL_0051: Unknown result type (might be due to invalid IL or missing references) //IL_0056: Unknown result type (might be due to invalid IL or missing references) //IL_010e: Unknown result type (might be due to invalid IL or missing references) //IL_011c: Unknown result type (might be due to invalid IL or missing references) //IL_0129: Unknown result type (might be due to invalid IL or missing references) //IL_0130: Expected O, but got Unknown //IL_013c: 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_016e: Unknown result type (might be due to invalid IL or missing references) if (pkg == null) { return null; } if (!pkg.ReadBool()) { return null; } string text = pkg.ReadString(); int num = pkg.ReadInt(); if (string.IsNullOrEmpty(text) || text.Length > 4096 || num <= 0 || num > 99999) { throw new InvalidDataException("Item package contains invalid name or stack data."); } float durability = pkg.ReadSingle(); Vector2i val = pkg.ReadVector2i(); int num2 = pkg.ReadInt(); int num3 = pkg.ReadInt(); long num4 = pkg.ReadLong(); string text2 = pkg.ReadString(); int worldLevel = pkg.ReadInt(); bool flag = pkg.ReadBool(); Dictionary<string, string> dictionary = new Dictionary<string, string>(); int num5 = pkg.ReadInt(); if (num5 < 0 || num5 > 64) { throw new InvalidDataException("Item package contains too many custom-data entries."); } for (int i = 0; i < num5; i++) { string text3 = pkg.ReadString(); string text4 = pkg.ReadString(); if (text3 == null || text4 == null || text3.Length > 4096 || text4.Length > 4096) { throw new InvalidDataException("Item package contains an oversized custom-data value."); } dictionary[text3] = text4; } Inventory val2 = new Inventory("tmp", (Sprite)null, Mathf.Max(1, val.x + 1), Mathf.Max(1, val.y + 1)); ItemData val3 = val2.AddItem(text, num, num2, num3, num4, text2, val, flag, false, true); if (val3 != null) { val3.m_durability = durability; val3.m_worldLevel = worldLevel; val3.m_customData = dictionary; } ItemData itemAt = val2.GetItemAt(val.x, val.y); if (itemAt != null) { val2.RemoveItem(itemAt); } return itemAt; } public static void WriteItemToPackage(ItemData itemData, ZPackage pkg) { //IL_0034: Unknown result type (might be due to invalid IL or missing references) pkg.Write(itemData != null); if (itemData == null) { return; } pkg.Write(itemData.PrefabName()); pkg.Write(itemData.m_stack); pkg.Write(itemData.m_durability); pkg.Write(itemData.m_gridPos); pkg.Write(itemData.m_quality); pkg.Write(itemData.m_variant); pkg.Write(itemData.m_crafterID); pkg.Write(itemData.m_crafterName); pkg.Write(itemData.m_worldLevel); pkg.Write(itemData.m_pickedUp); List<KeyValuePair<string, string>> list = (itemData.m_customData ?? new Dictionary<string, string>()).Where((KeyValuePair<string, string> pair) => pair.Key != null && pair.Value != null && pair.Key.Length <= 4096 && pair.Value.Length <= 4096).Take(64).ToList(); pkg.Write(list.Count); foreach (KeyValuePair<string, string> item in list) { pkg.Write(item.Key); pkg.Write(item.Value); } } public static ItemData ClampStackSize(this ItemData item) { if (item == null) { return null; } if (item.m_shared == null) { return null; } object obj; if (!((Object)(object)ObjectDB.instance == (Object)null)) { GameObject itemPrefab = ObjectDB.instance.GetItemPrefab(item.PrefabName()); obj = ((itemPrefab != null) ? itemPrefab.GetComponent<ItemDrop>() : null); } else { obj = null; } ItemDrop val = (ItemDrop)obj; if ((Object)(object)val != (Object)null && val.m_itemData?.m_shared != null) { item.m_stack = Mathf.Clamp(item.m_stack, 0, val.m_itemData.m_shared.m_maxStackSize); } return item; } public static string PrefabName(this ItemData item) { if (item == null) { return string.Empty; } if ((Object)(object)item.m_dropPrefab != (Object)null) { return ((Object)item.m_dropPrefab).name; } Log.LogWarning("Item missing prefab " + (item.m_shared?.m_name ?? "<unknown>")); return item.m_shared?.m_name ?? string.Empty; } public static bool MoveItem(Inventory inventory, ItemData item, int amount, Vector2i toPos, out int movedAmount) { //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_0051: Unknown result type (might be due to invalid IL or missing references) //IL_0057: Unknown result type (might be due to invalid IL or missing references) //IL