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 ExtraSlots v1.2.14
ExtraSlots.dll
Decompiled 3 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.Generic; using System.Diagnostics; using System.Globalization; using System.IO; using System.Linq; using System.Reflection; using System.Reflection.Emit; using System.Runtime.CompilerServices; using System.Runtime.ExceptionServices; using System.Runtime.InteropServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using System.Text; using BepInEx; using BepInEx.Bootstrap; using BepInEx.Configuration; using ConditionalConfigSync; using ExtraSlots; using ExtraSlots.Compatibility; using ExtraSlots.HotBars; using HarmonyLib; using JetBrains.Annotations; using LocalizationManager; using Microsoft.CodeAnalysis; using Splatform; using TMPro; using UnityEngine; using UnityEngine.EventSystems; using UnityEngine.InputSystem; using UnityEngine.InputSystem.LowLevel; using UnityEngine.InputSystem.Utilities; using UnityEngine.UI; using YamlDotNet.Serialization; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)] [assembly: AssemblyTitle("ExtraSlots")] [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("")] [assembly: AssemblyProduct("ExtraSlots")] [assembly: AssemblyCopyright("Copyright © 2024")] [assembly: AssemblyTrademark("")] [assembly: ComVisible(false)] [assembly: Guid("7e559c9a-ba1c-45b5-a260-ec3a1455248b")] [assembly: AssemblyFileVersion("1.2.14")] [assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.2.14.0")] [module: UnverifiableCode] 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; } } } namespace LocalizationManager { [PublicAPI] public class Localizer { private const string defaultLanguage = "English"; 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_00a8: Unknown result type (might be due to invalid IL or missing references) //IL_00b2: 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; } } 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 IEnumerator Load() { yield return (object)new WaitUntil((Func<bool>)(() => PlatformManager.DistributionPlatform != null && PlatformInitializer.PreferencesInitialized)); if (string.IsNullOrEmpty(PlatformPrefs.GetString("language", ""))) { PlatformPrefs.SetString("language", "English"); } LoadLocalization(Localization.instance, Localization.instance.GetSelectedLanguage()); } private static void LoadLocalization(Localization __instance, string language) { //IL_00ed: Unknown result type (might be due to invalid IL or missing references) //IL_00f7: Expected O, but got Unknown //IL_01da: Unknown result type (might be due to invalid IL or missing references) //IL_01e4: Expected O, but got Unknown if (!localizationLanguage.Remove(__instance)) { localizationObjects.Add(new WeakReference<Localization>(__instance)); } localizationLanguage.Add(__instance, language); Dictionary<string, string> localizationFiles = new Dictionary<string, string>(); string[] prefixes = new string[2] { Plugin.Info.Metadata.Name + ".", Plugin.Info.Metadata.Name.Replace(" ", "") + "." }; Scan(Paths.ConfigPath, warn: true); byte[] array = LoadTranslationFromAssembly("English"); if (array == 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> dictionary = ((BuilderSkeleton<DeserializerBuilder>)new DeserializerBuilder()).IgnoreFields().Build().Deserialize<Dictionary<string, string>>(Encoding.UTF8.GetString(array)); if (dictionary == null) { throw new Exception("Localization for mod " + Plugin.Info.Metadata.Name + " failed: Localization file was empty."); } string text = null; if (language != "English") { if (localizationFiles.ContainsKey(language)) { text = File.ReadAllText(localizationFiles[language]); } else { byte[] array2 = LoadTranslationFromAssembly(language); if (array2 != null) { text = Encoding.UTF8.GetString(array2); } } } if (text == null && localizationFiles.ContainsKey("English")) { text = File.ReadAllText(localizationFiles["English"]); } if (text != null) { Dictionary<string, string> dictionary2; try { dictionary2 = ((BuilderSkeleton<DeserializerBuilder>)new DeserializerBuilder()).IgnoreFields().Build().Deserialize<Dictionary<string, string>>(text) ?? new Dictionary<string, string>(); } catch (Exception arg) { global::ExtraSlots.ExtraSlots.LogWarning($"Failed to deserialize localization for language '{language}'. Using base localization only.\n{arg}"); dictionary2 = new Dictionary<string, string>(); } foreach (KeyValuePair<string, string> item in dictionary2) { dictionary[item.Key] = item.Value; } } loadedTexts[language] = dictionary; foreach (KeyValuePair<string, string> item2 in dictionary) { UpdatePlaceholderText(__instance, item2.Key); } void Scan(string root, bool warn) { foreach (string item3 in from f in Directory.GetFiles(root, "*.*", SearchOption.AllDirectories) where fileExtensions.Contains(Path.GetExtension(f)) select f) { string fileNameWithoutExtension = Path.GetFileNameWithoutExtension(item3); string[] array3 = prefixes; foreach (string text2 in array3) { if (fileNameWithoutExtension.StartsWith(text2)) { string text3 = fileNameWithoutExtension.Substring(text2.Length); if (!string.IsNullOrWhiteSpace(text3)) { if (localizationFiles.ContainsKey(text3)) { if (warn) { global::ExtraSlots.ExtraSlots.LogWarning("Duplicate localization '" + text3 + "' for " + Plugin.Info.Metadata.Name + ". Skipping " + item3); } } else { localizationFiles[text3] = item3; } } break; } } } } } static Localizer() { //IL_0050: Unknown result type (might be due to invalid IL or missing references) //IL_0056: Expected O, but got Unknown //IL_0084: Unknown result type (might be due to invalid IL or missing references) //IL_0091: 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> { ".json", ".yml" }; Harmony val = new Harmony("org.bepinex.helpers.LocalizationManager"); val.Patch((MethodBase)AccessTools.DeclaredMethod(typeof(Localization), "LoadCSV", (Type[])null, (Type[])null), (HarmonyMethod)null, new HarmonyMethod(AccessTools.DeclaredMethod(typeof(Localizer), "LoadLocalization", (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(); } } } namespace ExtraSlots { internal static class DebugLogging { [HarmonyPatch(typeof(Player), "CreateTombStone")] internal static class Player_CreateTombstone_LoggingItems { [HarmonyPriority(800)] private static void Prefix(Player __instance) { if (IsDebugEnabled && Slots.IsValidPlayer((Character)(object)__instance)) { ExtraSlots.LogDebug("Player.CreateTombStone:Prefix Player Item List:"); ((Humanoid)__instance).GetInventory().LogInventory(); } } [HarmonyPriority(0)] private static void Finalizer(Player __instance) { if (IsDebugEnabled && Slots.IsValidPlayer((Character)(object)__instance)) { ExtraSlots.LogDebug("Player.CreateTombStone:Finalizer Player Item List:"); ((Humanoid)__instance).GetInventory().LogInventory(); } } } [HarmonyPatch(typeof(Inventory), "MoveInventoryToGrave")] internal static class Inventory_MoveInventoryToGrave_LoggingItems { [HarmonyPriority(800)] private static void Prefix(Inventory __instance, Inventory original) { if (IsDebugEnabled) { ExtraSlots.LogDebug("Inventory.MoveInventoryToGrave:Prefix"); ExtraSlots.LogDebug("From inventory " + GetInventoryState(original)); original.LogInventory(); ExtraSlots.LogDebug("To inventory " + GetInventoryState(__instance)); __instance.LogInventory(); } } [HarmonyPriority(0)] private static void Finalizer(Inventory __instance, Inventory original) { if (IsDebugEnabled) { ExtraSlots.LogDebug("Inventory.MoveInventoryToGrave:Finalizer"); ExtraSlots.LogDebug("From inventory " + GetInventoryState(original)); original.LogInventory(); ExtraSlots.LogDebug("To inventory " + GetInventoryState(__instance)); __instance.LogInventory(); } } } internal static bool IsDebugEnabled => ExtraSlots.loggingEnabled.Value && ExtraSlots.loggingDebugEnabled.Value; internal static void LogItem(ItemData item) { //IL_00a1: 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) if (!IsDebugEnabled) { return; } if (item == null) { ExtraSlots.LogDebug("<null item>"); return; } object obj = item.m_shared?.m_name; if (obj == null) { GameObject dropPrefab = item.m_dropPrefab; obj = ((dropPrefab != null) ? ((Object)dropPrefab).name : null) ?? "<unmaterialized item>"; } string text = (string)obj; object obj2; if (item.m_shared != null) { Slots.Slot itemSlot = Slots.GetItemSlot(item); if (itemSlot != null) { obj2 = $"slot: {itemSlot} {itemSlot.GridPosition}"; goto IL_008e; } } obj2 = ""; goto IL_008e; IL_008e: string text2 = (string)obj2; ExtraSlots.LogDebug($"{text} {item.m_gridPos} stack:{item.m_stack} {text2}"); } internal static string GetInventoryState(Inventory inventory) { object result; if (inventory != null) { object[] obj = new object[7] { inventory.m_name, inventory.m_temoraryInventory, null, null, null, null, null }; Player localPlayer = Player.m_localPlayer; obj[2] = ((localPlayer != null) ? ((Humanoid)localPlayer).GetInventory() : null) == inventory; obj[3] = inventory.m_width; obj[4] = inventory.m_height; obj[5] = inventory.m_totalWeight; obj[6] = inventory.m_inventory?.Count ?? 0; result = string.Format("name:{0} temporary:{1} isPlayer:{2} size:{3}x{4} weight:{5} items:{6}", obj); } else { result = "<null inventory>"; } return (string)result; } internal static void LogInventory(this Inventory inventory) { if (!IsDebugEnabled || inventory?.m_inventory == null) { return; } foreach (ItemData item in from item in inventory.m_inventory orderby item?.m_gridPos.y ?? int.MaxValue, item?.m_gridPos.x ?? int.MaxValue select item) { LogItem(item); } } } public static class DeferredInventory { internal sealed class DeferredEntry { internal string PrefabName; internal string PreferredSlotId; internal bool RestoreEquipped; internal int OriginalStack; internal string ItemPackageBase64; internal bool PendingFinalization; } [HarmonyPatch(typeof(Player), "Load")] private static class Player_Load_ReadDeferredInventory { [HarmonyPriority(0)] private static void Postfix(Player __instance) { EnsureLoaded(__instance); ItemsSlotsValidation.ValidateItems(); ItemsSlotsValidation.ValidateSlots(); ItemsSlotsValidation.Validate(); } } [HarmonyPatch(typeof(Player), "Save")] private static class Player_Save_FlushDeferredInventory { [HarmonyPriority(800)] private static void Prefix(Player __instance) { if (__instance == statePlayer || (Object)(object)__instance == (Object)(object)Slots.CurrentPlayer) { Flush(__instance); } } } [HarmonyPatch(typeof(Inventory), "MoveInventoryToGrave")] private static class Inventory_MoveInventoryToGrave_AppendDeferredItems { [HarmonyPriority(0)] private static void Postfix(Inventory __instance, Inventory original) { if (original == Slots.PlayerInventory) { MoveAllToTombstone(__instance); } } } public const string CustomDataKey = "ExtraSlotsDeferredInventory"; public const int EnvelopeVersion = 1; private static readonly List<DeferredEntry> entries = new List<DeferredEntry>(); private static readonly HashSet<string> unavailablePrefabsLogged = new HashSet<string>(StringComparer.Ordinal); private static Player statePlayer; private static string statePayload = ""; private static bool storageAvailable = true; private static int revision; private static int lastAttemptRevision = -1; private static int lastRestorationFingerprint; private static bool hasLastRestorationFingerprint; public static int Count(Player player = null) { if (player == null) { player = Slots.CurrentPlayer; } return EnsureLoaded(player) ? entries.Count : 0; } internal static void InvalidateRestorationOpportunity() { lastAttemptRevision = -1; hasLastRestorationFingerprint = false; } internal static bool EnsureLoaded(Player player) { //IL_00b1: Unknown result type (might be due to invalid IL or missing references) //IL_00b8: Expected O, but got Unknown if ((Object)(object)player == (Object)null) { return false; } string value; string text = (player.m_customData.TryGetValue("ExtraSlotsDeferredInventory", out value) ? (value ?? "") : ""); if (statePlayer == player && string.Equals(statePayload, text, StringComparison.Ordinal)) { return storageAvailable; } statePlayer = player; statePayload = text; entries.Clear(); unavailablePrefabsLogged.Clear(); storageAvailable = true; revision = 0; lastAttemptRevision = -1; hasLastRestorationFingerprint = false; if (string.IsNullOrEmpty(text)) { return true; } try { ZPackage val = new ZPackage(text); int num = val.ReadInt(); if (num != 1) { storageAvailable = false; ExtraSlots.LogWarning($"Deferred inventory uses unsupported envelope version {num}. Existing data will be left untouched."); return false; } int num2 = val.ReadInt(); if (num2 < 0) { throw new InvalidOperationException($"Invalid deferred inventory entry count {num2}."); } for (int i = 0; i < num2; i++) { string prefabName = val.ReadString(); string preferredSlotId = val.ReadString(); bool restoreEquipped = val.ReadBool(); int originalStack = val.ReadInt(); string text2 = val.ReadString(); if (string.IsNullOrEmpty(text2)) { throw new InvalidOperationException($"Deferred inventory entry {i} has an empty item package."); } entries.Add(new DeferredEntry { PrefabName = prefabName, PreferredSlotId = preferredSlotId, RestoreEquipped = restoreEquipped, OriginalStack = originalStack, ItemPackageBase64 = text2 }); } ExtraSlots.LogDebug($"Deferred inventory loaded with {entries.Count} item(s)."); return true; } catch (Exception arg) { entries.Clear(); storageAvailable = false; ExtraSlots.LogWarning($"Failed to read deferred inventory. Existing data will be left untouched:\n{arg}"); return false; } } internal static bool Flush(Player player = null) { //IL_0071: Unknown result type (might be due to invalid IL or missing references) //IL_0077: Expected O, but got Unknown if (player == null) { player = statePlayer ?? Slots.CurrentPlayer; } if ((Object)(object)player == (Object)null || !EnsureLoaded(player) || !storageAvailable) { return false; } try { if (entries.Count == 0) { player.m_customData.Remove("ExtraSlotsDeferredInventory"); statePayload = ""; return true; } ZPackage val = new ZPackage(); val.Write(1); val.Write(entries.Count); foreach (DeferredEntry entry in entries) { val.Write(entry.PrefabName ?? ""); val.Write(entry.PreferredSlotId ?? ""); val.Write(entry.RestoreEquipped); val.Write(entry.OriginalStack); val.Write(entry.ItemPackageBase64 ?? ""); } statePayload = val.GetBase64(); player.m_customData["ExtraSlotsDeferredInventory"] = statePayload; return true; } catch (Exception arg) { ExtraSlots.LogWarning($"Failed to persist deferred inventory:\n{arg}"); return false; } } private static bool TryCreateEntry(ItemData item, string preferredSlotId, bool restoreEquipped, out DeferredEntry entry) { //IL_007e: Unknown result type (might be due to invalid IL or missing references) //IL_0083: Unknown result type (might be due to invalid IL or missing references) //IL_0090: Unknown result type (might be due to invalid IL or missing references) //IL_0097: Expected O, but got Unknown //IL_00a6: Unknown result type (might be due to invalid IL or missing references) //IL_00ad: Expected O, but got Unknown //IL_00b7: Unknown result type (might be due to invalid IL or missing references) //IL_00be: Expected O, but got Unknown entry = null; if (item == null) { return false; } GameObject dropPrefab = item.m_dropPrefab; string text = ((dropPrefab != null) ? ((Object)dropPrefab).name : null); if (string.IsNullOrEmpty(text)) { ExtraSlots.LogWarning("Cannot defer " + (item.m_shared?.m_name ?? "<unknown>") + ": item has no prefab reference."); return false; } try { ItemData val = item.Clone(); val.m_equipped = false; val.m_gridPos = new Vector2i(0, 0); Inventory val2 = new Inventory("ExtraSlotsDeferredInventory", (Sprite)null, 1, 1); val2.m_inventory.Add(val); ZPackage val3 = new ZPackage(); val2.Save(val3); ZPackage val4 = new ZPackage(); val4.WriteCompressed(val3); entry = new DeferredEntry { PrefabName = text, PreferredSlotId = (preferredSlotId ?? ""), RestoreEquipped = restoreEquipped, OriginalStack = item.m_stack, ItemPackageBase64 = val4.GetBase64() }; return true; } catch (Exception arg) { ExtraSlots.LogWarning($"Failed to serialize {item.m_shared?.m_name ?? text} for deferred inventory:\n{arg}"); return false; } } private static bool TryMaterialize(DeferredEntry entry, out ItemData item) { //IL_008d: Unknown result type (might be due to invalid IL or missing references) //IL_0094: Expected O, but got Unknown //IL_00a5: Unknown result type (might be due to invalid IL or missing references) //IL_00ac: Expected O, but got Unknown item = null; if (entry == null || string.IsNullOrEmpty(entry.PrefabName) || string.IsNullOrEmpty(entry.ItemPackageBase64)) { return false; } ObjectDB instance = ObjectDB.instance; if ((Object)(object)((instance != null) ? instance.GetItemPrefab(entry.PrefabName) : null) == (Object)null) { if (unavailablePrefabsLogged.Add(entry.PrefabName)) { ExtraSlots.LogWarning("Deferred item prefab " + entry.PrefabName + " is unavailable. Its opaque item package will be preserved until the prefab exists again."); } return false; } try { ZPackage val = new ZPackage(entry.ItemPackageBase64); ZPackage package = val.ReadCompressedPackage(); Inventory val2 = new Inventory("ExtraSlotsDeferredInventory", (Sprite)null, 1, 1); InventorySerialization.Load(val2, package); item = val2.m_inventory.FirstOrDefault(); if (val2.m_inventory.Count == 1 && item != null) { GameObject dropPrefab = item.m_dropPrefab; if (string.Equals((dropPrefab != null) ? ((Object)dropPrefab).name : null, entry.PrefabName, StringComparison.Ordinal)) { val2.m_inventory.Clear(); item.m_equipped = false; if (item.m_stack != entry.OriginalStack) { ExtraSlots.LogWarning($"Deferred item {entry.PrefabName} stack changed while materializing ({entry.OriginalStack} -> {item.m_stack}). Original package will be preserved."); item = null; return false; } return true; } } ExtraSlots.LogWarning("Deferred item " + entry.PrefabName + " did not materialize as the expected single item. Original package will be preserved."); item = null; return false; } catch (Exception arg) { ExtraSlots.LogWarning($"Failed to materialize deferred item {entry.PrefabName}. Original package will be preserved:\n{arg}"); item = null; return false; } } private static string CapturePreferredSlot(ItemData item) { if (item == null) { return ""; } if (item.m_customData.TryGetValue("ExtraSlotsEquippedBy", out var value) && item.m_customData.TryGetValue("ExtraSlotsEquippedSlot", out var value2) && !string.IsNullOrEmpty(value2)) { string text = value; PlayerProfile currentPlayerProfile = Slots.CurrentPlayerProfile; if (text == ((currentPlayerProfile != null) ? currentPlayerProfile.GetPlayerID().ToString() : null)) { return value2; } } Slots.Slot itemSlot = Slots.GetItemSlot(item); return (itemSlot != null && !itemSlot.IsEmptySlot) ? itemSlot.ID : ""; } private static void ApplyPreferredSlotMetadata(Player player, ItemData item, string preferredSlotId) { if (!((Object)(object)player == (Object)null) && item != null && !string.IsNullOrEmpty(preferredSlotId)) { item.m_customData["ExtraSlotsEquippedBy"] = player.GetPlayerID().ToString(); item.m_customData["ExtraSlotsEquippedSlot"] = preferredSlotId; } } private static void CancelTransientReferences(Player player, ItemData item) { if (!((Object)(object)player == (Object)null) && item != null) { while (player.IsEquipActionQueued(item)) { ((Humanoid)player).RemoveEquipAction(item); } player.m_actionQueue.RemoveAll((MinorActionData action) => action != null && action.m_item == item && ((int)action.m_type == 0 || (int)action.m_type == 1)); InventoryGui instance = InventoryGui.instance; if ((Object)(object)instance != (Object)null && instance.m_dragItem == item) { instance.SetupDragItem((ItemData)null, (Inventory)null, 1); } if ((Object)(object)instance != (Object)null && instance.m_splitItem == item) { instance.OnSplitCancel(); } } } internal static bool DeferExisting(ItemData item, string reason = null, string preferredSlotId = null, bool restoreEquipped = false) { Player currentPlayer = Slots.CurrentPlayer; Inventory playerInventory = Slots.PlayerInventory; if ((Object)(object)currentPlayer == (Object)null || playerInventory == null || item == null || !playerInventory.ContainsItem(item) || !EnsureLoaded(currentPlayer)) { return false; } if (preferredSlotId == null) { preferredSlotId = CapturePreferredSlot(item); } bool restoreEquipped2 = restoreEquipped || item.m_equipped || ((Humanoid)currentPlayer).IsItemEquiped(item); ItemData val = item.Clone(); val.m_equipped = false; ApplyPreferredSlotMetadata(currentPlayer, val, preferredSlotId); if (!TryCreateEntry(val, preferredSlotId, restoreEquipped2, out var entry)) { return false; } entries.Add(entry); revision++; if (!Flush(currentPlayer)) { entries.Remove(entry); revision++; return false; } CancelTransientReferences(currentPlayer, item); if (item.m_equipped || ((Humanoid)currentPlayer).IsItemEquiped(item)) { ((Humanoid)currentPlayer).UnequipItem(item, false); } item.m_equipped = false; if (!playerInventory.m_inventory.Remove(item)) { entries.Remove(entry); revision++; Flush(currentPlayer); return false; } Slots.ClearCachedItems(); PlayerInventoryOperations.MarkChanged(playerInventory); ExtraSlots.LogWarning("Item " + (item.m_shared?.m_name ?? entry.PrefabName) + " was moved to deferred inventory" + (string.IsNullOrEmpty(reason) ? "." : (" (" + reason + ")."))); return true; } internal static bool EnqueueDetached(Player player, ItemData item, string preferredSlotId = null, bool restoreEquipped = false, string reason = null) { DeferredEntry handle; return EnqueueDetached(player, item, out handle, preferredSlotId, restoreEquipped, reason); } internal static bool EnqueueDetached(Player player, ItemData item, out DeferredEntry handle, string preferredSlotId = null, bool restoreEquipped = false, string reason = null, bool pendingFinalization = false) { handle = null; if ((Object)(object)player == (Object)null || item == null || !EnsureLoaded(player)) { return false; } ItemData val = item.Clone(); val.m_equipped = false; ApplyPreferredSlotMetadata(player, val, preferredSlotId); if (!TryCreateEntry(val, preferredSlotId, restoreEquipped || item.m_equipped, out var entry)) { return false; } entry.PendingFinalization = pendingFinalization; entries.Add(entry); revision++; if (!Flush(player)) { entries.Remove(entry); revision++; return false; } handle = entry; ExtraSlots.LogWarning("Item " + (item.m_shared?.m_name ?? entry.PrefabName) + " was added to deferred inventory" + (string.IsNullOrEmpty(reason) ? "." : (" (" + reason + ")."))); return true; } internal static bool FinalizeDetachedReplacement(Player player, DeferredEntry handle, ItemData item) { if (handle != null) { handle.PendingFinalization = false; InvalidateRestorationOpportunity(); } if (handle == null || item == null || !EnsureLoaded(player)) { return false; } int num = entries.IndexOf(handle); if (num < 0) { return false; } bool flag = ((Humanoid)player).GetInventory().ContainsItem(item); DeferredEntry entry = null; if (!flag) { ItemData val = item.Clone(); val.m_equipped = false; ApplyPreferredSlotMetadata(player, val, handle.PreferredSlotId); if (!TryCreateEntry(val, handle.PreferredSlotId, handle.RestoreEquipped, out entry)) { return false; } } if (flag) { entries.RemoveAt(num); } else { entries[num] = entry; } revision++; if (Flush(player)) { return true; } if (flag) { entries.Insert(num, handle); } else { entries[num] = handle; } revision++; return false; } internal static string GetMigrationKey(ItemData item) { if (item == null) { return ""; } StringBuilder key = new StringBuilder(); GameObject dropPrefab = item.m_dropPrefab; Append(((dropPrefab != null) ? ((Object)dropPrefab).name : null) ?? ""); Append(item.m_stack.ToString(CultureInfo.InvariantCulture)); Append(item.m_quality.ToString(CultureInfo.InvariantCulture)); Append(item.m_variant.ToString(CultureInfo.InvariantCulture)); Append(item.m_durability.ToString("R", CultureInfo.InvariantCulture)); Append(item.m_crafterID.ToString(CultureInfo.InvariantCulture)); Append(item.m_crafterName ?? ""); Append(item.m_worldLevel.ToString(CultureInfo.InvariantCulture)); Append(item.m_pickedUp ? "1" : "0"); Append(item.m_cheated ? "1" : "0"); if (item.m_customData != null) { foreach (KeyValuePair<string, string> item2 in item.m_customData.OrderBy<KeyValuePair<string, string>, string>((KeyValuePair<string, string> pair) => pair.Key, StringComparer.Ordinal)) { if (!(item2.Key == "ExtraSlotsEquippedBy") && !(item2.Key == "ExtraSlotsEquippedSlot") && !(item2.Key == "ExtraSlotsEquippedWeaponShield")) { Append(item2.Key ?? ""); Append(item2.Value ?? ""); } } } return key.ToString(); void Append(string value) { key.Append(value.Length.ToString(CultureInfo.InvariantCulture)); key.Append(':'); key.Append(value); key.Append(';'); } } internal static List<string> GetMaterializedMigrationKeys(Player player) { List<string> list = new List<string>(); if ((Object)(object)player == (Object)null || !EnsureLoaded(player)) { return list; } foreach (DeferredEntry entry in entries) { if (TryMaterialize(entry, out var item)) { list.Add(GetMigrationKey(item)); } } return list; } private static int ComputeRestorationFingerprint() { Inventory playerInventory = Slots.PlayerInventory; if (playerInventory?.m_inventory == null) { return 0; } int num = 17; num = num * 31 + playerInventory.m_width; num = num * 31 + Slots.InventoryHeightPlayer; num = num * 31 + Slots.InventoryHeightFull; foreach (ItemData item in playerInventory.m_inventory) { if (item == null) { continue; } int num2 = num * 31; GameObject dropPrefab = item.m_dropPrefab; int? obj; if (dropPrefab == null) { obj = null; } else { string name = ((Object)dropPrefab).name; obj = ((name != null) ? new int?(StringExtensionMethods.GetStableHashCode(name)) : ((int?)null)); } int? num3 = obj; int valueOrDefault; if (!num3.HasValue) { SharedData shared = item.m_shared; int? obj2; if (shared == null) { obj2 = null; } else { string name2 = shared.m_name; obj2 = ((name2 != null) ? new int?(StringExtensionMethods.GetStableHashCode(name2)) : ((int?)null)); } int? num4 = obj2; valueOrDefault = num4.GetValueOrDefault(); } else { valueOrDefault = num3.GetValueOrDefault(); } num = num2 + valueOrDefault; num = num * 31 + item.m_stack; num = num * 31 + item.m_quality; num = num * 31 + item.m_variant; num = num * 31 + item.m_worldLevel; num = num * 31 + ((item.m_gridPos.y < Slots.InventoryHeightPlayer) ? 1 : 2); } Slots.Slot[] slots = Slots.slots; foreach (Slots.Slot slot in slots) { num = num * 31 + StringExtensionMethods.GetStableHashCode(slot.ID); num = num * 31 + (slot.IsActive ? 1 : 0); num = num * 31 + (slot.IsFree ? 1 : 0); } return num; } internal static bool TryRestoreAvailable() { Player currentPlayer = Slots.CurrentPlayer; if ((Object)(object)currentPlayer == (Object)null || currentPlayer.m_isLoading || InventoryBackup.IsRecovering(currentPlayer) || Slots.PlayerInventory == null || !EnsureLoaded(currentPlayer) || entries.Count == 0) { return false; } int num = ComputeRestorationFingerprint(); if (lastAttemptRevision == revision && hasLastRestorationFingerprint && lastRestorationFingerprint == num) { return false; } bool flag = false; using (PlayerInventoryOperations.Batch(Slots.PlayerInventory)) { try { int num2 = 0; while (num2 < entries.Count) { DeferredEntry deferredEntry = entries[num2]; if (deferredEntry.PendingFinalization || !TryMaterialize(deferredEntry, out var item)) { num2++; continue; } ApplyPreferredSlotMetadata(currentPlayer, item, deferredEntry.PreferredSlotId); EquipmentAndQuickSlotsCompat.ApplyCurrentSlotMetadata(currentPlayer, item); InventorySlotsCompat.ApplyCurrentSlotMetadata(currentPlayer, item); if (!PlayerInventoryOperations.TryInsertDetachedToBestAvailable(item, deferredEntry.PreferredSlotId, deferredEntry.RestoreEquipped, out var placedItem, out var fullyInserted, out var madeProgress)) { num2++; } else if (fullyInserted) { entries.RemoveAt(num2); revision++; flag = true; if (deferredEntry.RestoreEquipped && placedItem != null && placedItem.IsEquipable() && Slots.PlayerInventory.ContainsItem(placedItem) && !((Humanoid)currentPlayer).IsItemEquiped(placedItem)) { try { ((Humanoid)currentPlayer).EquipItem(placedItem, false); } catch (Exception arg) { ExtraSlots.LogWarning($"Deferred item {deferredEntry.PrefabName} was restored, but could not be equipped:\n{arg}"); } } ExtraSlots.LogMessage("Deferred item " + deferredEntry.PrefabName + " was restored to player inventory."); } else { if (madeProgress && item.m_stack > 0 && TryCreateEntry(item, deferredEntry.PreferredSlotId, deferredEntry.RestoreEquipped, out var entry)) { entries[num2] = entry; revision++; flag = true; } num2++; } } } finally { if (flag) { Flush(currentPlayer); } } } lastAttemptRevision = revision; lastRestorationFingerprint = ComputeRestorationFingerprint(); hasLastRestorationFingerprint = true; return flag; } internal static bool MoveAllToTombstone(Inventory graveInventory) { //IL_0097: Unknown result type (might be due to invalid IL or missing references) //IL_009c: 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) //IL_00e3: Unknown result type (might be due to invalid IL or missing references) //IL_00d2: Unknown result type (might be due to invalid IL or missing references) //IL_00d7: Unknown result type (might be due to invalid IL or missing references) //IL_00ed: Unknown result type (might be due to invalid IL or missing references) //IL_00fb: Unknown result type (might be due to invalid IL or missing references) //IL_010e: Unknown result type (might be due to invalid IL or missing references) //IL_0115: Unknown result type (might be due to invalid IL or missing references) Player currentPlayer = Slots.CurrentPlayer; if ((Object)(object)currentPlayer == (Object)null || graveInventory == null || graveInventory.m_temoraryInventory || !EnsureLoaded(currentPlayer) || entries.Count == 0) { return false; } int height = graveInventory.m_height; bool flag = false; int num = 0; while (num < entries.Count) { DeferredEntry deferredEntry = entries[num]; if (!TryMaterialize(deferredEntry, out var item)) { num++; continue; } ApplyPreferredSlotMetadata(currentPlayer, item, deferredEntry.PreferredSlotId); item.m_equipped = false; Vector2i val = FindTombstoneAppendPosition(graveInventory, height); if (val.x < 0 && graveInventory.m_height <= 255) { graveInventory.m_height++; val = FindTombstoneAppendPosition(graveInventory, height); } int stack = item.m_stack; if (val.x < 0 || val.x > 255 || val.y > 255 || !graveInventory.AddItem(item, stack, val.x, val.y, false)) { ExtraSlots.LogWarning("Unable to place deferred item " + deferredEntry.PrefabName + " into expanded tombstone inventory. Item remains deferred."); num++; continue; } entries.RemoveAt(num); revision++; flag = true; ExtraSlots.LogMessage("Deferred item " + deferredEntry.PrefabName + " was moved into tombstone inventory."); } if (flag) { Flush(currentPlayer); } return flag; } private static Vector2i FindTombstoneAppendPosition(Inventory inventory, int startHeight) { //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_0056: 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) for (int i = Math.Max(0, startHeight); i < inventory.m_height; i++) { for (int j = 0; j < inventory.m_width; j++) { if (inventory.GetItemAt(j, i) == null) { return new Vector2i(j, i); } } } return Slots.emptyPosition; } } internal static class DeferredTombstone { private sealed class Entry { internal string PrefabName; internal string PreferredSlotId; internal bool RestoreEquipped; internal int OriginalStack; internal string ItemPackageBase64; } [HarmonyPatch(typeof(TombStone), "Setup")] private static class TombStone_Setup_TransferOpaqueDeferred { [HarmonyPriority(0)] private static void Postfix(TombStone __instance) { TransferRemainingPlayerPayload(__instance); } } [HarmonyPatch(typeof(TombStone), "Interact")] private static class TombStone_Interact_MaterializeOpaqueDeferred { [HarmonyPriority(0)] private static bool Prefix(TombStone __instance, Humanoid character, bool hold, bool alt, ref bool __result) { if (!HasPayload(__instance)) { return true; } MaterializeAvailable(__instance); if (HasPayload(__instance)) { Container container = __instance.m_container; if (container != null) { Inventory inventory = container.GetInventory(); if (((inventory != null) ? new int?(inventory.NrOfItems()) : ((int?)null)) > 0) { goto IL_006e; } } if (hold) { return true; } __instance.m_localOpened = true; __result = (Object)(object)__instance.m_container != (Object)null && __instance.m_container.Interact(character, false, alt); return false; } goto IL_006e; IL_006e: return true; } } [HarmonyPatch(typeof(TombStone), "EasyFitInInventory")] private static class TombStone_EasyFitInInventory_OpaqueDeferredGuard { [HarmonyPriority(0)] private static void Postfix(TombStone __instance, ref bool __result) { if (HasPayload(__instance)) { __result = false; } } } [HarmonyPatch(typeof(TombStone), "GetHoverText")] private static class TombStone_GetHoverText_ShowOpaqueDeferred { [HarmonyPriority(0)] private static void Postfix(TombStone __instance, ref string __result) { if (string.IsNullOrEmpty(__result) && HasPayload(__instance)) { ZNetView nview = __instance.m_nview; if (nview != null && nview.IsValid()) { string text = __instance.m_text + " " + __instance.GetOwnerName(); __result = Localization.instance.Localize(text + "\n[<color=yellow><b>$KEY_Use</b></color>] $piece_container_open"); } } } } [HarmonyPatch] private static class Container_RPC_Response_MaterializeOpaqueDeferred { private static IEnumerable<MethodBase> TargetMethods() { yield return AccessTools.Method(typeof(Container), "RPC_OpenResponse", (Type[])null, (Type[])null); yield return AccessTools.Method(typeof(Container), "RPC_TakeAllResponse", (Type[])null, (Type[])null); } [HarmonyPriority(800)] private static void Prefix(Container __instance, bool granted) { if (!granted || !Object.op_Implicit((Object)(object)Player.m_localPlayer) || (Object)(object)__instance == (Object)null) { return; } TombStone componentInParent = ((Component)__instance).GetComponentInParent<TombStone>(); if (componentInParent != null && HasPayload(componentInParent)) { ZNetView nview = __instance.m_nview; if (nview != null) { nview.ClaimOwnership(); } MaterializeAvailable(componentInParent); } } } [HarmonyPatch(typeof(TombStone), "UpdateDespawn")] private static class TombStone_UpdateDespawn_PreserveOpaqueDeferred { private static void Prefix(TombStone __instance, out bool __state) { __state = false; if (!HasPayload(__instance)) { return; } MaterializeAvailable(__instance); if (HasPayload(__instance) && !((Object)(object)__instance.m_container == (Object)null) && !__instance.m_container.IsInUse()) { Inventory inventory = __instance.m_container.GetInventory(); if (inventory == null || inventory.NrOfItems() <= 0) { __instance.m_container.m_inUse = true; __state = true; } } } [HarmonyFinalizer] private static Exception Finalizer(TombStone __instance, bool __state, Exception __exception) { if (__state && (Object)(object)__instance?.m_container != (Object)null) { __instance.m_container.m_inUse = false; } return __exception; } } private const string PayloadKey = "ExtraSlotsDeferredTombstone"; private static readonly int payloadHash = StringExtensionMethods.GetStableHashCode("ExtraSlotsDeferredTombstone"); private static readonly HashSet<string> unavailablePrefabsLogged = new HashSet<string>(StringComparer.Ordinal); internal static bool HasPayload(TombStone tombstone) { return !string.IsNullOrEmpty(GetPayload(tombstone)); } private static string GetPayload(TombStone tombstone) { if (tombstone != null) { ZNetView nview = tombstone.m_nview; if (((nview != null) ? new bool?(nview.IsValid()) : ((bool?)null)) == true) { ZDO zDO = tombstone.m_nview.GetZDO(); return ((zDO != null) ? zDO.GetString(payloadHash, "") : null) ?? ""; } } return ""; } private static bool TransferRemainingPlayerPayload(TombStone tombstone) { Player currentPlayer = Slots.CurrentPlayer; if (!((Object)(object)currentPlayer == (Object)null) && tombstone != null) { ZNetView nview = tombstone.m_nview; if (((nview != null) ? new bool?(nview.IsValid()) : ((bool?)null)) == true && tombstone.m_nview.IsOwner()) { if (!currentPlayer.m_customData.TryGetValue("ExtraSlotsDeferredInventory", out var value) || string.IsNullOrEmpty(value)) { return false; } ZDO zDO = tombstone.m_nview.GetZDO(); if (zDO == null) { return false; } string text = zDO.GetString(payloadHash, ""); if (!string.IsNullOrEmpty(text) && !string.Equals(text, value, StringComparison.Ordinal)) { ExtraSlots.LogWarning("Tombstone already contains a different opaque deferred payload. Player deferred data was preserved instead of overwriting grave ownership."); return false; } zDO.Set(payloadHash, value); if (!string.Equals(zDO.GetString(payloadHash, ""), value, StringComparison.Ordinal)) { ExtraSlots.LogWarning("Failed to persist opaque deferred ownership on tombstone. Player deferred data was left intact."); return false; } currentPlayer.m_customData.Remove("ExtraSlotsDeferredInventory"); DeferredInventory.EnsureLoaded(currentPlayer); ExtraSlots.LogMessage("Remaining opaque deferred item data was transferred to tombstone ownership."); return true; } } return false; } private static int MaterializeAvailable(TombStone tombstone) { //IL_017a: Unknown result type (might be due to invalid IL or missing references) //IL_017f: Unknown result type (might be due to invalid IL or missing references) //IL_0181: Unknown result type (might be due to invalid IL or missing references) //IL_01be: Unknown result type (might be due to invalid IL or missing references) //IL_01b6: Unknown result type (might be due to invalid IL or missing references) //IL_01bb: Unknown result type (might be due to invalid IL or missing references) //IL_01c8: Unknown result type (might be due to invalid IL or missing references) //IL_01d6: Unknown result type (might be due to invalid IL or missing references) //IL_0236: Unknown result type (might be due to invalid IL or missing references) //IL_023d: Expected O, but got Unknown //IL_027e: Unknown result type (might be due to invalid IL or missing references) //IL_0285: Unknown result type (might be due to invalid IL or missing references) if (tombstone != null) { ZNetView nview = tombstone.m_nview; if (((nview != null) ? new bool?(nview.IsValid()) : ((bool?)null)) == true && tombstone.m_nview.IsOwner()) { Container val = (((Object)(object)tombstone.m_container != (Object)null) ? tombstone.m_container : ((Component)tombstone).GetComponent<Container>()); Inventory val2 = ((val != null) ? val.GetInventory() : null); if (val2 == null || val2.m_temoraryInventory || val.m_loading) { return 0; } val.Load(); string payload = GetPayload(tombstone); if (string.IsNullOrEmpty(payload) || !TryReadPayload(payload, out var result)) { return 0; } int height = val2.m_height; int num = 0; long owner = tombstone.GetOwner(); int num2 = 0; while (num2 < result.Count) { Entry entry = result[num2]; if (!TryMaterialize(entry, out var item)) { num2++; continue; } if (!string.IsNullOrEmpty(entry.PreferredSlotId) && owner != 0) { item.m_customData["ExtraSlotsEquippedBy"] = owner.ToString(); item.m_customData["ExtraSlotsEquippedSlot"] = entry.PreferredSlotId; } item.m_equipped = false; int height2 = val2.m_height; Vector2i val3 = FindAppendPosition(val2, height); if (val3.x < 0 && val2.m_height <= 255) { val2.m_height++; val3 = FindAppendPosition(val2, height); } if (val3.x < 0 || val3.x > 255 || val3.y > 255) { val2.m_height = height2; num2++; continue; } List<ItemData> collection = new List<ItemData>(val2.m_inventory); ZDO zDO = val.m_nview.GetZDO(); byte[] array = zDO.GetByteArray(ZDOVars.s_items, (byte[])null); if (array == null) { ZPackage val4 = new ZPackage(); val2.Save(val4); array = val4.GetArray(); } string payload2 = GetPayload(tombstone); int height3 = val.m_height; bool loading = val.m_loading; try { val.m_loading = true; int stack = item.m_stack; if (!val2.AddItem(item, stack, val3.x, val3.y, false)) { throw new InvalidOperationException("Unable to insert tombstone-owned item " + entry.PrefabName + "."); } val.m_height = Math.Max(val.m_height, val2.m_height); val.Save(); result.RemoveAt(num2); PersistPayload(tombstone, result); val.m_lastRevision = zDO.DataRevision; num++; } catch (Exception arg) { val2.m_inventory.Clear(); val2.m_inventory.AddRange(collection); val2.m_height = height2; val2.UpdateTotalWeight(); val.m_height = height3; if (!result.Contains(entry)) { result.Insert(num2, entry); } zDO.Set(ZDOVars.s_items, array); zDO.Set(payloadHash, payload2); PersistDimensions(val); val.m_lastRevision = zDO.DataRevision; ExtraSlots.LogWarning($"Tombstone materialization rolled back; opaque item {entry.PrefabName} was retained:\n{arg}"); num2++; } finally { val.m_loading = loading; } } if (num > 0) { val.m_width = Math.Max(val.m_width, val2.m_width); val.m_height = Math.Max(val.m_height, val2.m_height); PersistDimensions(val); } return num; } } return 0; } private static bool TryReadPayload(string payload, out List<Entry> result) { //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Expected O, but got Unknown result = new List<Entry>(); try { ZPackage val = new ZPackage(payload); int num = val.ReadInt(); if (num != 1) { ExtraSlots.LogWarning($"Tombstone deferred payload uses unsupported envelope version {num}. Opaque data will remain attached to the grave."); return false; } int num2 = val.ReadInt(); if (num2 < 0) { throw new InvalidOperationException($"Invalid tombstone deferred entry count {num2}."); } for (int i = 0; i < num2; i++) { string prefabName = val.ReadString(); string preferredSlotId = val.ReadString(); bool restoreEquipped = val.ReadBool(); int originalStack = val.ReadInt(); string text = val.ReadString(); if (string.IsNullOrEmpty(text)) { throw new InvalidOperationException($"Tombstone deferred entry {i} has an empty item package."); } result.Add(new Entry { PrefabName = prefabName, PreferredSlotId = preferredSlotId, RestoreEquipped = restoreEquipped, OriginalStack = originalStack, ItemPackageBase64 = text }); } return true; } catch (Exception arg) { result.Clear(); ExtraSlots.LogWarning($"Failed to read tombstone deferred payload. Opaque data will remain attached to the grave:\n{arg}"); return false; } } private static bool TryMaterialize(Entry entry, out ItemData item) { //IL_008d: Unknown result type (might be due to invalid IL or missing references) //IL_0094: Expected O, but got Unknown //IL_009c: Unknown result type (might be due to invalid IL or missing references) //IL_00a3: Expected O, but got Unknown item = null; if (entry == null || string.IsNullOrEmpty(entry.PrefabName) || string.IsNullOrEmpty(entry.ItemPackageBase64)) { return false; } ObjectDB instance = ObjectDB.instance; if ((Object)(object)((instance != null) ? instance.GetItemPrefab(entry.PrefabName) : null) == (Object)null) { if (unavailablePrefabsLogged.Add(entry.PrefabName)) { ExtraSlots.LogWarning("Tombstone deferred item prefab " + entry.PrefabName + " is unavailable. Opaque grave ownership will be preserved."); } return false; } try { ZPackage val = new ZPackage(entry.ItemPackageBase64); Inventory val2 = new Inventory("ExtraSlotsDeferredTombstone", (Sprite)null, 1, 1); InventorySerialization.Load(val2, val.ReadCompressedPackage()); item = ((val2.m_inventory.Count == 1) ? val2.m_inventory[0] : null); if (item != null && item.m_stack == entry.OriginalStack) { GameObject dropPrefab = item.m_dropPrefab; if (string.Equals((dropPrefab != null) ? ((Object)dropPrefab).name : null, entry.PrefabName, StringComparison.Ordinal)) { val2.m_inventory.Clear(); item.m_equipped = false; return true; } } item = null; ExtraSlots.LogWarning("Tombstone deferred item " + entry.PrefabName + " did not materialize as the expected single stack. Opaque grave ownership will be preserved."); return false; } catch (Exception arg) { item = null; ExtraSlots.LogWarning($"Failed to materialize tombstone deferred item {entry.PrefabName}. Opaque grave ownership will be preserved:\n{arg}"); return false; } } private static void PersistPayload(TombStone tombstone, IReadOnlyList<Entry> graveEntries) { //IL_0051: Unknown result type (might be due to invalid IL or missing references) //IL_0057: Expected O, but got Unknown object obj; if (tombstone == null) { obj = null; } else { ZNetView nview = tombstone.m_nview; obj = ((nview != null) ? nview.GetZDO() : null); } ZDO val = (ZDO)obj; if (val == null) { return; } if (graveEntries == null || graveEntries.Count == 0) { val.Set(payloadHash, ""); return; } ZPackage val2 = new ZPackage(); val2.Write(1); val2.Write(graveEntries.Count); foreach (Entry graveEntry in graveEntries) { val2.Write(graveEntry.PrefabName ?? ""); val2.Write(graveEntry.PreferredSlotId ?? ""); val2.Write(graveEntry.RestoreEquipped); val2.Write(graveEntry.OriginalStack); val2.Write(graveEntry.ItemPackageBase64 ?? ""); } val.Set(payloadHash, val2.GetBase64()); } private static Vector2i FindAppendPosition(Inventory inventory, int startHeight) { //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_0056: 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) for (int i = Math.Max(0, startHeight); i < inventory.m_height; i++) { for (int j = 0; j < inventory.m_width; j++) { if (inventory.GetItemAt(j, i) == null) { return new Vector2i(j, i); } } } return Slots.emptyPosition; } private static bool PersistDimensions(Container container) { if (container != null) { ZNetView nview = container.m_nview; if (((nview != null) ? new bool?(nview.IsValid()) : ((bool?)null)) == true && container.m_nview.IsOwner() && !((Object)(object)((Component)container).GetComponentInParent<TombStone>() == (Object)null)) { string name = ((object)container).GetType().Name; ZDO zDO = container.m_nview.GetZDO(); zDO.Set("HasFields", true); zDO.Set(StringExtensionMethods.GetStableHashCode("HasFields" + name), true); zDO.Set(name + ".m_width", container.m_width); zDO.Set(name + ".m_height", container.m_height); return true; } } return false; } } public static class ItemNameTokens { [HarmonyPatch(typeof(Player), "Load")] private static class Player_Load_UpdateRegisters { private static void Prefix() { UpdateRegisters(); } } public static readonly Dictionary<string, string> itemNames = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase); public static void UpdateRegisters() { if (!Object.op_Implicit((Object)(object)ObjectDB.instance)) { return; } foreach (GameObject item in ObjectDB.instance.m_items) { if ((Object)(object)item == (Object)null) { continue; } ItemDrop component = item.GetComponent<ItemDrop>(); if (component == null) { continue; } ItemData itemData = component.m_itemData; if (itemData != null) { SharedData shared = itemData.m_shared; if (shared != null && shared.m_name.StartsWith("$")) { itemNames[((Object)item).name] = shared.m_name; itemNames[shared.m_name] = shared.m_name; } } } Slots.UpdateCustomItemLists(); ExtraUtilitySlots.UpdateUniqueEquipped(); TombStoneInteraction.UpdateItemLists(); } public static string GetItemName(this string input) { return itemNames.GetValueOrDefault(input.Trim(), input); } } public static class LightenedSlots { private static readonly List<int> m_affectedRows = new List<int>(); public static bool IsEnabled => ExtraSlots.lightenedSlotsStartIndex.Value != 0; public static float WeightFactor => ExtraSlots.lightenedSlotsWeightFactor.Value; public static bool IsRowAffected(int row) { return IsEnabled && m_affectedRows.Contains(row); } public static void UpdateState() { UpdateAffectedRows(); InventoryInteraction.UpdateTotalWeight(); } public static void UpdateAffectedRows() { m_affectedRows.Clear(); if (!IsEnabled || !SlotsProgression.IsPlayerKeyItemConditionMet(ExtraSlots.lightenedSlotsPlayerKey.Value, ExtraSlots.lightenedSlotsItemDiscovered.Value)) { return; } for (int i = 0; i < Slots.InventoryHeightPlayer; i++) { if (!ExtraSlots.lightenedSlotsOnlyExtraRows.Value || i >= Slots.NativeInventoryHeight) { if (ExtraSlots.lightenedSlotsStartIndex.Value < 0 && i >= ExtraSlots.lightenedSlotsStartIndex.Value + Slots.InventoryHeightPlayer) { m_affectedRows.Add(i); } else if (ExtraSlots.lightenedSlotsStartIndex.Value > 0 && i >= ExtraSlots.lightenedSlotsStartIndex.Value - 1) { m_affectedRows.Add(i); } } } } } internal class CustomConfigs { internal class ConfigurationManagerAttributes { [UsedImplicitly] public Action<ConfigEntryBase>? CustomDrawer; } internal static object? configManager; internal static Type? configManagerStyles; internal static GUIStyle GetStyle(GUIStyle other) { //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_0051: Expected O, but got Unknown if (configManagerStyles == null) { return other; } FieldInfo fieldInfo = AccessTools.Field(configManagerStyles, "fontSize"); if (fieldInfo == null) { return other; } return new GUIStyle(other) { fontSize = (int)fieldInfo.GetValue(configManagerStyles) }; } internal static void Awake() { Assembly assembly = AppDomain.CurrentDomain.GetAssemblies().FirstOrDefault((Assembly a) => a.GetName().Name == "ConfigurationManager"); Type type = assembly?.GetType("ConfigurationManager.ConfigurationManager"); configManager = ((type == null) ? null : Chainloader.ManagerObject.GetComponent(type)); configManagerStyles = assembly?.GetType("ConfigurationManager.ConfigurationManagerStyles"); } internal static Action<ConfigEntryBase> DrawSeparatedStrings(string splitString) { return delegate(ConfigEntryBase cfg) { //IL_010a: Unknown result type (might be due to invalid IL or missing references) //IL_010f: Unknown result type (might be due to invalid IL or missing references) //IL_0125: Expected O, but got Unknown //IL_0155: Unknown result type (might be due to invalid IL or missing references) //IL_015a: Unknown result type (might be due to invalid IL or missing references) //IL_0170: Expected O, but got Unknown bool valueOrDefault = cfg.Description.Tags.Select((object a) => (a.GetType().Name == "ConfigurationManagerAttributes") ? ((bool?)a.GetType().GetField("ReadOnly")?.GetValue(a)) : ((bool?)null)).FirstOrDefault((bool? v) => v.HasValue) == true; bool flag = false; GUILayout.BeginVertical(Array.Empty<GUILayoutOption>()); List<string> list = new List<string>(); List<string> list2 = ((string)cfg.BoxedValue).Split(new string[1] { splitString }, StringSplitOptions.None).ToList(); for (int num = 0; num < list2.Count; num++) { GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>()); string text = list2[num]; string text2 = GUILayout.TextField(text, GetStyle(GUI.skin.textArea), (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.ExpandWidth(true) }); if (text2 != text && !valueOrDefault) { flag = true; } if (GUILayout.Button("x", new GUIStyle(GetStyle(GUI.skin.button)) { fixedWidth = 21f }, Array.Empty<GUILayoutOption>()) && !valueOrDefault) { flag = true; } else { list.Add(text2); } if (GUILayout.Button("+", new GUIStyle(GetStyle(GUI.skin.button)) { fixedWidth = 21f }, Array.Empty<GUILayoutOption>()) && !valueOrDefault) { flag = true; list.Add(""); } GUILayout.EndHorizontal(); } GUILayout.EndVertical(); if (flag) { cfg.BoxedValue = string.Join(splitString, list); } }; } internal static Action<ConfigEntryBase> DrawOrderedFixedStrings(string splitString) { return delegate(ConfigEntryBase cfg) { //IL_00e4: Unknown result type (might be due to invalid IL or missing references) //IL_00e9: Unknown result type (might be due to invalid IL or missing references) //IL_00ff: Expected O, but got Unknown //IL_015b: Unknown result type (might be due to invalid IL or missing references) //IL_0160: Unknown result type (might be due to invalid IL or missing references) //IL_0176: Expected O, but got Unknown bool valueOrDefault = cfg.Description.Tags.Select((object a) => (a.GetType().Name == "ConfigurationManagerAttributes") ? ((bool?)a.GetType().GetField("ReadOnly")?.GetValue(a)) : ((bool?)null)).FirstOrDefault((bool? v) => v.HasValue) == true; bool flag = false; GUILayout.BeginVertical(Array.Empty<GUILayoutOption>()); string[] array = ((string)cfg.BoxedValue).Split(new string[1] { splitString }, StringSplitOptions.None).ToArray(); for (int num = 0; num < array.Length; num++) { GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>()); string text = array[num]; GUILayout.Label(text, GetStyle(GUI.skin.textArea), (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.ExpandWidth(true) }); if (GUILayout.Button("ʌ", new GUIStyle(GetStyle(GUI.skin.button)) { fixedWidth = 21f }, Array.Empty<GUILayoutOption>()) && !valueOrDefault && (flag = num > 0)) { ref string reference = ref array[num]; ref string reference2 = ref array[num - 1]; string text2 = array[num - 1]; string text3 = array[num]; reference = text2; reference2 = text3; } if (GUILayout.Button("v", new GUIStyle(GetStyle(GUI.skin.button)) { fixedWidth = 21f }, Array.Empty<GUILayoutOption>()) && !valueOrDefault && (flag = num < array.Length - 1)) { ref string reference = ref array[num]; ref string reference3 = ref array[num + 1]; string text3 = array[num + 1]; string text2 = array[num]; reference = text3; reference3 = text2; } GUILayout.EndHorizontal(); } GUILayout.EndVertical(); if (flag) { cfg.BoxedValue = string.Join(splitString, array); } }; } } public static class EquipmentPanel { public class SidePanelDefaults { public bool active; public Vector2 anchoredPosition = Vector2.zero; public Vector2 anchorMin = Vector2.zero; public Vector2 anchorMax = Vector2.zero; } private static class SlotPositions { private static int Column(int i) { return i / 3; } private static int Row(int i) { return i % 3; } private static int LastEquipmentRow() { return Row(equipmentSlotsCount - 1); } internal static int LastEquipmentColumn() { return Column(equipmentSlotsCount - 1); } internal static Vector2 GetEquipmentTileOffset(int i) { //IL_0079: Unknown result type (might be due to invalid IL or missing references) //IL_007e: 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) int x = Column(i) * 4 + ((ExtraSlots.equipmentSlotsAlignment.Value == ExtraSlots.SlotsAlignment.VerticalTopHorizontalMiddle && Row(i) > LastEquipmentRow()) ? 1 : 0) * 2 + Math.Max(quickSlotsCount - 1 - LastEquipmentColumn(), 0) * 2; int y = Row(i) * 4 + Math.Max((ExtraSlots.equipmentSlotsAlignment.Value == ExtraSlots.SlotsAlignment.VerticalMiddleHorizontalLeft && Column(i) == LastEquipmentColumn()) ? (2 - LastEquipmentRow()) : 0, 0) * 2; return GetSlotPosition(x, y); } internal static Vector2 GetQuickSlotTileOffset(int i) { //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Unknown result type (might be due to invalid IL or missing references) int x = i * 4 + Math.Max(ExtraSlots.quickSlotsAlignmentCenter.Value ? (LastEquipmentColumn() + 1 - quickSlotsCount) : 0, 0); int y = EquipmentHeight * 4 + 1; return GetSlotPosition(x, y); } internal static Vector2 GetFoodSlotTileOffset(int i) { //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0022: 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) int x = Math.Max(LastEquipmentColumn() + 1, quickSlotsCount) * 4 + 1; int y = i * 4; return GetSlotPosition(x, y); } internal static Vector2 GetAmmoSlotTileOffset(int i) { //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Unknown result type (might be due to invalid IL or missing references) int x = Math.Max(LastEquipmentColumn() + 1, quickSlotsCount) * 4 + 1 + (Slots.IsFoodSlotAvailable() ? 4 : 0); int y = i * 4; return GetSlotPosition(x, y); } internal static Vector2 GetMiscSlotTileOffset(int i) { //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_002f: Unknown result type (might be due to invalid IL or missing references) int x = Math.Max(LastEquipmentColumn() + 1, quickSlotsCount) * 4 + i * 4 + 1; int y = EquipmentHeight * 4 + 1; return GetSlotPosition(x, y); } private static Vector2 GetSlotPosition(int x, int y) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Unknown result type (might be due to invalid IL or missing references) return PanelPosition + new Vector2((float)x * 70f / 4f, (float)(-y) * 70f / 4f); } } [HarmonyPatch(typeof(InventoryGui), "Show")] private static class InventoryGui_Show_UpdatePanel { private static void Postfix() { if (!((Object)(object)Player.m_localPlayer == (Object)null)) { UpdatePanel(); } } } [HarmonyPatch(typeof(InventoryGui), "OnDestroy")] private static class InventoryGui_OnDestroy_ClearObjects { private static void Postfix() { ClearPanel(); } } [HarmonyPatch(typeof(InventoryGui), "Update")] private static class InventoryGui_Update_UpdateEquipmentPanel { private static void Postfix() { if (Object.op_Implicit((Object)(object)Player.m_localPlayer) && InventoryGui.IsVisible()) { UpdateEquipmentBackground(); } } } [HarmonyPatch(typeof(InventoryGrid), "UpdateGui")] internal static class InventoryGrid_UpdateGui_UpdateSlotsOnDirty { private static void Prefix(InventoryGrid __instance, ref int __state) { if (!((Object)(object)__instance != (Object)(object)InventoryGui.instance.m_playerGrid)) { __state = __instance.m_elements.Count; } } private static void Postfix(InventoryGrid __instance, int __state) { if (!((Object)(object)__instance != (Object)(object)InventoryGui.instance.m_playerGrid)) { if (__state != __instance.m_elements.Count) { MarkDirty(); } UpdateInventorySlots(); } } } [HarmonyPatch(typeof(InventoryGui), "SetupDragItem")] private static class InventoryGui_SetupDragItem_UpdateSlotsOnItemDrag { private static void Prefix(InventoryGui __instance, ref bool __state) { __state = Object.op_Implicit((Object)(object)__instance.m_dragGo); } private static void Postfix(InventoryGui __instance, bool __state) { MarkDirty(); if (!Object.op_Implicit((Object)(object)__instance.m_dragGo) && __state) { UpdateSidePanels(); } } } [HarmonyPatch(typeof(InventoryGrid), "UpdateGamepad")] public static class InventoryGrid_UpdateGamepad_GamepadSupport { public static Vector2i FindEquipmentSlot(int row = -1, Slots.Slot slotRow = null, int col = -1, Slots.Slot slotCol = null, bool right = false, Slots.Slot before = null, Slots.Slot after = null) { //IL_010b: Unknown result type (might be due to invalid IL or missing references) //IL_0110: Unknown result type (might be due to invalid IL or missing references) //IL_0114: Unknown result type (might be due to invalid IL or missing references) //IL_00cd: Unknown result type (might be due to invalid IL or missing references) //IL_00d2: Unknown result type (might be due to invalid IL or missing references) //IL_00f9: Unknown result type (might be due to invalid IL or missing references) //IL_00fe: Unknown result type (might be due to invalid IL or missing references) Slots.Slot[] equipmentSlots = Slots.GetEquipmentSlots(); if (row == -1 && slotRow != null) { row = Array.IndexOf(equipmentSlots, slotRow) % 3; } if (col == -1 && slotCol != null) { col = Array.IndexOf(equipmentSlots, slotCol) / 3; } int num = ((before == null) ? (-1) : Array.IndexOf(equipmentSlots, before)); int num2 = ((after == null) ? (-1) : Array.IndexOf(equipmentSlots, after)); int num3 = (right ? equipmentSlots.Length : (-1)); while (true) { num3 = ((!right) ? (num3 + 1) : (num3 - 1)); if (num3 < 0 || num3 == equipmentSlots.Length) { break; } if ((num <= -1 || num3 < num) && (num2 <= -1 || num3 > num2)) { if (row == -1 && col == -1) { return equipmentSlots[num3].GridPosition; } if ((row != -1 && row == num3 % 3) || (col != -1 && col == num3 / 3)) { return equipmentSlots[num3].GridPosition; } } } return Slots.emptyPosition; } private static bool Prefix(InventoryGrid __instance) { //IL_0045: 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_00bc: Unknown result type (might be due to invalid IL or missing references) //IL_0378: Unknown result type (might be due to invalid IL or missing references) //IL_0158: Unknown result type (might be due to invalid IL or missing references) //IL_015d: Unknown result type (might be due to invalid IL or missing references) //IL_0163: Unknown result type (might be due to invalid IL or missing references) //IL_0168: Unknown result type (might be due to invalid IL or missing references) //IL_0182: Unknown result type (might be due to invalid IL or missing references) //IL_0187: Unknown result type (might be due to invalid IL or missing references) //IL_0502: Unknown result type (might be due to invalid IL or missing references) //IL_0308: Unknown result type (might be due to invalid IL or missing references) //IL_030d: Unknown result type (might be due to invalid IL or missing references) //IL_01fd: Unknown result type (might be due to invalid IL or missing references) //IL_01cc: Unknown result type (might be due to invalid IL or missing references) //IL_01d1: 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_00fd: Unknown result type (might be due to invalid IL or missing references) //IL_0103: Unknown result type (might be due to invalid IL or missing references) //IL_0108: Unknown result type (might be due to invalid IL or missing references) //IL_07a8: Unknown result type (might be due to invalid IL or missing references) //IL_04ad: Unknown result type (might be due to invalid IL or missing references) //IL_04b2: Unknown result type (might be due to invalid IL or missing references) //IL_04b4: Unknown result type (might be due to invalid IL or missing references) //IL_04b6: Unknown result type (might be due to invalid IL or missing references) //IL_033c: Unknown result type (might be due to invalid IL or missing references) //IL_0341: Unknown result type (might be due to invalid IL or missing references) //IL_0220: Unknown result type (might be due to invalid IL or missing references) //IL_0225: Unknown result type (might be due to invalid IL or missing references) //IL_0122: Unknown result type (might be due to invalid IL or missing references) //IL_0127: Unknown result type (might be due to invalid IL or missing references) //IL_056e: Unknown result type (might be due to invalid IL or missing references) //IL_04c7: Unknown result type (might be due to invalid IL or missing references) //IL_04c9: Unknown result type (might be due to invalid IL or missing references) //IL_066f: Unknown result type (might be due to invalid IL or missing references) //IL_0674: Unknown result type (might be due to invalid IL or missing references) //IL_0525: Unknown result type (might be due to invalid IL or missing references) //IL_052a: Unknown result type (might be due to invalid IL or missing references) //IL_0416: Unknown result type (might be due to invalid IL or missing references) //IL_041b: Unknown result type (might be due to invalid IL or missing references) //IL_09ef: Unknown result type (might be due to invalid IL or missing references) //IL_07ff: Unknown result type (might be due to invalid IL or missing references) //IL_0804: Unknown result type (might be due to invalid IL or missing references) //IL_05e4: Unknown result type (might be due to invalid IL or missing references) //IL_0842: Unknown result type (might be due to invalid IL or missing references) //IL_0847: Unknown result type (might be due to invalid IL or missing references) //IL_076c: Unknown result type (might be due to invalid IL or missing references) //IL_0771: Unknown result type (might be due to invalid IL or missing references) //IL_0591: Unknown result type (might be due to invalid IL or missing references) //IL_0596: Unknown result type (might be due to invalid IL or missing references) //IL_0482: Unknown result type (might be due to invalid IL or missing references) //IL_0487: Unknown result type (might be due to invalid IL or missing references) //IL_0469: Unknown result type (might be due to invalid IL or missing references) //IL_046e: Unknown result type (might be due to invalid IL or missing references) //IL_02a7: Unknown result type (might be due to invalid IL or missing references) //IL_02ac: Unknown result type (might be due to invalid IL or missing references) //IL_0292: Unknown result type (might be due to invalid IL or missing references) //IL_0297: Unknown result type (might be due to invalid IL or missing references) //IL_0993: Unknown result type (might be due to invalid IL or missing references) //IL_0998: Unknown result type (might be due to invalid IL or missing references) //IL_092a: Unknown result type (might be due to invalid IL or missing references) //IL_092f: Unknown result type (might be due to invalid IL or missing references) //IL_06e1: Unknown result type (might be due to invalid IL or missing references) //IL_06e6: Unknown result type (might be due to invalid IL or missing references) //IL_0655: Unknown result type (might be due to invalid IL or missing references) //IL_065a: Unknown result type (might be due to invalid IL or missing references) //IL_02ef: Unknown result type (might be due to invalid IL or missing references) //IL_02f4: Unknown result type (might be due to invalid IL or missing references) //IL_02d8: Unknown result type (might be due to invalid IL or missing references) //IL_02dd: Unknown result type (might be due to invalid IL or missing references) //IL_0be2: Unknown result type (might be due to invalid IL or missing references) //IL_09b3: Unknown result type (might be due to invalid IL or missing references) //IL_09b8: Unknown result type (might be due to invalid IL or missing references) //IL_0950: Unknown result type (might be due to invalid IL or missing references) //IL_0955: Unknown result type (might be due to invalid IL or missing references) //IL_08ca: Unknown result type (might be due to invalid IL or missing references) //IL_08bf: Unknown result type (might be due to invalid IL or missing references) //IL_08c4: Unknown result type (might be due to invalid IL or missing references) //IL_0607: Unknown result type (might be due to invalid IL or missing references) //IL_060c: Unknown result type (might be due to invalid IL or missing references) //IL_0970: Unknown result type (might be due to invalid IL or missing references) //IL_0975: Unknown result type (might be due to invalid IL or missing references) //IL_0899: Unknown result type (might be due to invalid IL or missing references) //IL_089e: Unknown result type (might be due to invalid IL or missing references) //IL_0743: Unknown result type (might be due to invalid IL or missing references) //IL_0748: Unknown result type (might be due to invalid IL or missing references) //IL_0a4e: Unknown result type (might be due to invalid IL or missing references) //IL_08ef: Unknown result type (might be due to invalid IL or missing references) //IL_08f4: Unknown result type (might be due to invalid IL or missing references) //IL_0b62: Unknown result type (might be due to invalid IL or missing references) //IL_0b2f: Unknown result type (might be due to invalid IL or missing references) //IL_0b34: Unknown result type (might be due to invalid IL or missing references) //IL_0afc: Unknown result type (might be due to invalid IL or missing references) //IL_0b01: Unknown result type (might be due to invalid IL or missing references) //IL_0b56: Unknown result type (might be due to invalid IL or missing references) //IL_0b5b: Unknown result type (might be due to invalid IL or missing references) //IL_0ab3: Unknown result type (might be due to invalid IL or missing references) //IL_0ab8: Unknown result type (might be due to invalid IL or missing references) //IL_0ba6: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)__instance != (Object)(object)InventoryGui.instance.m_playerGrid || !__instance.m_uiGroup.IsActive || Console.IsVisible() || ZInput.IsTouchActive() || !ZInput.IsExclusiveGamepadActive()) { return true; } Slots.Slot slotInGrid = Slots.GetSlotInGrid(__instance.m_selected); if (ZInput.GetButtonDown("JoyDPadLeft") || ZInput.GetButtonDown("JoyLStickLeft")) { ExtraSlots.LogDebug($"From {__instance.m_selected} {slotInGrid} left"); if (slotInGrid != null) { if (slotInGrid.IsAmmoSlot) { __instance.m_selected.x += 3; Slots.Slot slotInGrid2 = Slots.GetSlotInGrid(__instance.m_selected); if (slotInGrid2 == null || !slotInGrid2.IsActive) { int num = __instance.m_selected.x % 3; __instance.m_selected = FindEquipmentSlot(num, null, -1, null, right: true); if (__instance.m_selected == Slots.emptyPosition) { __instance.m_selected = new Vector2i(Slots.InventoryWidth - 1, num); } } } else if (slotInGrid.IsFoodSlot) { int num2 = __instance.m_selected.x % 3; __instance.m_selected = FindEquipmentSlot(num2, null, -1, null, right: true); if (__instance.m_selected == Slots.emptyPosition) { __instance.m_selected = new Vector2i(Slots.InventoryWidth - 1, num2); } } else if (slotInGrid.IsQuickSlot) { __instance.m_selected.x--; if (__instance.m_selected.x < 0) { __instance.m_selected = new Vector2i(Slots.InventoryWidth - 1, 3); } } else if (slotInGrid.IsMiscSlot) { __instance.m_selected.x--; Slots.Slot slotInGrid3 = Slots.GetSlotInGrid(__instance.m_selected); if (slotInGrid3 == null) { __instance.m_selected = new Vector2i(Slots.InventoryWidth - 1, 3); } else if (!slotInGrid3.IsActive) { if (slotInGrid3.IsQuickSlot) { IEnumerable<Slots.Slot> source = from slot3 in Slots.GetQuickSlots() where slot3.IsActive select slot3; if (source.Any()) { __instance.m_selected = source.Last().GridPosition; } else { __instance.m_selected = new Vector2i(Slots.InventoryWidth - 1, 3); } } else if (slotInGrid3.IsMiscSlot && quickSlotsCount == 0) { __instance.m_selected = new Vector2i(Slots.InventoryWidth - 1, 3); } else { __instance.m_selected = new Vector2i(Slots.InventoryWidth - 1, 3); } } } else { __instance.m_selected = FindEquipmentSlot(-1, slotInGrid, -1, null, right: true, slotInGrid); if (__instance.m_selected.x < 0) { __instance.m_selected = new Vector2i(Slots.InventoryWidth - 1, Array.IndexOf(Slots.GetEquipmentSlots(), slotInGrid) % 3); } } return false; } } if (ZInput.GetButtonDown("JoyDPadRight") || ZInput.GetButtonDown("JoyLStickRight")) { ExtraSlots.LogDebug($"From {__instance.m_selected} {slotInGrid} right"); if (slotInGrid != null) { if (slotInGrid.IsFoodSlot) { Slots.Slot slotInGrid4 = Slots.GetSlotInGrid(new Vector2i(__instance.m_selected.x - 3, __instance.m_selected.y)); if (slotInGrid4 != null && slotInGrid4.IsActive) { __instance.m_selected = slotInGrid4.GridPosition; } } else { if (slotInGrid.IsAmmoSlot) { return false; } if (slotInGrid.IsMiscSlot) { Slots.Slot slotInGrid5 = Slots.GetSlotInGrid(new Vector2i(__instance.m_selected.x + 1, __instance.m_selected.y)); if (slotInGrid5 != null && slotInGrid5.IsActive) { __instance.m_selected = slotInGrid5.GridPosition; } } else if (slotInGrid.IsQuickSlot) { if (__instance.m_selected.x < quickSlotsCount - 1) { Slots.Slot slotInGrid6 = Slots.GetSlotInGrid(new Vector2i(__instance.m_selected.x + 1, __instance.m_selected.y)); if (slotInGrid6 != null && slotInGrid6.IsActive) { __instance.m_selected = slotInGrid6.GridPosition; } } else { IEnumerable<Slots.Slot> source2 = from slot3 in Slots.GetMiscSlots() where slot3.IsActive select slot3; if (source2.Any()) { __instance.m_selected = source2.First().GridPosition; } } } else { __instance.m_selected = FindEquipmentSlot(-1, slotInGrid, -1, null, right: false, null, slotInGrid); if (__instance.m_selected.x < 0) { Slots.Slot[] array = (from slot3 in Slots.GetFoodSlots() where slot3.IsActive select slot3).ToArray(); if (array.Length == 3) { __instance.m_selected = array[Array.IndexOf(Slots.GetEquipmentSlots(), slotInGrid) % 3].GridPosition; return false; } Slots.Slot[] array2 = (from slot3 in Slots.GetAmmoSlots() where slot3.IsActive select slot3).ToArray(); if (array2.Length == 3) { __instance.m_selected = array2[Array.IndexOf(Slots.GetEquipmentSlots(), slotInGrid) % 3].GridPosition; return false; } } if (__instance.m_selected.x < 0) { __instance.m_selected = slotInGrid.GridPosition; } } } return false; } if (__instance.m_selected.x >= Slots.InventoryWidth - 1) { if (__instance.m_selected.y > 2) { IEnumerable<Slots.Slot> source3 = from slot3 in Slots.GetQuickSlots() where slot3.IsActive select slot3; if (source3.Any()) { __instance.m_selected = source3.First().GridPosition; return false; } IEnumerable<Slots.Slot> source4 = from slot3 in Slots.GetMiscSlots() where slot3.IsActive select slot3; if (source4.Any()) { __instance.m_selected = source4.First().GridPosition; return false; } __instance.m_selected = new Vector2i(0, Slots.InventoryHeightPlayer); } else { Vector2i val = FindEquipmentSlot(Math.Min(__instance.m_selected.y, equipmentSlotsCount - 1)); if (val != Slots.emptyPosition) { __instance.m_selected = val; } } return false; } } if (ZInput.GetButtonDown("JoyDPadUp") || ZInput.GetButtonDown("JoyLStickUp")) { ExtraSlots.LogDebug($"From {__instance.m_selected} {slotInGrid} up"); if (slotInGrid != null) { if (slotInGrid.IsFoodSlot) { __instance.m_selected.x--; if (__instance.m_selected.x < 3) { __instance.m_selected = slotInGrid.GridPosition; } } else if (slotInGrid.IsAmmoSlot) { __instance.m_selected.x--; if (__instance.m_selected.x < 0) { __instance.m_selected = slotInGrid.GridPosition; } } else if (slotInGrid.IsMiscSlot) { if (slotInGrid.Index == 6) { Slots.Slot slot = Slots.GetFoodSlots().Last(); __instance.m_selected = ((slot != null && slot.IsActive) ? slot : Slots.GetAmmoSlots().Last()).GridPosition; } else if (slotInGrid.Index == 7) { __instance.m_selected = Slots.GetAmmoSlots().Last().GridPosition; } Slots.Slot slotInGrid7 = Slots.GetSlotInGrid(__instance.m_selected); if (slotInGrid7 == null || !slotInGrid7.IsActive) { __instance.m_selected = slotInGrid.GridPosition; } } else if (slotInGrid.IsQuickSlot) { __instance.m_selected = FindEquipmentSlot(-1, null, Math.Min(__instance.m_selected.x, equipmentSlotsCount / 3), null, right: true); if (__instance.m_selected.x < 0) { __instance.m_selected = FindEquipmentSlot(-1, null, -1, null, right: true); } if (__instance.m_selected.x < 0) { __instance.m_selected = slotInGrid.GridPosition; } } else { __instance.m_selected = FindEquipmentSlot(-1, null, Array.IndexOf(Slots.GetEquipmentSlots(), slotInGrid) / 3, null, right: true, slotInGrid); if (__instance.m_selected.x < 0) { __instance.m_selected = slotInGrid.GridPosition; } } return false; } } if (ZInput.GetButtonDown("JoyDPadDown") || ZInput.GetButtonDown("JoyLStickDown")) { ExtraSlots.LogDebug($"From {__instance.m_selected} {slotInGrid} down"); if (slotInGrid != null) { if (slotInGrid.IsQuickSlot || slotInGrid.IsMiscSlot) { if (!__instance.jumpToNextContainer) { return false; } __instance.OnMoveToLowerInventoryGrid?.Invoke(__instance.m_selected); return false; } if (slotInGrid.IsAmmoSlot) { __instance.m_selected.x++; if (__instance.m_selected.x > 2) { Slots.Slot slot2 = Slots.GetMiscSlots()[1]; __instance.m_selected = ((slot2 != null && slot2.IsActive) ? slot2 : Slots.GetMiscSlots()[0]).GridPosition; } } else if (slotInGrid.IsFoodSlot) { __instance.m_selected.x++; if (__instance.m_selected.x > 5) { __instance.m_selected = Slots.GetMiscSlots()[0].GridPosition; } } else if (slotInGrid.IsEquipmentSlot) { int num3 = Array.IndexOf(Slots.GetEquipmentSlots(), slotInGrid) / 3; __instance.m_selected = FindEquipmentSlot(-1, null, num3, null, right: false, null, slotInGrid); if (__instance.m_selected.x < 0) { __instance.m_selected = Slots.GetQuickSlots()[num3].GridPosition; } } Slots.Slot slotInGrid8 = Slots.GetSlotInGrid(__instance.m_selected); if (slotInGrid8 == null || !slotInGrid8.IsActive) { if (!__instance.jumpToNextContainer) { return false; } __instance.OnMoveToLowerInventoryGrid?.Invoke(__instance.m_selected); } return false; } if (__instance.m_selected.y >= Slots.InventoryHeightPlayer - 1) { __instance.OnMoveToLowerInventoryGrid?.Invoke(__instance.m_selected); return false; } } return true; } private static void Postfix(InventoryGrid __instance, bool __runOriginal) { //IL_000f: Unknown result type (might be due to invalid IL or missing references) if (!__runOriginal) { ExtraSlots.LogDebug($"Selected {__instance.m_selected}"); } } } [HarmonyPatch(typeof(InventoryGrid), "SetGamepadSelection")] public static class InventoryGrid_SetSelection_GamepadSupport { private static void Prefix(InventoryGrid __instance, ref Vector2i pos) { //IL_0027: Unknown result type (might be due to invalid IL or missing references) if (Object.op_Implicit((Object)(object)InventoryGui.instance) && !((Object)(object)__instance != (Object)(object)InventoryGui.instance.m_playerGrid)) { Slots.Slot slotInGrid = Slots.GetSlotInGrid(pos); if (slotInGrid == null || slotInGrid.IsEmptySlot || !slotInGrid.IsActive) { pos.x = Mathf.Clamp(pos.x, 0, Slots.InventoryWidth - 1); pos.y = Mathf.Clamp(pos.y, 0, Slots.InventoryHeightPlayer - 1); } } } } [HarmonyPatch(typeof(RectTransformUtility), "RectangleContainsScreenPoint", new Type[] { typeof(RectTransform), typeof(Vector2) })] public static class RectTransformUtility_RectangleContainsScreenPoint_BackpacksCompat { private static void Postfix(RectTransform rect, Vector2 screenPoint, ref bool __result) { //IL_006a: Unknown result type (might be due to invalid IL or missing references) if (!Object.op_Implicit((Object)(object)InventoryGui.instance) || (Object)(object)rect != (Object)(object)InventoryGui.instance.m_playerGrid.m_gridRoot) { return; } for (int i = 0; i < Math.Min(Slots.slots.Length, InventoryGui.instance.m_playerGrid.m_elements.Count - Slots.InventorySizePlayer); i++) { InventoryElement val = InventoryGui.instance.m_playerGrid.m_elements[Slots.InventorySizePlayer + i]; if (Object.op_Implicit((Object)(object)val) && ((Component)val).gameObject.activeInHierarchy && RectTransformUtility.RectangleContainsScreenPoint(val.GetElementRectTransform(), screenPoint)) { __result = true; break; } } } } private const string BackgroundName = "ExtraSlotsEquipmentPanel"; private const float tileSpace = 6f; private const float tileSize = 70f; private const float interslotSpaceInTiles = 0.25f; private const float inventoryPanelOffset = 100f; private static int equipmentSlotsCount = 0; internal static int quickSlotsCount = 0; private static Vector2? draggedPanelOffset; private static readonly Vector3[] dragRectCorners = (Vector3[])(object)new Vector3[4]; public static RectTransform inventoryDarken = null; public static RectTransform inventoryBackground = null; public static Image inventoryBackgroundImage = null; public static RectTransform equipmentBackground = null; public static Image equipmentBackgroundImage = null; public static RectTransform selectedFrame = null; public static RectTransform inventorySelectedFrame = null; private static bool isDirty = true; private static int updateSidePanelsInFrames; private static int updateSidePanelsPreviousExtraRows = -10; private static Color normalColor = Color.clear; private static Color highlightedColor = Color.clear; private static Color normalColorUnfit = Color.clear; private static Color highlightedColorUnfit = Color.clear; private static Material iconMaterial; private static Vector3 originalScale = Vector3.zero; private static Vector2 originalTooltipPosition = Vector2.zero; internal static Sprite ammoSlot; internal static Sprite miscSlot; internal static Sprite quickSlot; internal static Sprite lightenedSlot; internal static Sprite background; private static readonly Dictionary<string, SidePanelDefaults> defaultPositionsSidePanels = new Dictionary<string, SidePanelDefaults>(); private static float InventoryPanelWidth { get { //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Unknown result type (might be due to invalid IL or missing references) float result; if (!Object.op_Implicit((Object)(object)InventoryGui.instance)) { result = 0f; } else { Rect rect = InventoryGui.instance.m_player.rect; result = ((Rect)(ref rect)).width; } return result; } } private static float PanelWidth => ((float)Math.Max(quickSlotsCount, SlotPositions.LastEquipmentColumn() + 1) + FoodAmmoSlotsWidthInTiles) * 70f + 3f; private static float PanelHeight => (((quickSlotsCount > 0 || Slots.IsFirstMiscSlotAvailable()) ? 1.25f : 0f) + (float)EquipmentHeight) * 70f + 3f; private static Vector2 CurrentPanelOffset => (Vector2)(((??)draggedPanelOffset) ?? ExtraSlots.equipmentPanelOffset.Value); private static Vector2 PanelOffset => new Vector2(CurrentPanelOffset.x, 0f - CurrentPanelOffset.y); private static Vector2 PanelPosition => GetPanelPosition(CurrentPanelOffset); private static float FoodAmmoSlotsWidthInTiles => ((Slots.IsFoodSlotAvailable() || Slots.IsAmmoSlotAvailable()) ? 0.25f : 0f) + (Slots.IsFoodSlotAvailable() ? 1f : 0f) + (Slots.IsAmmoSlotAvailable() ? 1f : 0f); private static int EquipmentHeight => (equipmentSlotsCount > 3 || Slots.IsFoodSlotAvailable() || Slots.IsAmmoSlotAvailable()) ? 3 : equipmentSlotsCount; private static bool CanDragPanel => UIDragging.CanDrag(ExtraSlots.panelsDraggable.Value, ExtraSlots.panelsDragKey.Value); private static RectTransform SelectedFrameArmor { get { Transform obj = ((Transform)InventoryGui.instance.m_player).Find("selected_frame/selected (2)"); return (RectTransform)(object)((obj is RectTransform) ? obj : null); } } private static RectTransform SelectedFrameWeight { get { Transform obj = ((Transform)InventoryGui.instance.m_player).Find("selected_frame/selected (3)"); return (RectTransform)(object)((obj is RectTransform) ? obj : null); } } private static Vector2 GetPanelPosition(Vector2 offset) { //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_0012: 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) return new Vector2(InventoryPanelWidth + 100f + offset.x, 0f - offset.y); } private static Vector2 SnapPanelOffset(Vector2 offset) { //IL_003d: 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_002a: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_029f: 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) //IL_00b7: Unknown result type (might be due to invalid IL or missing references) //IL_00bc: Unknown result type (might be due to invalid IL or missing references) //IL_00ae: Unknown result type (might be due to invalid IL or missing references) //IL_00af: Unknown result type (might be due to invalid IL or missing references) //IL_029a: Unknown result type (might be due to invalid IL or missing references) //IL_029b: Unknown result type (might be due to invalid IL or missing references) if (!ExtraSlots.equipmentPanelSticky.Value || ExtraSlots.equipmentPanelStickyDistance.Value <= 0f) { return offset; } float value = ExtraSlots.equipmentPanelStickyDistance.Value; bool flag = Mathf.Abs(offset.x) <= value; bool flag2 = Mathf.Abs(offset.y) <= value; if (flag) { offset.x = 0f; } if (flag2) { offset.y = 0f; } if (!Object.op_Implicit((Object)(object)InventoryGui.instance) || !Object.op_Implicit((Object)(object)InventoryGui.instance.m_player)) { return offset; } Rect predictedPanelRect = GetPredictedPanelRect(offset); RectTransform[] array = (RectTransform[])(object)new RectTransform[5] { inventoryBackground, InventoryGui.instance.m_player, InventoryGui.instance.m_crafting, InventoryGui.instance.m_info, InventoryGui.instance.m_container }; float bestDelta = 0f; float bestDistance = value + 1f; RectTransform[] array2 = array; foreach (RectTransform target in array2) { if (TryGetRectInPlayerSpace(target, out var rect) && RangesOverlap(((Rect)(ref predictedPanelRect)).yMin, ((Rect)(ref predictedPanelRect)).yMax, ((Rect)(ref rect)).yMin, ((Rect)(ref rect)).yMax)) { ConsiderSnap(((Rect)(ref rect)).xMin - ((Rect)(ref predictedPanelRect)).xMax, ref bestDelta, ref bestDistance, value); ConsiderSnap(((Rect)(ref rect)).xMax - ((Rect)(ref predictedPanelRect)).xMin, ref bestDelta, ref bestDistance, value); } } if (!flag && bestDistance <= value) { offset.x += bestDelta; ((Rect)(ref predictedPanelRect)).x = ((Rect)(ref predictedPanelRect)).x + bestDelta; } float bestDelta2 = 0f; float bestDistance2 = value + 1f; RectTransform[] array3 = array; foreach (RectTransform target2 in array3) { if (TryGetRectInPlayerSpace(target2, out var rect2) && Range