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 SeamlessStorage v1.0.1
SeamlessStorage.dll
Decompiled 2 days 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.Concurrent; using System.Collections.Generic; using System.Collections.ObjectModel; using System.ComponentModel; using System.Diagnostics; using System.Diagnostics.CodeAnalysis; using System.Globalization; using System.IO; using System.IO.Compression; using System.Linq; using System.Linq.Expressions; using System.Reflection; using System.Reflection.Emit; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Serialization; using System.Runtime.Serialization.Formatters.Binary; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using System.Text; using System.Text.RegularExpressions; using System.Threading; using AzuEPI; using AzuEPI.Core.Slots; using AzuExtendedPlayerInventory; using Backpacks; using BepInEx; using BepInEx.Bootstrap; using BepInEx.Configuration; using BepInEx.Logging; using EpicLootAPI; using GUIFramework; using HarmonyLib; using ItemDataManager; using JetBrains.Annotations; using Jewelcrafting; using Microsoft.CodeAnalysis; using Newtonsoft.Json; using SeamlessStorage.CraftFromChests; using SeamlessStorage.CraftFromChests.APIs; using SeamlessStorage.CraftFromChests.Compatibility; using SeamlessStorage.CraftFromChests.Compatibility.WardIsLove; using SeamlessStorage.CraftFromChests.IContainers; using SeamlessStorage.CraftFromChests.Patches; using SeamlessStorage.CraftFromChests.Util; using SeamlessStorage.CraftFromChests.Util.Functions; using SeamlessStorage.Deposit; using SeamlessStorage.Deposit.APIs; using SeamlessStorage.Deposit.APIs.Compatibility.WardIsLove; using SeamlessStorage.Deposit.Interfaces; using SeamlessStorage.Deposit.Patches.Combining; using SeamlessStorage.Deposit.Patches.Favoriting; using SeamlessStorage.Deposit.Patches.Rename; using SeamlessStorage.Deposit.Patches.Search; using SeamlessStorage.Deposit.Patches.Sorting; using SeamlessStorage.Deposit.Patches.Trash; using SeamlessStorage.Deposit.Util; using SeamlessStorage.SharedChest; using ServerSync; using TMPro; using UnityEngine; using UnityEngine.EventSystems; using UnityEngine.Events; using UnityEngine.Pool; using UnityEngine.Rendering; using UnityEngine.UI; using YamlDotNet.Core; using YamlDotNet.Core.Events; using YamlDotNet.Core.ObjectPool; using YamlDotNet.Core.Tokens; using YamlDotNet.Helpers; using YamlDotNet.Serialization; using YamlDotNet.Serialization.BufferedDeserialization; using YamlDotNet.Serialization.BufferedDeserialization.TypeDiscriminators; using YamlDotNet.Serialization.Callbacks; using YamlDotNet.Serialization.Converters; using YamlDotNet.Serialization.EventEmitters; using YamlDotNet.Serialization.NamingConventions; using YamlDotNet.Serialization.NodeDeserializers; using YamlDotNet.Serialization.NodeTypeResolvers; using YamlDotNet.Serialization.ObjectFactories; using YamlDotNet.Serialization.ObjectGraphTraversalStrategies; using YamlDotNet.Serialization.ObjectGraphVisitors; using YamlDotNet.Serialization.Schemas; using YamlDotNet.Serialization.TypeInspectors; using YamlDotNet.Serialization.TypeResolvers; using YamlDotNet.Serialization.Utilities; using YamlDotNet.Serialization.ValueDeserializers; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: IgnoresAccessChecksTo("assembly_guiutils")] [assembly: IgnoresAccessChecksTo("assembly_utils")] [assembly: IgnoresAccessChecksTo("assembly_valheim")] [assembly: IgnoresAccessChecksTo("gui_framework")] [assembly: AssemblyCompany("SeamlessStorage")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.0.1.0")] [assembly: AssemblyInformationalVersion("1.0.1")] [assembly: AssemblyProduct("SeamlessStorage")] [assembly: AssemblyTitle("SeamlessStorage")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.0.1.0")] [module: UnverifiableCode] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)] internal sealed class NullableAttribute : Attribute { public readonly byte[] NullableFlags; public NullableAttribute(byte P_0) { NullableFlags = new byte[1] { P_0 }; } public NullableAttribute(byte[] P_0) { NullableFlags = P_0; } } [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] internal sealed class NullableContextAttribute : Attribute { public readonly byte Flag; public NullableContextAttribute(byte P_0) { Flag = P_0; } } [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 JetBrains.Annotations { [AttributeUsage(AttributeTargets.All)] internal sealed class UsedImplicitlyAttribute : Attribute { public UsedImplicitlyAttribute() { } public UsedImplicitlyAttribute(ImplicitUseKindFlags useKindFlags) { } public UsedImplicitlyAttribute(ImplicitUseTargetFlags targetFlags) { } public UsedImplicitlyAttribute(ImplicitUseKindFlags useKindFlags, ImplicitUseTargetFlags targetFlags) { } } [Flags] internal enum ImplicitUseKindFlags { Default = 7, Assign = 1, Accessors = 2, InstantiatedWithFixedConstructorSignature = 4, InstantiatedNoFixedConstructorSignature = 8 } [Flags] internal enum ImplicitUseTargetFlags { Default = 1, Itself = 1, Members = 2, WithMembers = 3 } } namespace LocalizationManager { [PublicAPI] public class Localizer { private static readonly Dictionary<string, Dictionary<string, Func<string>>> PlaceholderProcessors; private static readonly Dictionary<string, Dictionary<string, string>> loadedTexts; private static readonly ConditionalWeakTable<Localization, string> localizationLanguage; private static readonly List<WeakReference<Localization>> localizationObjects; private static BaseUnityPlugin? _plugin; private static readonly List<string> fileExtensions; private static BaseUnityPlugin plugin { get { //IL_009b: Unknown result type (might be due to invalid IL or missing references) //IL_00a5: Expected O, but got Unknown if (_plugin == null) { IEnumerable<TypeInfo> source; try { source = Assembly.GetExecutingAssembly().DefinedTypes.ToList(); } catch (ReflectionTypeLoadException ex) { source = from t in ex.Types where t != null select t.GetTypeInfo(); } _plugin = (BaseUnityPlugin)Chainloader.ManagerObject.GetComponent((Type)source.First((TypeInfo t) => t.IsClass && typeof(BaseUnityPlugin).IsAssignableFrom(t))); } return _plugin; } } public static event Action? OnLocalizationComplete; private static void UpdatePlaceholderText(Localization localization, string key) { localizationLanguage.TryGetValue(localization, out string value); string text = loadedTexts[value][key]; if (PlaceholderProcessors.TryGetValue(key, out Dictionary<string, Func<string>> value2)) { text = value2.Aggregate(text, (string current, KeyValuePair<string, Func<string>> kv) => current.Replace("{" + kv.Key + "}", kv.Value())); } localization.AddWord(key, text); } public static void AddPlaceholder<T>(string key, string placeholder, ConfigEntry<T> config, Func<T, string>? convertConfigValue = null) where T : notnull { if (convertConfigValue == null) { convertConfigValue = (T val) => val.ToString(); } if (!PlaceholderProcessors.ContainsKey(key)) { PlaceholderProcessors[key] = new Dictionary<string, Func<string>>(); } config.SettingChanged += delegate { UpdatePlaceholder(); }; if (loadedTexts.ContainsKey(Localization.instance.GetSelectedLanguage())) { UpdatePlaceholder(); } void UpdatePlaceholder() { PlaceholderProcessors[key][placeholder] = () => convertConfigValue(config.Value); UpdatePlaceholderText(Localization.instance, key); } } public static void AddText(string key, string text) { List<WeakReference<Localization>> list = new List<WeakReference<Localization>>(); foreach (WeakReference<Localization> localizationObject in localizationObjects) { if (localizationObject.TryGetTarget(out var target)) { Dictionary<string, string> dictionary = loadedTexts[localizationLanguage.GetOrCreateValue(target)]; if (!target.m_translations.ContainsKey(key)) { dictionary[key] = text; target.AddWord(key, text); } } else { list.Add(localizationObject); } } foreach (WeakReference<Localization> item in list) { localizationObjects.Remove(item); } } public static void Load() { _ = plugin; } public static void LoadLocalizationLater(Localization __instance) { LoadLocalization(Localization.instance, __instance.GetSelectedLanguage()); } public static void SafeCallLocalizeComplete() { Localizer.OnLocalizationComplete?.Invoke(); } private static void LoadLocalization(Localization __instance, string language) { if (!localizationLanguage.Remove(__instance)) { localizationObjects.Add(new WeakReference<Localization>(__instance)); } localizationLanguage.Add(__instance, language); Dictionary<string, string> dictionary = new Dictionary<string, string>(); foreach (string item in from f in Directory.GetFiles(Path.GetDirectoryName(Paths.PluginPath), plugin.Info.Metadata.Name + ".*", SearchOption.AllDirectories) where fileExtensions.IndexOf(Path.GetExtension(f)) >= 0 select f) { string[] array = Path.GetFileNameWithoutExtension(item).Split('.'); if (array.Length >= 2) { string text = array[1]; if (dictionary.ContainsKey(text)) { Debug.LogWarning((object)("Duplicate key " + text + " found for " + plugin.Info.Metadata.Name + ". The duplicate file found at " + item + " will be skipped.")); } else { dictionary[text] = item; } } } byte[] array2 = LoadTranslationFromAssembly("English"); if (array2 == null) { throw new Exception("Found no English localizations in mod " + plugin.Info.Metadata.Name + ". Expected an embedded resource translations/English.json or translations/English.yml."); } Dictionary<string, string> dictionary2 = new DeserializerBuilder().IgnoreFields().Build().Deserialize<Dictionary<string, string>>(Encoding.UTF8.GetString(array2)); if (dictionary2 == null) { throw new Exception("Localization for mod " + plugin.Info.Metadata.Name + " failed: Localization file was empty."); } string text2 = null; if (language != "English") { if (dictionary.TryGetValue(language, out var value)) { text2 = File.ReadAllText(value); } else { byte[] array3 = LoadTranslationFromAssembly(language); if (array3 != null) { text2 = Encoding.UTF8.GetString(array3); } } } if (text2 == null && dictionary.TryGetValue("English", out var value2)) { text2 = File.ReadAllText(value2); } if (text2 != null) { foreach (KeyValuePair<string, string> item2 in new DeserializerBuilder().IgnoreFields().Build().Deserialize<Dictionary<string, string>>(text2) ?? new Dictionary<string, string>()) { dictionary2[item2.Key] = item2.Value; } } loadedTexts[language] = dictionary2; foreach (KeyValuePair<string, string> item3 in dictionary2) { UpdatePlaceholderText(__instance, item3.Key); } } static Localizer() { //IL_004e: Unknown result type (might be due to invalid IL or missing references) //IL_0053: Unknown result type (might be due to invalid IL or missing references) //IL_0081: Unknown result type (might be due to invalid IL or missing references) //IL_008e: Expected O, but got Unknown //IL_008f: Unknown result type (might be due to invalid IL or missing references) //IL_00bd: Unknown result type (might be due to invalid IL or missing references) //IL_00ca: Expected O, but got Unknown //IL_00f8: Unknown result type (might be due to invalid IL or missing references) //IL_0105: Expected O, but got Unknown PlaceholderProcessors = new Dictionary<string, Dictionary<string, Func<string>>>(); loadedTexts = new Dictionary<string, Dictionary<string, string>>(); localizationLanguage = new ConditionalWeakTable<Localization, string>(); localizationObjects = new List<WeakReference<Localization>>(); fileExtensions = new List<string>(2) { ".json", ".yml" }; Harmony val = new Harmony("org.bepinex.helpers.LocalizationManager"); val.Patch((MethodBase)AccessTools.DeclaredMethod(typeof(Localization), "SetupLanguage", (Type[])null, (Type[])null), (HarmonyMethod)null, new HarmonyMethod(AccessTools.DeclaredMethod(typeof(Localizer), "LoadLocalization", (Type[])null, (Type[])null)), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); val.Patch((MethodBase)AccessTools.DeclaredMethod(typeof(FejdStartup), "SetupGui", (Type[])null, (Type[])null), (HarmonyMethod)null, new HarmonyMethod(AccessTools.DeclaredMethod(typeof(Localizer), "LoadLocalizationLater", (Type[])null, (Type[])null)), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); val.Patch((MethodBase)AccessTools.DeclaredMethod(typeof(FejdStartup), "Start", (Type[])null, (Type[])null), (HarmonyMethod)null, new HarmonyMethod(AccessTools.DeclaredMethod(typeof(Localizer), "SafeCallLocalizeComplete", (Type[])null, (Type[])null)), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); } private static byte[]? LoadTranslationFromAssembly(string language) { foreach (string fileExtension in fileExtensions) { byte[] array = ReadEmbeddedFileBytes("translations." + language + fileExtension); if (array != null) { return array; } } return null; } public static byte[]? ReadEmbeddedFileBytes(string resourceFileName, Assembly? containingAssembly = null) { using MemoryStream memoryStream = new MemoryStream(); if ((object)containingAssembly == null) { containingAssembly = Assembly.GetCallingAssembly(); } string text = containingAssembly.GetManifestResourceNames().FirstOrDefault((string str) => str.EndsWith(resourceFileName, StringComparison.Ordinal)); if (text != null) { containingAssembly.GetManifestResourceStream(text)?.CopyTo(memoryStream); } return (memoryStream.Length == 0L) ? null : memoryStream.ToArray(); } } public static class LocalizationManagerVersion { public const string Version = "1.4.1"; } } namespace SeamlessStorage { public enum ChestAccessPolicy { AnyAccessible, OwnChestsOnly, OwnPrivateOnly } public static class ChestAccess { private class ConfigurationManagerAttributes { public int? Order; } private const string NotYourChest = "the server only allows your own chests."; public static ConfigEntry<ChestAccessPolicy> Policy { get; private set; } public static void Bind(BaseUnityPlugin host, ConfigSync configSync) { //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_0044: Expected O, but got Unknown if (Policy == null) { ConfigEntry<ChestAccessPolicy> val = host.Config.Bind<ChestAccessPolicy>("1 - General", "Chest Access Policy", ChestAccessPolicy.AnyAccessible, new ConfigDescription("Which chests the mod may deposit into or pull from. AnyAccessible = current behavior (ward + vanilla privacy). OwnChestsOnly = only chests you built. OwnPrivateOnly = only your Private chests. Under Own* policies, Item Drawers without a Piece are blocked (your backpack still works). [Synced with Server]", (AcceptableValueBase)null, new object[1] { new ConfigurationManagerAttributes { Order = 10 } })); configSync.AddConfigEntry<ChestAccessPolicy>(val).SynchronizedConfig = true; Policy = val; } } public static bool MatchesPolicy(Container container, long playerId) { return PolicyDenyReason(container, playerId) == null; } private static string? PolicyDenyReason(Container container, long playerId) { //IL_0066: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)container == (Object)null || Policy == null) { return null; } ChestAccessPolicy value = Policy.Value; if (value == ChestAccessPolicy.AnyAccessible) { return null; } if (IsOnLocalPlayer(((Component)container).gameObject)) { return null; } Piece val = ResolvePiece(((Component)container).gameObject, container); if ((Object)(object)val == (Object)null) { return "the server only allows your own chests."; } long creator = val.GetCreator(); if (creator == 0L || creator != playerId) { return "the server only allows your own chests."; } if (value == ChestAccessPolicy.OwnPrivateOnly && (int)container.m_privacy != 0) { return "the server only allows your own Private chests - set this chest to Private first."; } return null; } public static bool IsAllowed(Container container, long playerId) { return DenyReason(container, playerId) == null; } public static string? DenyReason(Container container, long playerId) { if ((Object)(object)container == (Object)null) { return "this chest is unavailable."; } if (!container.CheckAccess(playerId)) { return "this is someone else's private chest."; } return PolicyDenyReason(container, playerId); } public static bool MatchesPolicyForObject(GameObject go, long playerId) { if ((Object)(object)go == (Object)null || Policy == null) { return true; } if (Policy.Value == ChestAccessPolicy.AnyAccessible) { return true; } Container val = go.GetComponent<Container>() ?? go.GetComponentInParent<Container>(); if ((Object)(object)val != (Object)null) { return MatchesPolicy(val, playerId); } if (IsOnLocalPlayer(go)) { return true; } Piece val2 = ResolvePiece(go, null); if ((Object)(object)val2 == (Object)null) { return false; } long creator = val2.GetCreator(); if (creator == 0L || creator != playerId) { return false; } return true; } private static Piece? ResolvePiece(GameObject go, Container? container) { if ((Object)(object)container?.m_piece != (Object)null) { return container.m_piece; } return go.GetComponent<Piece>() ?? go.GetComponentInParent<Piece>(); } private static bool IsOnLocalPlayer(GameObject go) { Player localPlayer = Player.m_localPlayer; if ((Object)(object)localPlayer == (Object)null || (Object)(object)go == (Object)null) { return false; } Player componentInParent = go.GetComponentInParent<Player>(); if ((Object)(object)componentInParent != (Object)null) { return (Object)(object)componentInParent == (Object)(object)localPlayer; } return false; } } [BepInPlugin("ModdedWolf.SeamlessStorage", "Seamless Storage", "1.0.1")] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInIncompatibility("aedenthorn.CraftFromContainers")] [BepInIncompatibility("CFCMod")] public class SeamlessStoragePlugin : BaseUnityPlugin { public const string GUID = "ModdedWolf.SeamlessStorage"; public const string NAME = "Seamless Storage"; public const string VERSION = "1.0.1"; private static readonly string[] IncompatiblePluginGuids = new string[2] { Decode("QXp1bWF0dC5BenVBdXRvU3RvcmU="), Decode("QXp1bWF0dC5BenVDcmFmdHlCb3hlcw==") }; private static bool _modulesReady; private readonly Harmony _harmony = new Harmony("ModdedWolf.SeamlessStorage"); internal static SeamlessStoragePlugin Instance { get; private set; } internal static ManualLogSource Log { get; private set; } private static string Decode(string value) { return Encoding.UTF8.GetString(Convert.FromBase64String(value)); } private void Awake() { Instance = this; Log = ((BaseUnityPlugin)this).Logger; List<string> list = new List<string>(); string[] incompatiblePluginGuids = IncompatiblePluginGuids; foreach (string text in incompatiblePluginGuids) { if (Chainloader.PluginInfos.TryGetValue(text, out var value)) { BepInPlugin metadata = value.Metadata; string text2 = ((metadata != null) ? metadata.Name : null); text2 = ((!string.IsNullOrWhiteSpace(text2)) ? (text2 + " (" + text + ")") : text); list.Add(text2); } } if (list.Count > 0) { Log.LogError((object)("Seamless Storage found another mod that provides the same storage features. Disable conflicting chest-deposit / craft-from-container mods, then restart. Seamless Storage will not start. Conflicting: " + string.Join(", ", list))); return; } bool saveOnConfigSet = ((BaseUnityPlugin)this).Config.SaveOnConfigSet; ((BaseUnityPlugin)this).Config.SaveOnConfigSet = false; CraftFromChestsModule.Initialize((BaseUnityPlugin)(object)this); DepositModule.Initialize((BaseUnityPlugin)(object)this); _harmony.PatchAll(Assembly.GetExecutingAssembly()); ((BaseUnityPlugin)this).Config.Save(); ((BaseUnityPlugin)this).Config.SaveOnConfigSet = saveOnConfigSet; _modulesReady = true; Log.LogInfo((object)"Seamless Storage v1.0.1 loaded."); } private void Start() { if (_modulesReady) { CraftFromChestsModule.OnStart(); DepositModule.OnStart(); } } private void Update() { if (_modulesReady) { CraftFromChestsModule.OnUpdate(); DepositModule.OnUpdate(); } } private void LateUpdate() { if (_modulesReady) { CraftFromChestsModule.OnLateUpdate(); } } private void OnDestroy() { if (_modulesReady) { CraftFromChestsModule.OnDestroyed(); DepositModule.OnDestroyed(); } } } internal static class Sync { internal static readonly ConfigSync Instance = new ConfigSync("ModdedWolf.SeamlessStorage") { DisplayName = "Seamless Storage", CurrentVersion = "1.0.1", MinimumRequiredVersion = "1.0.1" }; } } namespace SeamlessStorage.SharedChest { internal static class ClientOps { internal static int TryAddFromPlayer(Container container, ItemData item, int amount) { //IL_0064: Unknown result type (might be due to invalid IL or missing references) //IL_00b6: Unknown result type (might be due to invalid IL or missing references) if (!SharedChest.IsEnabled && !SharedChest.ExternalMultiUserChestLoaded) { return 0; } if (!Object.op_Implicit((Object)(object)container) || !Object.op_Implicit((Object)(object)container.m_nview) || !container.m_nview.HasOwner()) { return 0; } if (!Object.op_Implicit((Object)(object)Player.m_localPlayer)) { return 0; } Inventory inventory = ((Humanoid)Player.m_localPlayer).GetInventory(); if (inventory == null || !inventory.ContainsItem(item)) { return 0; } amount = InvUtil.PossibleAmount(container.GetInventory(), item, new Vector2i(-1, -1), amount); if (amount <= 0) { return 0; } if (SharedChest.ExternalMultiUserChestLoaded) { int stack = item.m_stack; container.GetInventory().AddItem(item, amount, -1, -1, false); if (!inventory.ContainsItem(item)) { return stack; } return stack - item.m_stack; } int stack2 = item.m_stack; if (BeginAdd(container, item, inventory, new Vector2i(-1, -1), amount) != null) { return amount; } if (!inventory.ContainsItem(item)) { return stack2; } return Math.Max(0, stack2 - item.m_stack); } internal static AddRequest? BeginAdd(Container container, ItemData item, Inventory source, Vector2i to, int dragAmount) { //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_0041: Unknown result type (might be due to invalid IL or missing references) //IL_007f: Unknown result type (might be due to invalid IL or missing references) //IL_009e: Unknown result type (might be due to invalid IL or missing references) if (!Object.op_Implicit((Object)(object)container) || !Object.op_Implicit((Object)(object)container.m_nview) || !container.m_nview.HasOwner()) { return null; } dragAmount = InvUtil.PossibleAmount(container.GetInventory(), item, to, dragAmount); ItemData itemAt = container.GetInventory().GetItemAt(to.x, to.y); bool flag = itemAt != null && dragAmount != item.m_stack && !ItemPack.CanStack(itemAt, item); if (dragAmount <= 0 || flag || !source.ContainsItem(item)) { return null; } AddRequest addRequest = new AddRequest(to, dragAmount, item, source, container.GetInventory()); RequestStore.Track(addRequest); SlotBlock.Of(source).Block(item.m_gridPos); source.RemoveItem(item, dragAmount); if (container.m_nview.IsOwner()) { AddResponse response = OwnerOps.ApplyAdd(container.GetInventory(), addRequest); ApplyAddResponse(source, response); return null; } RpcHub.Invoke(container.m_nview, "SS_RequestItemAdd", addRequest); return addRequest; } internal static RemoveRequest? BeginRemove(Container container, ItemData item, Inventory destination, Vector2i to, int dragAmount, ItemData? switchItem) { //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_0046: 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_008e: Unknown result type (might be due to invalid IL or missing references) if (!Object.op_Implicit((Object)(object)container) || !Object.op_Implicit((Object)(object)container.m_nview) || !container.m_nview.HasOwner()) { return null; } dragAmount = InvUtil.PossibleAmount(destination, item, to, dragAmount); if (dragAmount <= 0 || SlotBlock.Of(destination).IsBlocked(to)) { return null; } RemoveRequest removeRequest = new RemoveRequest(item.m_gridPos, to, dragAmount, switchItem, container.GetInventory(), destination); if (switchItem != null && !ItemPack.CanStack(item, switchItem)) { if (dragAmount != item.m_stack) { return null; } destination.RemoveItem(switchItem); } RequestStore.Track(removeRequest); SlotBlock.Of(destination).Block(removeRequest.ToPos); if (container.m_nview.IsOwner()) { RemoveResponse response = OwnerOps.ApplyRemove(container.GetInventory(), removeRequest); ApplyRemoveResponse(destination, response); return null; } RpcHub.Invoke(container.m_nview, "SS_RequestItemRemove", removeRequest); return removeRequest; } internal static void BeginMove(Container container, ItemData item, Vector2i toPos, int dragAmount) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) MoveRequest package = new MoveRequest(item, toPos, dragAmount, container.GetInventory()); RequestStore.Track(package); RpcHub.Invoke(container.m_nview, "SS_RequestItemMove", package); } internal static void OnAddResponse(long sender, ZDOID containerId, ZPackage package) { AddResponse addResponse = new AddResponse(package); ApplyAddResponse(RequestStore.Get<AddRequest>(addResponse.SourceId)?.SourceInventory, addResponse); } internal static void ApplyAddResponse(Inventory? inventory, AddResponse response) { //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Unknown result type (might be due to invalid IL or missing references) if (inventory != null) { SlotBlock.Of(inventory).Release(response.InventoryPos); RequestStore.Forget(response); if (response.SwitchItem != null && !InvUtil.AddAt(inventory, response.SwitchItem, response.SwitchItem.m_stack, response.InventoryPos)) { DropAtPlayer(response.SwitchItem, response.SwitchItem.m_stack); } RefreshGui(inventory); } } internal static void OnRemoveResponse(long sender, ZDOID containerId, ZPackage package) { RemoveResponse removeResponse = new RemoveResponse(package); ApplyRemoveResponse(RequestStore.Get<RemoveRequest>(removeResponse.SourceId)?.TargetInventory, removeResponse); } internal static void ApplyRemoveResponse(Inventory? inventory, RemoveResponse response) { //IL_0017: 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_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_004f: Unknown result type (might be due to invalid IL or missing references) //IL_00f8: Unknown result type (might be due to invalid IL or missing references) //IL_00ff: Expected O, but got Unknown //IL_005b: Unknown result type (might be due to invalid IL or missing references) //IL_007c: Unknown result type (might be due to invalid IL or missing references) //IL_0088: Unknown result type (might be due to invalid IL or missing references) //IL_008e: Unknown result type (might be due to invalid IL or missing references) RemoveRequest removeRequest = RequestStore.Get<RemoveRequest>(response.SourceId); Vector2i val = removeRequest?.ToPos ?? Vector2i.zero; if (inventory == null) { inventory = removeRequest?.TargetInventory; } if (inventory == null) { return; } SlotBlock.Of(inventory).Release(val); RequestStore.Forget(response); if (response.Success && val.x >= 0 && val.y >= 0 && response.ResponseItem != null) { if (!InvUtil.AddAt(inventory, response.ResponseItem, response.Amount, val)) { ItemData itemAt = inventory.GetItemAt(val.x, val.y); int num = response.Amount; if (itemAt != null && ItemPack.CanStack(response.ResponseItem, itemAt)) { int num2 = itemAt.m_shared.m_maxStackSize - itemAt.m_stack; itemAt.m_stack += num2; num -= num2; } DropAtPlayer(response.ResponseItem, num); } } else if (response.ResponseItem != null) { Inventory val2 = new Inventory("ss_tmp", (Sprite)null, 1, 1); val2.AddItem(response.ResponseItem); inventory.MoveItemToThis(val2, response.ResponseItem); ItemData itemAt2 = val2.GetItemAt(0, 0); if (itemAt2 != null) { DropAtPlayer(itemAt2, itemAt2.m_stack); } } RefreshGui(inventory); } internal static void OnMoveResponse(long sender, ZDOID containerId, ZPackage package) { RequestStore.Forget(new MoveResponse(package)); } internal static void OnConsumeResponse(long sender, ZDOID containerId, ZPackage package) { ConsumeResponse consumeResponse = new ConsumeResponse(package); Player localPlayer = Player.m_localPlayer; if (!Object.op_Implicit((Object)(object)localPlayer)) { return; } SlotBlock.Of(((Humanoid)localPlayer).GetInventory()).BlockConsume = false; if (consumeResponse.Item != null && ((Humanoid)localPlayer).CanConsumeItem(consumeResponse.Item, false)) { if (Object.op_Implicit((Object)(object)consumeResponse.Item.m_shared.m_consumeStatusEffect)) { ((Character)localPlayer).m_seman.AddStatusEffect(consumeResponse.Item.m_shared.m_consumeStatusEffect, true, 0, 0f, (short)(-1)); } if ((double)consumeResponse.Item.m_shared.m_food > 0.0) { localPlayer.EatFood(consumeResponse.Item); } } } internal static void OnDropResponse(long sender, ZDOID containerId, ZPackage package) { //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Unknown result type (might be due to invalid IL or missing references) DropResponse dropResponse = new DropResponse(package); DropAtPlayer(dropResponse.Item, dropResponse.Item?.m_stack ?? 0); if (Object.op_Implicit((Object)(object)InventoryGui.instance) && Object.op_Implicit((Object)(object)Player.m_localPlayer) && dropResponse.Sender == ((Character)Player.m_localPlayer).GetZDOID()) { InventoryGui.instance.UpdateCraftingPanel(false); } } internal static void OnSalvageResponse(long sender, ZDOID containerId, ZPackage package) { ItemSalvage.OnChestItemRemoved(new SalvageResponse(package).Item); } internal static void DropAtPlayer(ItemData? item, int amount) { //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_002c: 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) //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_0055: Unknown result type (might be due to invalid IL or missing references) //IL_005a: Unknown result type (might be due to invalid IL or missing references) //IL_005f: Unknown result type (might be due to invalid IL or missing references) //IL_0069: 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_008f: Unknown result type (might be due to invalid IL or missing references) //IL_009d: Unknown result type (might be due to invalid IL or missing references) //IL_00a3: Unknown result type (might be due to invalid IL or missing references) Player localPlayer = Player.m_localPlayer; if (!((Object)(object)localPlayer == (Object)null) && item != null && amount > 0) { Transform transform = ((Component)localPlayer).transform; ItemDrop val = ItemDrop.DropItem(item, amount, transform.position + transform.forward + transform.up, transform.rotation); val.OnPlayerDrop(); ((Component)val).GetComponent<Rigidbody>().velocity = (transform.forward + Vector3.up) * 5f; ((Character)localPlayer).m_zanim.SetTrigger("interact"); ((Humanoid)localPlayer).m_dropEffects.Create(transform.position, Quaternion.identity, (Transform)null, 1f, -1, default(ZDOID)); ((Character)localPlayer).Message((MessageType)1, "$msg_dropped " + val.m_itemData.m_shared.m_name, val.m_itemData.m_stack, val.m_itemData.GetIcon(), false); } } private static void RefreshGui(Inventory inventory) { if (Object.op_Implicit((Object)(object)InventoryGui.instance) && Object.op_Implicit((Object)(object)Player.m_localPlayer) && ((Humanoid)Player.m_localPlayer).GetInventory().GetInventories().Contains(inventory)) { InventoryGui.instance.UpdateCraftingPanel(false); } } } internal static class InventoryExtensions { internal static IEnumerable<Inventory> GetInventories(this Inventory inventory) { yield return inventory; } } internal abstract class InvOwner { internal abstract ZNetView View { get; } internal abstract Inventory Inventory { get; } internal virtual bool IsValid() { if (Object.op_Implicit((Object)(object)View) && View.HasOwner()) { return Inventory != null; } return false; } internal static InvOwner? Of(Inventory? inventory) { if (inventory == null) { return null; } if (PlayerLink.TryGet(inventory, out PlayerInvOwner owner)) { return owner; } if (ContainerLink.TryGet(inventory, out ContainerInvOwner owner2)) { return owner2; } return null; } internal static InvOwner? Of(ItemData? item) { if (item == null) { return null; } if (InventoryInterceptPatch.ItemInventory.TryGetValue(item, out Inventory value)) { return Of(value); } return null; } } internal sealed class ContainerInvOwner : InvOwner { internal Container Container { get; } internal override ZNetView View => Container.m_nview; internal override Inventory Inventory => Container.GetInventory(); internal ContainerInvOwner(Container container) { Container = container; } } internal sealed class PlayerInvOwner : InvOwner { private readonly Inventory _inventory; internal Humanoid Humanoid { get; } internal override ZNetView View => ((Character)Humanoid).m_nview; internal override Inventory Inventory => _inventory; internal PlayerInvOwner(Humanoid humanoid, Inventory inventory) { Humanoid = humanoid; _inventory = inventory; } } internal sealed class ContainerLink : MonoBehaviour { private static readonly ConditionalWeakTable<Inventory, ContainerInvOwner> Map = new ConditionalWeakTable<Inventory, ContainerInvOwner>(); private Inventory? _inventory; private void Awake() { Container container = default(Container); if (!((Component)this).TryGetComponent<Container>(ref container)) { return; } _inventory = container.GetInventory(); if (_inventory != null) { Map.GetValue(_inventory, (Inventory _) => new ContainerInvOwner(container)); } } private void OnDestroy() { if (_inventory != null) { Map.Remove(_inventory); } } internal static bool TryGet(Inventory inventory, out ContainerInvOwner? owner) { return Map.TryGetValue(inventory, out owner); } } internal sealed class PlayerLink : MonoBehaviour { private static readonly ConditionalWeakTable<Inventory, PlayerInvOwner> Map = new ConditionalWeakTable<Inventory, PlayerInvOwner>(); private Inventory? _inventory; private void Awake() { Link(); } private void Start() { Link(); } private void Link() { Humanoid humanoid = default(Humanoid); if (!((Component)this).TryGetComponent<Humanoid>(ref humanoid)) { return; } _inventory = humanoid.GetInventory(); if (_inventory == null) { return; } foreach (Inventory sub in _inventory.GetInventories()) { Map.GetValue(sub, (Inventory _) => new PlayerInvOwner(humanoid, sub)); } } private void OnDestroy() { if (_inventory == null) { return; } foreach (Inventory inventory in _inventory.GetInventories()) { Map.Remove(inventory); } } internal static bool TryGet(Inventory inventory, out PlayerInvOwner? owner) { return Map.TryGetValue(inventory, out owner); } } internal static class InvUtil { internal static Inventory Copy(Inventory target) { //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0053: Expected O, but got Unknown return new Inventory(target.m_name, target.m_bkg, target.m_width, target.m_height) { m_inventory = new List<ItemData>(from x in target.GetAllItems() select x.Clone()) }; } internal static bool AddAt(Inventory target, ItemData item, int amount, Vector2i pos) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_004f: Unknown result type (might be due to invalid IL or missing references) //IL_0055: Unknown result type (might be due to invalid IL or missing references) if (amount <= 0) { return false; } ItemData itemAt = target.GetItemAt(pos.x, pos.y); if (itemAt != null) { if (!ItemPack.CanStack(itemAt, item)) { return false; } if (itemAt.m_stack + amount > itemAt.m_shared.m_maxStackSize) { return false; } } ItemData val = ItemPack.CloneDeep(item); val.m_stack = amount; return target.AddItem(val, amount, pos.x, pos.y, false); } internal static bool MoveItem(Inventory inventory, ItemData item, int amount, Vector2i toPos, out int movedAmount) { //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_006d: Unknown result type (might be due to invalid IL or missing references) //IL_0073: Unknown result type (might be due to invalid IL or missing references) //IL_00bb: Unknown result type (might be due to invalid IL or missing references) //IL_00c1: Unknown result type (might be due to invalid IL or missing references) movedAmount = 0; if (item == null) { return false; } ItemData itemAt = inventory.GetItemAt(toPos.x, toPos.y); if (itemAt == item) { movedAmount = amount; return true; } if (itemAt == null) { movedAmount = amount; return inventory.MoveItemToThis(inventory, item, amount, toPos.x, toPos.y); } if (ItemPack.CanStack(itemAt, item)) { movedAmount = Mathf.Min(amount, itemAt.m_shared.m_maxStackSize - itemAt.m_stack); return inventory.MoveItemToThis(inventory, item, movedAmount, toPos.x, toPos.y); } if (item.m_stack != amount) { return false; } inventory.RemoveItem(item); inventory.MoveItemToThis(inventory, itemAt, itemAt.m_stack, item.m_gridPos.x, item.m_gridPos.y); inventory.MoveItemToThis(inventory, item, amount, toPos.x, toPos.y); movedAmount = amount; return true; } internal static int PossibleAmount(Inventory inventoryTo, ItemData dragItem, Vector2i to, int dragAmount) { //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Unknown result type (might be due to invalid IL or missing references) dragAmount = ((dragAmount >= 0) ? Mathf.Min(dragAmount, dragItem.m_stack) : dragItem.m_stack); if (to.x >= 0 && to.y >= 0) { ItemData itemAt = inventoryTo.GetItemAt(to.x, to.y); if (itemAt != null && dragAmount < dragItem.m_stack) { if (ItemPack.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; } } internal static class ItemPack { private static readonly MethodInfo MemberwiseCloneMethod = AccessTools.Method(typeof(object), "MemberwiseClone", (Type[])null, (Type[])null); internal static void Write(ItemData? item, ZPackage pkg) { //IL_0034: Unknown result type (might be due to invalid IL or missing references) pkg.Write(item != null); if (item == null) { return; } pkg.Write(PrefabName(item)); pkg.Write(item.m_stack); pkg.Write(item.m_durability); pkg.Write(item.m_gridPos); pkg.Write(item.m_quality); pkg.Write(item.m_variant); pkg.Write(item.m_crafterID); pkg.Write(item.m_crafterName); pkg.Write(item.m_worldLevel); pkg.Write(item.m_pickedUp); pkg.Write(item.m_customData.Count); foreach (KeyValuePair<string, string> customDatum in item.m_customData) { pkg.Write(customDatum.Key); pkg.Write(customDatum.Value); } } internal static ItemData? Read(ZPackage pkg) { //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_008f: Unknown result type (might be due to invalid IL or missing references) //IL_0097: 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_00a6: Expected O, but got Unknown //IL_00ab: Unknown result type (might be due to invalid IL or missing references) //IL_00c5: Unknown result type (might be due to invalid IL or missing references) //IL_00cb: Unknown result type (might be due to invalid IL or missing references) if (!pkg.ReadBool()) { return null; } string text = pkg.ReadString(); int num = pkg.ReadInt(); float num2 = pkg.ReadSingle(); Vector2i val = pkg.ReadVector2i(); int num3 = pkg.ReadInt(); int num4 = pkg.ReadInt(); long num5 = pkg.ReadLong(); string text2 = pkg.ReadString(); int num6 = pkg.ReadInt(); bool flag = pkg.ReadBool(); Dictionary<string, string> dictionary = new Dictionary<string, string>(); int num7 = pkg.ReadInt(); for (int i = 0; i < num7; i++) { dictionary[pkg.ReadString()] = pkg.ReadString(); } Inventory val2 = new Inventory("ss_tmp", (Sprite)null, val.x + 1, val.y + 1); val2.AddItem(text, num, num2, val, false, num3, num4, num5, text2, dictionary, num6, flag, false, false); ItemData itemAt = val2.GetItemAt(val.x, val.y); if (itemAt != null) { val2.RemoveItem(itemAt); } return itemAt; } internal static string PrefabName(ItemData item) { if ((Object)(object)item.m_dropPrefab != (Object)null) { return ((Object)item.m_dropPrefab).name; } return item.m_shared.m_name; } internal static bool CanStack(ItemData a, ItemData b) { if (a.m_shared.m_name == b.m_shared.m_name && (a.m_shared.m_maxQuality <= 1 || b.m_quality == a.m_quality)) { return a.m_shared.m_maxStackSize != 1; } return false; } internal static ItemData CloneDeep(ItemData item) { //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Expected O, but got Unknown ItemData obj = item.Clone(); obj.m_shared = (SharedData)MemberwiseCloneMethod.Invoke(item.m_shared, null); return obj; } internal static ItemData? ClampStack(ItemData? item) { if (item == null || (Object)(object)ObjectDB.instance == (Object)null) { return item; } GameObject itemPrefab = ObjectDB.instance.GetItemPrefab(PrefabName(item)); if ((Object)(object)itemPrefab == (Object)null) { return item; } ItemDrop component = itemPrefab.GetComponent<ItemDrop>(); if ((Object)(object)component != (Object)null) { item.m_shared.m_maxStackSize = component.m_itemData.m_shared.m_maxStackSize; } return item; } } internal static class OwnerOps { internal static void OnAdd(long sender, ZDOID containerId, ZPackage package) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) Handle(containerId, sender, "SS_RequestItemAddResponse", ApplyAdd, new AddRequest(package)); } internal static void OnRemove(long sender, ZDOID containerId, ZPackage package) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) Handle(containerId, sender, "SS_RequestItemRemoveResponse", ApplyRemove, new RemoveRequest(package)); } internal static void OnMove(long sender, ZDOID containerId, ZPackage package) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) Handle(containerId, sender, "SS_RequestItemMoveResponse", ApplyMove, new MoveRequest(package)); } internal static void OnConsume(long sender, ZDOID containerId, ZPackage package) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) Handle(containerId, sender, "SS_RequestItemConsumeResponse", ApplyConsume, new ConsumeRequest(package)); } internal static void OnDrop(long sender, ZDOID containerId, ZPackage package) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) Handle(containerId, sender, "SS_RequestItemDropResponse", ApplyDrop, new DropRequest(package)); } internal static void OnSalvage(long sender, ZDOID containerId, ZPackage package) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) Handle(containerId, sender, "SS_RequestItemSalvageResponse", ApplySalvage, new SalvageRequest(package)); } internal static void OnSort(long sender, ZDOID containerId, int mode) { //IL_0005: Unknown result type (might be due to invalid IL or missing references) ZDO zDO = ZDOMan.instance.GetZDO(containerId); ZNetView val = ((zDO != null) ? ZNetScene.instance.FindInstance(zDO) : null); if (Object.op_Implicit((Object)(object)val) && val.IsOwner()) { Container componentInChildren = ((Component)val).GetComponentInChildren<Container>(); if (!((Object)(object)componentInChildren == (Object)null)) { InventorySorter.Sort(componentInChildren.GetInventory(), (SortMode)mode, isPlayer: false, ignoreHotbar: false); } } } private static void Handle<TIn, TOut>(ZDOID containerId, long target, string responseRpc, Func<Inventory, TIn, TOut> apply, TIn input) where TIn : ISsPackage where TOut : ISsPackage, new() { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_0079: Unknown result type (might be due to invalid IL or missing references) ZDO zDO = ZDOMan.instance.GetZDO(containerId); ZNetView val = ((zDO != null) ? ZNetScene.instance.FindInstance(zDO) : null); TOut val2; if (!Object.op_Implicit((Object)(object)val) || !val.IsOwner()) { val2 = Fallback<TOut>(input); } else { Container componentInChildren = ((Component)val).GetComponentInChildren<Container>(); val2 = (((Object)(object)componentInChildren != (Object)null) ? apply(componentInChildren.GetInventory(), input) : Fallback<TOut>(input)); } ZRoutedRpc.instance.InvokeRoutedRPC(target, responseRpc, new object[2] { containerId, val2.Write() }); } private static TOut Fallback<TOut>(ISsPackage input) where TOut : ISsPackage, new() { //IL_0066: 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_006b: Unknown result type (might be due to invalid IL or missing references) TOut val = new TOut(); if (input is ISsRequest ssRequest && val is ISsResponse ssResponse) { ssResponse.SourceId = ssRequest.RequestId; } if (input is AddRequest addRequest && val is AddResponse addResponse) { addResponse.SwitchItem = addRequest.DragItem; addResponse.InventoryPos = addRequest.DragItem?.m_gridPos ?? Vector2i.zero; } else if (input is RemoveRequest removeRequest && val is RemoveResponse removeResponse) { removeResponse.ResponseItem = removeRequest.SwitchItem; } return val; } internal static AddResponse ApplyAdd(Inventory inventory, AddRequest request) { //IL_000f: Unknown result type (might be due to invalid IL or missing references) if (request.DragItem == null) { return new AddResponse(request.RequestId, success: false, Vector2i.zero, 0, request.DragItem); } if (request.ToPos.x < 0 || request.ToPos.y < 0) { return AddAny(inventory, request); } return AddSlot(inventory, request); } private static AddResponse AddSlot(Inventory inventory, AddRequest 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_0077: Unknown result type (might be due to invalid IL or missing references) //IL_007c: Unknown result type (might be due to invalid IL or missing references) //IL_008e: Unknown result type (might be due to invalid IL or missing references) if (!CanStackSlot(inventory, request, out int stackSpace, out ItemData removed)) { return new AddResponse(request.RequestId, success: false, request.DragItem.m_gridPos, 0, request.DragItem); } bool flag = InvUtil.AddAt(inventory, request.DragItem, stackSpace, request.ToPos); if (!flag) { stackSpace = 0; } if (!flag || stackSpace != request.DragItem.m_stack) { removed = request.DragItem; removed.m_stack = request.DragItem.m_stack - stackSpace; removed.m_gridPos = request.DragItem.m_gridPos; } return new AddResponse(request.RequestId, flag, request.DragItem.m_gridPos, stackSpace, removed); } private static bool CanStackSlot(Inventory inventory, AddRequest request, out int stackSpace, out ItemData? removed) { ItemData itemAt = inventory.GetItemAt(request.ToPos.x, request.ToPos.y); removed = null; if (itemAt == null) { stackSpace = request.DragItem.m_stack; return true; } if (ItemPack.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); removed = itemAt; stackSpace = request.DragItem.m_stack; return true; } stackSpace = 0; return false; } private static AddResponse AddAny(Inventory inventory, AddRequest 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("ss_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 AddResponse(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 AddResponse(request.RequestId, success, request.DragItem.m_gridPos, num, val2); } internal static RemoveResponse ApplyRemove(Inventory inventory, RemoveRequest request) { //IL_00c4: Unknown result type (might be due to invalid IL or missing references) ItemData itemAt = inventory.GetItemAt(request.FromPos.x, request.FromPos.y); if (itemAt == null) { return new RemoveResponse(request.RequestId, success: false, 0, null); } int num = 0; ItemData switchItem = request.SwitchItem; bool success; if (switchItem == null) { num = Mathf.Min(itemAt.m_stack, request.DragAmount); success = inventory.RemoveItem(itemAt, num); } else if (ItemPack.CanStack(itemAt, switchItem)) { num = Mathf.Min(switchItem.m_shared.m_maxStackSize - switchItem.m_stack, request.DragAmount); success = inventory.RemoveItem(itemAt, num); } else { if (request.DragAmount < itemAt.m_stack) { return new RemoveResponse(request.RequestId, success: false, 0, request.SwitchItem); } num = Mathf.Min(itemAt.m_stack, request.DragAmount); success = inventory.RemoveItem(itemAt, request.DragAmount); if (!InvUtil.AddAt(inventory, switchItem, switchItem.m_stack, request.FromPos)) { ClientOps.DropAtPlayer(switchItem, switchItem.m_stack); } } ItemData val = itemAt.Clone(); val.m_stack = num; return new RemoveResponse(request.RequestId, success, num, val); } private static MoveResponse ApplyMove(Inventory inventory, MoveRequest request) { //IL_0058: Unknown result type (might be due to invalid IL or missing references) ItemData itemAt = inventory.GetItemAt(request.FromPos.x, request.FromPos.y); if (itemAt == null) { return new MoveResponse(request.RequestId, success: false, 0); } if (StringExtensionMethods.GetStableHashCode(ItemPack.PrefabName(itemAt)) != request.ItemHash) { return new MoveResponse(request.RequestId, success: false, 0); } int movedAmount; bool success = InvUtil.MoveItem(inventory, itemAt, request.DragAmount, request.ToPos, out movedAmount); return new MoveResponse(request.RequestId, success, movedAmount); } private static ConsumeResponse ApplyConsume(Inventory inventory, ConsumeRequest request) { ItemData itemAt = inventory.GetItemAt(request.ItemPosX, request.ItemPosY); if (itemAt == null || itemAt.m_stack <= 0) { return ConsumeResponse.FromItem(null); } inventory.RemoveOneItem(itemAt); ItemData obj = itemAt.Clone(); obj.m_stack = 1; return ConsumeResponse.FromItem(obj); } private static DropResponse ApplyDrop(Inventory inventory, DropRequest request) { //IL_0022: 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_004d: Unknown result type (might be due to invalid IL or missing references) ItemData itemAt = inventory.GetItemAt(request.Slot.x, request.Slot.y); if (itemAt == null) { return new DropResponse(null, request.Sender); } int num = Mathf.Min(itemAt.m_stack, request.Amount); inventory.RemoveItem(itemAt, num); if (num == 0) { return new DropResponse(null, request.Sender); } ItemData obj = itemAt.Clone(); obj.m_stack = num; return new DropResponse(obj, request.Sender); } private static SalvageResponse ApplySalvage(Inventory inventory, SalvageRequest request) { ItemData itemAt = inventory.GetItemAt(request.Slot.x, request.Slot.y); if (itemAt == null || request.Amount <= 0 || itemAt.m_stack < request.Amount || itemAt.m_quality != request.Quality || StringExtensionMethods.GetStableHashCode(ItemPack.PrefabName(itemAt)) != request.ItemHash) { return new SalvageResponse(); } ItemData obj = itemAt.Clone(); obj.m_stack = request.Amount; inventory.RemoveItem(itemAt, request.Amount); return new SalvageResponse(obj); } } internal sealed class AddRequest : ISsRequest, ISsPackage { internal readonly Vector2i ToPos; internal readonly ItemData? DragItem; internal readonly bool AllowSwitch; public int RequestId { get; set; } public Inventory? SourceInventory { get; } public Inventory? TargetInventory { get; } internal AddRequest(Vector2i toPos, int dragAmount, ItemData? dragItem, Inventory? source, Inventory? target) { //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) ToPos = toPos; SourceInventory = source; TargetInventory = target; if (dragItem != null) { DragItem = dragItem.Clone(); DragItem.m_stack = Mathf.Min(dragAmount, DragItem.m_stack); AllowSwitch = dragAmount == dragItem.m_stack; } } internal AddRequest(ZPackage pkg) { //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Unknown result type (might be due to invalid IL or missing references) RequestId = pkg.ReadInt(); ToPos = pkg.ReadVector2i(); DragItem = ItemPack.Read(pkg); AllowSwitch = pkg.ReadBool(); } public ZPackage Write() { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Expected O, but got Unknown //IL_0014: Unknown result type (might be due to invalid IL or missing references) ZPackage val = new ZPackage(); val.Write(RequestId); val.Write(ToPos); ItemPack.Write(DragItem, val); val.Write(AllowSwitch); return val; } } internal sealed class AddResponse : ISsResponse, ISsPackage { internal bool Success; internal int Amount; internal Vector2i InventoryPos; internal ItemData? SwitchItem; public int SourceId { get; set; } public AddResponse() { } internal AddResponse(int sourceId, bool success, Vector2i inventoryPos, int amount, ItemData? switchItem) { //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) SourceId = sourceId; Success = success; InventoryPos = inventoryPos; Amount = amount; SwitchItem = ItemPack.ClampStack(switchItem); } internal AddResponse(ZPackage pkg) { //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Unknown result type (might be due to invalid IL or missing references) SourceId = pkg.ReadInt(); InventoryPos = pkg.ReadVector2i(); Success = pkg.ReadBool(); Amount = pkg.ReadInt(); SwitchItem = ItemPack.Read(pkg); } public ZPackage Write() { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Expected O, but got Unknown //IL_0014: Unknown result type (might be due to invalid IL or missing references) ZPackage val = new ZPackage(); val.Write(SourceId); val.Write(InventoryPos); val.Write(Success); val.Write(Amount); ItemPack.Write(SwitchItem, val); return val; } } internal sealed class RemoveRequest : ISsRequest, ISsPackage { internal readonly Vector2i FromPos; internal readonly Vector2i ToPos; internal readonly int DragAmount; internal readonly ItemData? SwitchItem; public int RequestId { get; set; } public Inventory? SourceInventory { get; } public Inventory? TargetInventory { get; } internal RemoveRequest(Vector2i fromPos, Vector2i toPos, int dragAmount, ItemData? switchItem, Inventory? source, Inventory? target) { //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) FromPos = fromPos; ToPos = toPos; DragAmount = dragAmount; SwitchItem = ((switchItem != null) ? switchItem.Clone() : null); SourceInventory = source; TargetInventory = target; } internal RemoveRequest(ZPackage pkg) { //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Unknown result type (might be due to invalid IL or missing references) RequestId = pkg.ReadInt(); FromPos = pkg.ReadVector2i(); ToPos = pkg.ReadVector2i(); DragAmount = pkg.ReadInt(); SwitchItem = ItemPack.Read(pkg); } public ZPackage Write() { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Expected O, but got Unknown //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Unknown result type (might be due to invalid IL or missing references) ZPackage val = new ZPackage(); val.Write(RequestId); val.Write(FromPos); val.Write(ToPos); val.Write(DragAmount); ItemPack.Write(SwitchItem, val); return val; } } internal sealed class RemoveResponse : ISsResponse, ISsPackage { internal bool Success; internal int Amount; internal ItemData? ResponseItem; public int SourceId { get; set; } public RemoveResponse() { } internal RemoveResponse(int sourceId, bool success, int amount, ItemData? responseItem) { SourceId = sourceId; Success = success; Amount = amount; ResponseItem = ItemPack.ClampStack(responseItem); } internal RemoveResponse(ZPackage pkg) { SourceId = pkg.ReadInt(); Success = pkg.ReadBool(); Amount = pkg.ReadInt(); ResponseItem = ItemPack.Read(pkg); } public ZPackage Write() { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Expected O, but got Unknown ZPackage val = new ZPackage(); val.Write(SourceId); val.Write(Success); val.Write(Amount); ItemPack.Write(ResponseItem, val); return val; } } internal sealed class MoveRequest : ISsRequest, ISsPackage { internal readonly Vector2i FromPos; internal readonly Vector2i ToPos; internal readonly int ItemHash; internal readonly int DragAmount; public int RequestId { get; set; } public Inventory? SourceInventory { get; } public Inventory? TargetInventory { get; } internal MoveRequest(ItemData? item, Vector2i toPos, int dragAmount, Inventory? inventory) { //IL_0036: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_0041: 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_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Unknown result type (might be due to invalid IL or missing references) SourceInventory = inventory; TargetInventory = inventory; if (item == null) { FromPos = new Vector2i(-1, -1); ToPos = new Vector2i(-1, -1); return; } FromPos = item.m_gridPos; ToPos = toPos; ItemHash = StringExtensionMethods.GetStableHashCode(ItemPack.PrefabName(item)); DragAmount = dragAmount; } internal MoveRequest(ZPackage pkg) { //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Unknown result type (might be due to invalid IL or missing references) RequestId = pkg.ReadInt(); FromPos = pkg.ReadVector2i(); ToPos = pkg.ReadVector2i(); ItemHash = pkg.ReadInt(); DragAmount = pkg.ReadInt(); } public ZPackage Write() { //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_0011: 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_001d: 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_0029: 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_0042: Expected O, but got Unknown ZPackage val = new ZPackage(); val.Write(RequestId); val.Write(FromPos); val.Write(ToPos); val.Write(ItemHash); val.Write(DragAmount); return val; } } internal sealed class MoveResponse : ISsResponse, ISsPackage { internal bool Success; internal int Amount; public int SourceId { get; set; } public MoveResponse() { } internal MoveResponse(int sourceId, bool success, int amount) { SourceId = sourceId; Success = success; Amount = amount; } internal MoveResponse(ZPackage pkg) { SourceId = pkg.ReadInt(); Success = pkg.ReadBool(); Amount = pkg.ReadInt(); } public ZPackage Write() { //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_0011: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Expected O, but got Unknown ZPackage val = new ZPackage(); val.Write(SourceId); val.Write(Success); val.Write(Amount); return val; } } internal sealed class ConsumeRequest : ISsPackage { internal readonly int ItemPosX; internal readonly int ItemPosY; internal ConsumeRequest(ItemData item) { ItemPosX = item.m_gridPos.x; ItemPosY = item.m_gridPos.y; } internal ConsumeRequest(ZPackage pkg) { ItemPosX = pkg.ReadInt(); ItemPosY = pkg.ReadInt(); } public ZPackage Write() { //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_0011: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Expected O, but got Unknown ZPackage val = new ZPackage(); val.Write(ItemPosX); val.Write(ItemPosY); return val; } } internal sealed class ConsumeResponse : ISsPackage { internal ItemData? Item; public ConsumeResponse() { } internal static ConsumeResponse FromItem(ItemData? item) { return new ConsumeResponse { Item = item }; } internal ConsumeResponse(ZPackage pkg) { Item = ItemPack.Read(pkg); } public ZPackage Write() { //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(); ItemPack.Write(Item, val); return val; } } internal sealed class DropRequest : ISsPackage { internal readonly Vector2i Slot; internal readonly int Amount; internal readonly ZDOID Sender; internal DropRequest(Vector2i slot, int amount, ZDOID sender) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Unknown result type (might be due to invalid IL or missing references) Slot = slot; Amount = amount; Sender = sender; } internal DropRequest(ZPackage pkg) { //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Unknown result type (might be due to invalid IL or missing references) Slot = pkg.ReadVector2i(); Amount = pkg.ReadInt(); Sender = pkg.ReadZDOID(); } public ZPackage Write() { //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_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_001d: 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_002a: Expected O, but got Unknown ZPackage val = new ZPackage(); val.Write(Slot); val.Write(Amount); val.Write(Sender); return val; } } internal sealed class SalvageRequest : ISsPackage { internal readonly Vector2i Slot; internal readonly int Amount; internal readonly int ItemHash; internal readonly int Quality; internal SalvageRequest(ItemData item, int amount) { //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Unknown result type (might be due to invalid IL or missing references) Slot = item.m_gridPos; Amount = amount; ItemHash = StringExtensionMethods.GetStableHashCode(ItemPack.PrefabName(item)); Quality = item.m_quality; } internal SalvageRequest(ZPackage pkg) { //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Unknown result type (might be due to invalid IL or missing references) Slot = pkg.ReadVector2i(); Amount = pkg.ReadInt(); ItemHash = pkg.ReadInt(); Quality = pkg.ReadInt(); } public ZPackage Write() { //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_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_001d: 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_0036: Expected O, but got Unknown ZPackage val = new ZPackage(); val.Write(Slot); val.Write(Amount); val.Write(ItemHash); val.Write(Quality); return val; } } internal sealed class SalvageResponse : ISsPackage { internal ItemData? Item; public SalvageResponse() { } internal SalvageResponse(ItemData? item) { Item = item; } internal SalvageResponse(ZPackage pkg) { Item = ItemPack.Read(pkg); } public ZPackage Write() { //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(); ItemPack.Write(Item, val); return val; } } internal sealed class DropResponse : ISsPackage { internal ItemData? Item; internal ZDOID Sender; public DropResponse() { } internal DropResponse(ItemData? item, ZDOID sender) { //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) Item = item; Sender = sender; } internal DropResponse(ZPackage pkg) { //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Unknown result type (might be due to invalid IL or missing references) Item = ItemPack.Read(pkg); Sender = pkg.ReadZDOID(); } public ZPackage Write() { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Expected O, but got Unknown //IL_0014: Unknown result type (might be due to invalid IL or missing references) ZPackage val = new ZPackage(); ItemPack.Write(Item, val); val.Write(Sender); return val; } } [HarmonyPatch] internal static class ContainerOpenPatch { [HarmonyPatch(typeof(Container), "Awake")] [HarmonyPostfix] private static void ContainerAwake(Container __instance) { if (!SharedChest.ExternalMultiUserChestLoaded) { ((Component)__instance).gameObject.AddComponent<ContainerLink>(); if (!Object.op_Implicit((Object)(object)__instance.m_nview)) { __instance.m_nview = (Object.op_Implicit((Object)(object)__instance.m_rootObjectOverride) ? ((Component)__instance.m_rootObjectOverride).GetComponent<ZNetView>() : ((Component)__instance).GetComponent<ZNetView>()); } } } [HarmonyPatch(typeof(Container), "RPC_RequestOpen")] [HarmonyPrefix] private static bool RequestOpen(Container __instance, long uid, long playerID) { //IL_009a: Unknown result type (might be due to invalid IL or missing references) //IL_005d: Unknown result type (might be due to invalid IL or missing references) if (!SharedChest.IsEnabled) { return true; } if (!__instance.m_nview.IsOwner()) { return true; } if (!__instance.CheckAccess(playerID)) { __instance.m_nview.InvokeRPC(uid, "RPC_OpenResponse", new object[1] { false }); return false; } if (IsInUseByOther(__instance, uid)) { ZDOMan.instance.ForceSendZDO(uid, __instance.m_nview.GetZDO().m_uid); __instance.m_nview.InvokeRPC(uid, "RPC_OpenResponse", new object[1] { true }); return false; } ZDOMan.instance.ForceSendZDO(uid, __instance.m_nview.GetZDO().m_uid); __instance.m_nview.GetZDO().SetOwner(uid); __instance.m_nview.InvokeRPC(uid, "RPC_OpenResponse", new object[1] { true }); return false; } [HarmonyPatch(typeof(Container), "RPC_RequestStack")] [HarmonyPrefix] private static bool RequestStack(Container __instance, long uid, long playerID) { //IL_009a: Unknown result type (might be due to invalid IL or missing references) //IL_005d: Unknown result type (might be due to invalid IL or missing references) if (!SharedChest.IsEnabled) { return true; } if (!__instance.m_nview.IsOwner()) { return true; } if (!__instance.CheckAccess(playerID)) { __instance.m_nview.InvokeRPC(uid, "RPC_StackResponse", new object[1] { false }); return false; } if (IsInUseByOther(__instance, uid)) { ZDOMan.instance.ForceSendZDO(uid, __instance.m_nview.GetZDO().m_uid); __instance.m_nview.InvokeRPC(uid, "RPC_StackResponse", new object[1] { true }); return false; } ZDOMan.instance.ForceSendZDO(uid, __instance.m_nview.GetZDO().m_uid); __instance.m_nview.GetZDO().SetOwner(uid); __instance.m_nview.InvokeRPC(uid, "RPC_StackResponse", new object[1] { true }); return false; } private static bool IsInUseByOther(Container container, long requesterUid) { if (container.IsInUse() || (Object.op_Implicit((Object)(object)container.m_wagon) && container.m_wagon.InUse())) { return requesterUid != ZNet.GetUID(); } return false; } [HarmonyPatch(typeof(Container), "Load")] [HarmonyPrefix] private static void AllowNonOwnerLoad(Container __instance, ref bool __state) { __state = false; if (SharedChest.IsEnabled && Object.op_Implicit((Object)(object)__instance) && Object.op_Implicit((Object)(object)__instance.m_nview) && __instance.m_nview.IsValid() && !__instance.m_nview.IsOwner() && __instance.IsInUse()) { AccessTools.Field(typeof(Container), "m_inUse")?.SetValue(__instance, false); __state = true; } } [HarmonyPatch(typeof(Container), "Load")] [HarmonyPostfix] private static void RestoreInUseAfterLoad(Container __instance, bool __state) { } } [HarmonyPatch(typeof(Game), "Start")] internal static class GameStartPatch { private static void Postfix() { if (!SharedChest.ExternalMultiUserChestLoaded) { RpcHub.Register(); } } } [HarmonyPatch(typeof(Humanoid), "Awake")] internal static class HumanoidAwakePatch { private static void Postfix(Humanoid __instance) { if (!SharedChest.ExternalMultiUserChestLoaded) { ((Component)__instance).gameObject.AddComponent<PlayerLink>(); } } } [HarmonyPatch] internal static class InventoryGuiSharedPatch { [HarmonyPatch(typeof(InventoryGui), "Update")] [HarmonyPostfix] private static void UpdateContainerChanges(InventoryGui __instance) { if (SharedChest.IsEnabled && Object.op_Implicit((Object)(object)__instance.m_currentContainer) && Object.op_Implicit((Object)(object)__instance.m_currentContainer.m_nview) && __instance.m_currentContainer.m_nview.IsValid()) { __instance.m_currentContainer.CheckForChanges(); } } [HarmonyPatch(typeof(InventoryGui), "UpdateContainer")] [HarmonyTranspiler] private static IEnumerable<CodeInstruction> AllowNonOwnerOpen(IEnumerable<CodeInstruction> instructions) { //IL_000b: 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: Expected O, but got Unknown //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_0053: Expected O, but got Unknown //IL_0075: Unknown result type (might be due to invalid IL or missing references) //IL_007b: Expected O, but got Unknown //IL_00a9: Unknown result type (might be due to invalid IL or missing references) //IL_00af: Expected O, but got Unknown if (SharedChest.ExternalMultiUserChestLoaded) { return instructions; } return new CodeMatcher(instructions, (ILGenerator)null).MatchForward(true, (CodeMatch[])(object)new CodeMatch[3] { new CodeMatch((OpCode?)OpCodes.Ldarg_0, (object)null, (string)null), new CodeMatch((Func<CodeInstruction, bool>)((CodeInstruction i) => i.opcode == OpCodes.Ldfld && ((FieldInfo)i.operand).Name == "m_currentContainer"), (string)null), new CodeMatch((Func<CodeInstruction, bool>)((CodeInstruction i) => i.opcode == OpCodes.Callvirt && ((MethodInfo)i.operand).Name == "IsOwner"), (string)null) }).RemoveInstructions(1).Insert((CodeInstruction[])(object)new CodeInstruction[1] { new CodeInstruction(OpCodes.Call, (object)AccessTools.Method(typeof(InventoryGuiSharedPatch), "CanShowContainer", (Type[])null, (Type[])null)) }) .InstructionEnumeration(); } private static bool CanShowContainer(Container container) { if (!SharedChest.IsEnabled) { return container.IsOwner(); } return true; } [HarmonyPatch(typeof(InventoryGui), "OnRightClickItem")] [HarmonyPrefix] private static bool RightClickConsume(InventoryGui __instance, InventoryGrid grid, ItemData item) { if (!SharedChest.IsEnabled) { return true; } Player localPlayer = Player.m_localPlayer; if (item == null || !Object.op_Implicit((Object)(object)localPlayer)) { return true; } if (grid.GetInventory() == ((Humanoid)localPlayer).GetInventory()) { return true; } if (!Object.op_Implicit((Object)(object)__instance.m_currentContainer) || __instance.m_currentContainer.IsOwner()) { return true; } if (SlotBlock.Of(((Humanoid)localPlayer).GetInventory()).BlockConsume) { return false; } if (((Humanoid)localPlayer).CanConsumeItem(item, false)) { SlotBlock.Of(((Humanoid)localPlayer).GetInventory()).BlockConsume = true; RpcHub.Invoke(__instance.m_currentContainer.m_nview, "SS_RequestItemConsume", new ConsumeRequest(item)); } return false; } [HarmonyPatch(typeof(InventoryGui), "OnDropOutside")] [HarmonyPrefix] private static void DropOutside(InventoryGui __instance, ref bool __runOriginal) { //IL_0067: Unknown result type (might be due to invalid IL or missing references) //IL_0077: Unknown result type (might be due to invalid IL or missing references) if (SharedChest.IsEnabled && __runOriginal && Object.op_Implicit((Object)(object)__instance.m_dragGo) && !((Humanoid)Player.m_localPlayer).GetInventory().GetInventories().Contains(__instance.m_dragInventory) && Object.op_Implicit((Object)(object)__instance.m_currentContainer) && !__instance.m_currentContainer.IsOwner()) { RpcHub.Invoke(__instance.m_currentContainer.m_nview, "SS_RequestItemDrop", new DropRequest(__instance.m_dragItem.m_gridPos, __instance.m_dragAmount, ((Character)Player.m_localPlayer).GetZDOID())); __instance.SetupDragItem((ItemData)null, (Inventory)null, 1); __runOriginal = false; } } } [HarmonyPatch] internal static class InventoryInterceptPatch { internal static readonly ConditionalWeakTable<ItemData, Inventory> ItemInventory = new ConditionalWeakTable<ItemData, Inventory>(); private static readonly WeakReference<ItemData> LastRemoved = new WeakReference<ItemData>(null); private static bool _allowSwap = true; [HarmonyPatch(typeof(Inventory), "AddItem", new Type[] { typeof(ItemData), typeof(int), typeof(int), typeof(int), typeof(bool) })] [HarmonyPrefix] [HarmonyPriority(100)] private static void AddItemPrefix(Inventory __instance, ref bool __runOriginal, ItemData item, int amount, int x, int y, ref bool __result) { //IL_0013: Unknown result type (might be due to invalid IL or missing references) if (SharedChest.IsEnabled && __runOriginal && Intercept(__instance, item, amount, new Vector2i(x, y), out var success)) { __result = success; __runOriginal = false; } } [HarmonyPatch(typeof(Inventory), "AddItem", new Type[] { typeof(ItemData) })] [HarmonyPrefix] [HarmonyPriority(100)] private static void AddItemPrefix2(Inventory __instance, ref bool __runOriginal, ItemData item, ref bool __result) { //IL_0016: Unknown result type (might be due to invalid IL or missing references) if (SharedChest.IsEnabled && __runOriginal && Intercept(__instance, item, item.m_stack, new Vector2i(-1, -1), out var success)) { __result = success; __runOriginal = false; } } [HarmonyPatch(typeof(Inventory), "RemoveItem", new Type[] { typeof(ItemData) })] [HarmonyPrefix] [HarmonyPriority(100)] private static void RemovePrefix(Inventory __instance, ref bool __runOriginal, ref bool __result) { if (SharedChest.IsEnabled && __runOriginal) { InvOwner invOwner = InvOwner.Of(__instance); if (invOwner != null && invOwner.IsValid() && !invOwner.View.IsOwner()) { __result = false; __runOriginal = false; } } } [HarmonyPatch(typeof(Inventory), "RemoveItem", new Type[] { typeof(ItemData) })] [HarmonyPostfix] private static void RemovePostfix(Inventory __instance, ItemData item, ref bool __result) { if (SharedChest.IsEnabled) { LastRemoved.SetTarget(__result ? item : null); } } [HarmonyPatch(typeof(Inventory), "MoveAll")] [HarmonyPrefix] [HarmonyPriority(800)] private static void MoveAllPrefix() { if (SharedChest.IsEnabled) { _allowSwap = false; } } [HarmonyPatch(typeof(Inventory), "MoveAll")] [HarmonyPostfix] [HarmonyPriority(0)] private static void MoveAllPostfix() { if (SharedChest.IsEnabled) { _allowSwap = true; } } [HarmonyPatch(typeof(Inventory), "Changed")] [HarmonyPostfix] private static void ChangedPostfix(Inventory __instance) { if (!SharedChest.IsEnabled) { return; } foreach (Inventory inventory in __instance.GetInventories()) { foreach (ItemData allItem in inventory.GetAllItems()) { ItemInventory.Remove(allItem); ItemInventory.Add(allItem, inventory); } } } [HarmonyPatch(typeof(Humanoid), "Pickup")] [HarmonyPrefix] private static bool BlockPickupWhilePending(Humanoid __instance) { if (!SharedChest.IsEnabled) { return true; } Inventory inventory = __instance.GetInventory(); if (inventory != null) { return !SlotBlock.Of(inventory).AnyBlocked; } return true; } private static bool Intercept(Inventory inventory, ItemData item, int amount, Vector2i pos, out bool success) { //IL_005b: Unknown result type (might be due to invalid IL or missing references) //IL_00dc: 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_01c5: Unknown result type (might be due to invalid IL or missing references) //IL_014d: Unknown result type (might be due to invalid IL or missing references) //IL_010d: Unknown result type (might be due to invalid IL or missing references) //IL_0112: Unknown result type (might be due to invalid IL or missing references) InvOwner invOwner = InvOwner.Of(item); InvOwner invOwner2 = InvOwner.Of(inventory); if (invOwner == null || !invOwner.IsValid() || invOwner2 == null || !invOwner2.IsValid()) { success = false; return false; } if (invOwner.View.IsOwner() && !invOwner2.View.IsOwner() && invOwner2 is ContainerInvOwner containerInvOwner) { AddRequest addRequest = ClientOps.BeginAdd(containerInvOwner.Container, item, invOwner.Inventory, pos, amount); success = addRequest != null && addRequest.DragItem?.m_stack == amount; return true; } if (!invOwner.View.IsOwner() && invOwner2.View.IsOwner() && invOwner is ContainerInvOwner containerInvOwner2) { ItemData val = invOwner2.Inventory.GetItemAt(pos.x, pos.y); if (val == null && LastRemoved.TryGetTarget(out ItemData target) && InvOwner.Of(target) == invOwner2 && target.m_gridPos == pos) { val = target; } if (!_allowSwap && val != null) { success = false; return true; } if (val != null && ItemPack.CanStack(item, val)) { val = null; } RemoveRequest removeRequest = ClientOps.BeginRemove(containerInvOwner2.Container, item, invOwner2.Inventory, pos, amount, val); success = removeRequest == null || removeRequest.DragAmount == amount; if (removeRequest == null) { success = true; } return true; } if (!invOwner.View.IsOwner() && !invOwner2.View.IsOwner() && invOwner is ContainerInvOwner containerInvOwner3 && invOwner2 is ContainerInvOwner containerInvOwner4 && (Object)(object)containerInvOwner3.Container == (Object)(object)containerInvOwner4.Container) { ClientOps.BeginMove(containerInvOwner3.Container, item, pos, amount); success = true; return true; } success = false; return false; } } internal interface ISsPackage { ZPackage Write(); } internal interface ISsRequest : ISsPackage { int RequestId { get; set; } Inventory? SourceInventory { get; } Inventory? TargetInventory { get; } } internal interface ISsResponse : ISsPackage { int SourceId { get; set; } } internal static class RequestStore { private static readonly Dictionary<int, ISsPackage> Packages = new Dictionary<int, ISsPackage>(); private static readonly Dictionary<int, float> AddedAt = new Dictionary<int, float>(); private static readonly Random Rng = new Random(); private const float TimeoutSeconds = 60f; internal static int Track(ISsPackage package) { Prune(); int num = Rng.Next(int.MinValue, int.MaxValue); if (package is ISsRequest ssRequest) { ssRequest.RequestId = num; } Packages[num] = package; AddedAt[num] = Time.time; return num; } internal static void Forget(int id) { Packages.Remove(id); AddedAt.Remove(id); } internal static void Forget(ISsResponse response) { Forget(response.SourceId); } internal static T? Get<T>(int id) where T : class, ISsPackage { if (!Packages.TryGetValue(id, out ISsPackage value)) { return null; } return value as T; } private static void Prune() { if (Packages.Count == 0) { return; } float time = Time.time; List<int> list = new List<int>(); foreach (KeyValuePair<int, float> item in AddedAt) { if (time - item.Value >= 60f) { list.Add(item.Key); } } foreach (int item2 in list) { Forget(item2); } } } internal sealed class SlotBlock { private static readonly ConditionalWeakTable<Inventory, SlotBlock> Table = new ConditionalWeakTable<Inventory, SlotBlock>(); private readonly HashSet<Vector2i> _blocked = new HashSet<Vector2i>(); internal bool BlockConsume; internal bool AnyBlocked { get { if (_blocked.Count <= 0) { return BlockConsume; } return true; } } internal static SlotBlock Of(Inventory inventory) { return Table.GetValue(inventory, (Inventory _) => new SlotBlock()); } internal void Block(Vector2i slot) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0009: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Unknown result type (might be due to invalid IL or missing references) if (slot.x >= 0 && slot.y >= 0) { _blocked.Add(slot); } } internal void Release(Vector2i slot) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) _blocked.Remove(slot); } internal bool IsBlocked(Vector2i slot) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) return _blocked.Contains(slot); } } internal static class RpcNames { internal const string Add = "SS_RequestItemAdd"; internal const string AddResponse = "SS_RequestItemAddResponse"; internal const string Remove = "SS_RequestItemRemove"; internal const string RemoveResponse = "SS_RequestItemRemoveResponse"; internal const string Move = "SS_RequestItemMove"; internal const string MoveResponse = "SS_RequestItemMoveResponse"; internal const string Consume = "SS_RequestItemConsume"; internal const string ConsumeResponse = "SS_RequestItemConsumeResponse"; internal const string Drop = "SS_RequestItemDrop"; internal const string DropResponse = "SS_RequestItemDropResponse"; internal const string Salvage = "SS_RequestItemSalvage"; internal const string SalvageResponse = "SS_RequestItemSalvageResponse"; internal const string Sort = "SS_RequestSort"; } internal static class RpcHub { internal static void Register() { ZRoutedRpc.instance.Register<ZDOID, ZPackage>("SS_RequestItemAdd", (Action<long, ZDOID, ZPackage>)OwnerOps.OnAdd); ZRoutedRpc.instance.Register<ZDOID, ZPackage>("SS_RequestItemRemove", (Action<long, ZDOID, ZPackage>)OwnerOps.OnRemove); ZRoutedRpc.instance.Register<ZDOID, ZPackage>("SS_RequestItemMove", (Action<long, ZDOID, ZPackage>)OwnerOps.OnMove); ZRoutedRpc.instance.Register<ZDOID, ZPackage>("SS_RequestItemConsume", (Action<long, ZDOID, ZPackage>)OwnerOps.OnConsume); ZRoutedRpc.instance.Register<ZDOID, ZPackage>("SS_RequestItemDrop", (Action<long, ZDOID, ZPackage>)OwnerOps.OnDrop); ZRoutedRpc.instance.Register<ZDOID, ZPackage>("SS_RequestItemSalvage", (Action<long, ZDOID, ZPackage>)OwnerOps.OnSalvage); ZRoutedRpc.instance.Register<ZDOID, int>("SS_RequestSort", (Action<long, ZDOID, int>)OwnerOps.OnSort); ZRoutedRpc.instance.Register<ZDOID, ZPackage>("SS_RequestItemAddResponse", (Action<long, ZDOID, ZPackage>)ClientOps.OnAddResponse); ZRoutedRpc.instance.Register<ZDOID, ZPackage>("SS_RequestItemRemoveResponse", (Action<long, ZDOID, ZPackage>)ClientOps.OnRemoveResponse); ZRoutedRpc.instance.Register<ZDOID, ZPackage>("SS_RequestItemMoveResponse", (Action<long, ZDOID, ZPackage>)ClientOps.OnMoveResponse); ZRoutedRpc.instance.Register<ZDOID, ZPackage>("SS_RequestItemConsumeResponse", (Action<long, ZDOID, ZPackage>)ClientOps.OnConsumeResponse); ZRoutedRpc.instance.Register<ZDOID, ZPackage>("SS_RequestItemDropResponse", (Action<long, ZDOID, ZPackage>)ClientOps.OnDropResponse); ZRoutedRpc.instance.Register<ZDOID, ZPackage>("SS_RequestItemSalvageResponse", (Action<long, ZDOID, ZPackage>)ClientOps.OnSalvageResponse); } internal static void Invoke(ZNetView netView, string rpc, ISsPackage package) { //IL_001f: Unknown result type (might be due to invalid IL or missing references) ZRoutedRpc.instance.InvokeRoutedRPC(netView.m_zdo.GetOwner(), rpc, new object[2] { netView.m_zdo.m_uid, package.Write() }); } } public static class SharedChest { public const string MultiUserChestGuid = "com.maxsch.valheim.MultiUserChest"; internal static ConfigEntry<DepositModule.Toggle> EnableSharedChests; public static bool ExternalMultiUserChestLoaded => Chainloader.PluginInfos.ContainsKey("com.maxsch.valheim.MultiUserChest"); public static bool IsEnabled { get { if (!ExternalMultiUserChestLoaded && EnableSharedChests != null) { return EnableSharedChests.Value == DepositModule.Toggle.On; } return false; } } public static bool CanUseWhileInUse { get { if (!ExternalMultiUserChestLoaded) { return IsEnabled; } return true; } } internal static void SetEnabledConfig(ConfigEntry<DepositModule.Toggle> entry) { EnableSharedChests = entry; } } public static class SharedChestApi { public static bool IsEnabled => SharedChest.IsEnabled; public static bool CanUseWhileInUse => SharedChest.CanUseWhileInUse; public static Inventory CopyInventory(Inventory target) { return InvUtil.Copy(target); } public static int TryAddFromPlayer(Container container, ItemData item, int amount) { return ClientOps.TryAddFromPlayer(container, item, amount); } public static int HowMuchFits(Inventory target, ItemData item) { return InventoryMove.HowMuchFits(target, item); } } } namespace SeamlessStorage.Deposit { [HarmonyPatch(typeof(Terminal), "InitTerminal")] internal static class TerminalInitTerminalPatch { [Serializable] [CompilerGenerated] private sealed class <>c { public static readonly <>c <>9 = new <>c(); public static ConsoleEvent <>9__0_0; public static ConsoleOptionsFetcher <>9__0_1; internal void <Postfix>b__0_0(ConsoleEventArgs args) { if (args.Length > 1 && Object.op_Implicit((Object)(object)ZNetScene.instance)) { ChestSearch.SearchNearby(string.Join(" ", args.Args.Skip(1).ToArray())); } } internal List<string> <Postfix>b__0_1() { if (Object.op_Implicit((Object)(object)ZNetScene.instance)) { return ZNetScene.instance.GetPrefabNames(); } return new List<string>(); } } private static void Postfix(Terminal __instance) { //IL_001e: 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_0029: Expected O, but got Unknown //IL_0051: Unknown result type (might be due to invalid IL or missing references) //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_004e: Expected O, but got Unknown object obj = <>c.<>9__0_0; if (obj == null) { ConsoleEvent val = delegate(ConsoleEventArgs args) { if (args.Length > 1 && Object.op_Implicit((Object)(object)ZNetScene.instance)) { ChestSearch.SearchNearby(string.Join(" ", args.Args.Skip(1).ToArray())); } }; <>c.<>9__0_0 = val; obj = (object)val; } object obj2 = <>c.<>9__0_1; if (obj2 == null) { ConsoleOptionsFetcher val2 = () => Object.op_Implicit((Object)(object)ZNetScene.instance) ? ZNetScene.instance.GetPrefabNames() : new List<string>(); <>c.<>9__0_1 = val2; obj2 = (object)val2; } new ConsoleCommand("seamlesssearch", "[prefab name/query text] - search for items in chests near the player. It uses the prefab name", (ConsoleEvent)obj, false, false, false, false, false, false, (ConsoleOptionsFetcher)obj2, false, false, false); } } public class DepositModule { public enum Toggle { Off, On } public enum StoreHighlightPreset { BrightCyan, NeonBlue, Lime, Gold, Magenta, White, Custom } private class ConfigurationManagerAttributes { [UsedImplicitly] public int? Order; [UsedImplicitly] public bool? Browsable; [UsedImplicitly] public string Category; [UsedImplicitly] public Action<ConfigEntryBase>? CustomDrawer; } private class AcceptableShortcuts : AcceptableValueBase { public AcceptableShortcuts() : base(typeof(KeyboardShortcut)) { } public override object Clamp(object value) { return value; } public override bool IsValid(object value) { return true; } public override string ToDescriptionString() { return "# Acceptable values: " + string.Join(", ", UnityInput.Current.SupportedKeyCodes); } } internal const string ModName = "Seamless Storage"; internal const string ModVersion = "1.0.1"; internal const string Author = "ModdedWolf"; internal const string ModGUID = "ModdedWolf.SeamlessStorage"; internal const string KgGuid = "kg.ItemDrawers"; internal const string BackpacksGuid = "org.bepinex.plugins.backpacks"; private static string ConfigFileName = "ModdedWolf.SeamlessStorage.cfg"; private static readonly string ConfigFileFullPath = Paths.ConfigPath + Path.DirectorySeparatorChar + ConfigFileName; internal static string ConnectionError = ""; private static Harmony _harmony = null; public static ManualLogSource DepositLog = null; private static BaseUnityPlugin Host = null; internal static bool BackpacksIsLoaded = false; internal static readonly string yamlFileName = "ModdedWolf.SeamlessStorage.Deposit.yml"; internal static readonly string yamlPath = Paths.ConfigPath + Path.DirectorySeparatorChar + yamlFileName; internal static readonly CustomSyncedValue<string> DepositContainerData = new CustomSyncedValue<string>(ConfigSync, "seamlessDepositData", ""); internal static readonly CustomSyncedValue<string> PullContainerGroupsData = new CustomSyncedValue<string>(ConfigSync, "seamlessDepositGroupsData", ""); internal static Dictionary<string, object>? yamlData; internal static Dictionary<string?, HashSet<string?>> groups = null; internal static DepositModule self = null; private const string RangeMigrationMarker = "# Seamless Storage: containers without a range use the Fallback Chest Range config."; private static readonly Regex PinnedDefaultRange = new Regex("^\\s+range:\\s*6(\\.0+)?\\s*(#.*)?$", RegexOptions.IgnoreCase); internal static ConfigEntry<Toggle> EnableAutoDeposit = null; internal static ConfigEntry<Toggle> EnableChestRename = null; internal static ConfigEntry<Toggle> EnableItemSearchButton = null; internal static ConfigEntry<Toggle> EnableSingleItemDeposit = null; internal static ConfigEntry<Toggle> EnableRightClickDragDeposit = null; internal static ConfigEntry<Toggle> ChestsPickupFromGround = null; internal static ConfigEntry<Toggle> MustHaveExistingItemToPull =