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 HexQuickStackStorage v1.4.4
Plugins/HexQuickStackStorage.dll
Decompiled 3 weeks ago
The result has been truncated due to the large size, download it to view full contents!
using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Globalization; using System.IO; using System.IO.Compression; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Serialization; using System.Runtime.Versioning; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; using HexQuickStackStorage.Components; using HexQuickStackStorage.Services; using HexQuickStackStorage.UI; using JetBrains.Annotations; using Microsoft.CodeAnalysis; using ServerSync; using TMPro; using UnityEngine; using UnityEngine.EventSystems; using UnityEngine.Events; using UnityEngine.UI; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: AssemblyTitle("HexQuickStackStorage")] [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("")] [assembly: AssemblyProduct("HexQuickStackStorage")] [assembly: AssemblyCopyright("Copyright © 2026")] [assembly: AssemblyTrademark("")] [assembly: ComVisible(false)] [assembly: Guid("dfffd921-4f13-41b7-9dd6-fed57ea5fb5c")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")] [assembly: AssemblyVersion("1.0.0.0")] namespace HexQuickStackStorage { internal enum ContainerAccessModeEnum { CharacterOwned, Accessible } [BepInPlugin("com.hex.quickstackstorage", "HexQuickStackStorage", "1.4.4")] public class Plugin : BaseUnityPlugin { internal const string PluginGuid = "com.hex.quickstackstorage"; private const string PluginName = "HexQuickStackStorage"; private const string PluginVersion = "1.4.4"; private static readonly ConfigSync ConfigSync = new ConfigSync("com.hex.quickstackstorage") { DisplayName = "HexQuickStackStorage", CurrentVersion = "1.4.4", MinimumRequiredVersion = "1.4.4" }; private const KeyCode DefaultTrashModifierKey = (KeyCode)304; private const KeyCode DefaultFavoriteModifierKey = (KeyCode)306; private ConfigEntry<float> _searchRadius; private ConfigEntry<KeyboardShortcut> _quickStackShortcut; private ConfigEntry<KeyCode> _trashModifierKey; private ConfigEntry<KeyCode> _favoriteModifierKey; private ConfigEntry<bool> _enableChestAutoSorting; private ConfigEntry<bool> _enableAutoStoreTrophies; private ConfigEntry<ContainerAccessModeEnum> _containerAccessMode; private ConfigEntry<bool> _enableDeleteConfirmation; private ConfigEntry<bool> _lockConfiguration; private ConfigEntry<bool> _enableTrashFeature; private Harmony _harmonyInstance; private bool _isValidatingModifierKeys; private bool _modifierValidationMessagePending; internal static Plugin Instance { get; private set; } internal static ManualLogSource Log { get; private set; } internal static float SearchRadius { get { if (Instance?._searchRadius == null) { return 25f; } return Instance._searchRadius.Value; } } internal static KeyboardShortcut QuickStackShortcut { get { //IL_002a: 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) if (Instance?._quickStackShortcut == null) { return new KeyboardShortcut((KeyCode)112, Array.Empty<KeyCode>()); } return Instance._quickStackShortcut.Value; } } internal static KeyCode TrashModifierKey { get { //IL_0023: Unknown result type (might be due to invalid IL or missing references) if (Instance?._trashModifierKey == null) { return (KeyCode)304; } return Instance._trashModifierKey.Value; } } internal static KeyCode FavoriteModifierKey { get { //IL_0023: Unknown result type (might be due to invalid IL or missing references) if (Instance?._favoriteModifierKey == null) { return (KeyCode)306; } return Instance._favoriteModifierKey.Value; } } internal static bool EnableChestAutoSorting { get { if (Instance?._enableChestAutoSorting != null) { return Instance._enableChestAutoSorting.Value; } return false; } } internal static bool EnableAutoStoreTrophies { get { if (Instance?._enableAutoStoreTrophies != null) { return Instance._enableAutoStoreTrophies.Value; } return false; } } internal static ContainerAccessModeEnum ContainerAccessMode { get { if (Instance?._containerAccessMode == null) { return ContainerAccessModeEnum.CharacterOwned; } return Instance._containerAccessMode.Value; } } internal static bool EnableDeleteConfirmation { get { if (Instance?._enableDeleteConfirmation != null) { return Instance._enableDeleteConfirmation.Value; } return false; } } internal static bool EnableTrashFeature { get { if (Instance?._enableTrashFeature != null) { return Instance._enableTrashFeature.Value; } return false; } } private void Awake() { //IL_0072: Unknown result type (might be due to invalid IL or missing references) //IL_007c: Expected O, but got Unknown //IL_00aa: Unknown result type (might be due to invalid IL or missing references) //IL_022a: Unknown result type (might be due to invalid IL or missing references) //IL_0234: Expected O, but got Unknown Instance = this; Log = ((BaseUnityPlugin)this).Logger; _lockConfiguration = ((BaseUnityPlugin)this).Config.Bind<bool>("Server", "LockConfiguration", false, "Locks synchronized configuration settings to the server's values."); ConfigSync.AddLockingConfigEntry<bool>(_lockConfiguration); _searchRadius = ((BaseUnityPlugin)this).Config.Bind<float>("Chests", "SearchRadius", 25f, new ConfigDescription("The radius in which to search for nearby containers when quick stacking.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(5f, 150f), Array.Empty<object>())); ConfigSync.AddConfigEntry<float>(_searchRadius); _quickStackShortcut = ((BaseUnityPlugin)this).Config.Bind<KeyboardShortcut>("Chests", "QuickStackShortcut", new KeyboardShortcut((KeyCode)112, Array.Empty<KeyCode>()), "Keyboard shortcut used to quick stack nearby containers."); _trashModifierKey = ((BaseUnityPlugin)this).Config.Bind<KeyCode>("Inventory", "TrashModifierKey", (KeyCode)304, "Modifier key held while right-clicking an item to mark or unmark it as trash."); _favoriteModifierKey = ((BaseUnityPlugin)this).Config.Bind<KeyCode>("Inventory", "FavoriteModifierKey", (KeyCode)306, "Modifier key held while right-clicking an item to favorite or unfavorite it."); _enableChestAutoSorting = ((BaseUnityPlugin)this).Config.Bind<bool>("Chests", "EnableChestAutoSorting", false, "Automatically sort a chest when it is opened."); ConfigSync.AddConfigEntry<bool>(_enableChestAutoSorting); _enableAutoStoreTrophies = ((BaseUnityPlugin)this).Config.Bind<bool>("Chests", "EnableAutoStoreTrophies", false, "Automatically store trophies when quick stacking into containers that already contain any trophy."); ConfigSync.AddConfigEntry<bool>(_enableAutoStoreTrophies); _containerAccessMode = ((BaseUnityPlugin)this).Config.Bind<ContainerAccessModeEnum>("Chests", "ContainerAccessMode", ContainerAccessModeEnum.CharacterOwned, "Controls which containers Quick Stack can use. CharacterOwned only uses containers created by the current character. Accessible allows any public container the character can access."); ConfigSync.AddConfigEntry<ContainerAccessModeEnum>(_containerAccessMode); _enableDeleteConfirmation = ((BaseUnityPlugin)this).Config.Bind<bool>("Inventory", "EnableDeleteConfirmation", true, "Enable a confirmation dialog when deleting items marked as trash."); _enableTrashFeature = ((BaseUnityPlugin)this).Config.Bind<bool>("Inventory", "EnableTrashFeature", true, "Enable the trash feature, allowing items to be marked as trash and deleted. If disabled the trash tab on the player inventory will be removed.. Requires game restart."); _trashModifierKey.SettingChanged += OnModifierKeyChanged; _favoriteModifierKey.SettingChanged += OnModifierKeyChanged; ValidateModifierKeys(); TrashService.Initialize(); FavoriteService.Initialize(); Assembly executingAssembly = Assembly.GetExecutingAssembly(); _harmonyInstance = new Harmony("com.hex.quickstackstorage"); _harmonyInstance.PatchAll(executingAssembly); Log.LogInfo((object)"HexQuickStackStorage v1.4.4 loaded."); } private void Update() { //IL_0025: Unknown result type (might be due to invalid IL or missing references) Player localPlayer = Player.m_localPlayer; if (!((Object)(object)localPlayer == (Object)null)) { if (_modifierValidationMessagePending) { ShowModifierValidationMessage(localPlayer); } if (IsShortcutDown(_quickStackShortcut.Value) && !Console.IsVisible() && !TextInput.IsVisible() && !Menu.IsVisible() && !((Object)(object)InventoryUiController.GetCurrentContainer() != (Object)null)) { QuickStackService.QuickStack(localPlayer); } } } internal static void SetDeleteConfirmationEnabled(bool enabled) { if (Instance?._enableDeleteConfirmation != null) { Instance._enableDeleteConfirmation.Value = enabled; } } private void OnDestroy() { if (_trashModifierKey != null) { _trashModifierKey.SettingChanged -= OnModifierKeyChanged; } if (_favoriteModifierKey != null) { _favoriteModifierKey.SettingChanged -= OnModifierKeyChanged; } Harmony harmonyInstance = _harmonyInstance; if (harmonyInstance != null) { harmonyInstance.UnpatchSelf(); } ManualLogSource log = Log; if (log != null) { log.LogInfo((object)"HexQuickStackStorage v1.4.4 unloaded."); } Log = null; Instance = null; } private void OnModifierKeyChanged(object sender, EventArgs e) { ValidateModifierKeys(); } private void ValidateModifierKeys() { //IL_000f: 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_0035: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Invalid comparison between Unknown and I4 if (!_isValidatingModifierKeys && _trashModifierKey.Value == _favoriteModifierKey.Value) { _isValidatingModifierKeys = true; _favoriteModifierKey.Value = (KeyCode)(((int)_trashModifierKey.Value == 306) ? 304 : 306); _isValidatingModifierKeys = false; Player localPlayer = Player.m_localPlayer; if ((Object)(object)localPlayer == (Object)null) { _modifierValidationMessagePending = true; } else { ShowModifierValidationMessage(localPlayer); } } } private void ShowModifierValidationMessage(Player player) { ((Character)player).Message((MessageType)2, "Trash and Favorite modifier keys cannot be the same. Favorite modifier has been reset.", 0, (Sprite)null, false); _modifierValidationMessagePending = false; } private static bool IsShortcutDown(KeyboardShortcut shortcut) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Unknown result type (might be due to invalid IL or missing references) if (!ZInput.GetKeyDown(((KeyboardShortcut)(ref shortcut)).MainKey, true)) { return false; } foreach (KeyCode modifier in ((KeyboardShortcut)(ref shortcut)).Modifiers) { if (!ZInput.GetKey(modifier, true)) { return false; } } return true; } } internal static class ContainerService { private static readonly MethodInfo CheckAccessMethod = AccessTools.Method(typeof(Container), "CheckAccess", (Type[])null, (Type[])null); private static readonly FieldInfo PieceField = AccessTools.Field(typeof(Container), "m_piece"); internal static List<Container> GetNearbyContainers(Player player) { //IL_0024: Unknown result type (might be due to invalid IL or missing references) List<Container> list = new List<Container>(); if ((Object)(object)player == (Object)null || (Object)(object)Game.instance == (Object)null) { return list; } Collider[] array = Physics.OverlapSphere(((Component)player).transform.position, Plugin.SearchRadius); HashSet<Container> hashSet = new HashSet<Container>(); Collider[] array2 = array; foreach (Collider val in array2) { if (!((Object)(object)val == (Object)null)) { Container componentInParent = ((Component)val).GetComponentInParent<Container>(); if (!((Object)(object)componentInParent == (Object)null) && hashSet.Add(componentInParent) && CanUseContainer(componentInParent)) { list.Add(componentInParent); } } } return list; } internal static bool CanUseContainer(Container container) { //IL_0036: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)container == (Object)null || (Object)(object)Game.instance == (Object)null) { return false; } PlayerProfile playerProfile = Game.instance.GetPlayerProfile(); if (playerProfile == null) { return false; } if (container.m_checkGuardStone && !PrivateArea.CheckAccess(((Component)container).transform.position, 0f, true, false)) { return false; } long playerID = playerProfile.GetPlayerID(); switch (Plugin.ContainerAccessMode) { case ContainerAccessModeEnum.CharacterOwned: return WasCreatedByPlayer(container, playerID); case ContainerAccessModeEnum.Accessible: if (!IsWorldGeneratedChest(container)) { return CheckAccess(container, playerID); } return false; default: return false; } } internal static bool WasCreatedByPlayer(Container container, long playerId) { if ((Object)(object)container == (Object)null) { return false; } Piece componentInParent = ((Component)container).GetComponentInParent<Piece>(); if ((Object)(object)componentInParent == (Object)null) { return false; } return componentInParent.GetCreator() == playerId; } private static bool IsWorldGeneratedChest(Container container) { if ((Object)(object)container == (Object)null || PieceField == null) { return false; } object? value = PieceField.GetValue(container); Piece val = (Piece)((value is Piece) ? value : null); if ((Object)(object)val == (Object)null) { return false; } return !val.IsPlacedByPlayer(); } private static bool CheckAccess(Container container, long playerId) { if ((Object)(object)container == (Object)null || CheckAccessMethod == null) { return false; } return (bool)CheckAccessMethod.Invoke(container, new object[1] { playerId }); } } internal static class FavoriteService { private const string FavoriteFileName = "HexQuickStackStorage.favorites.txt"; private static readonly HashSet<string> FavoriteItemNames = new HashSet<string>(StringComparer.Ordinal); private static string FavoriteFilePath => Path.Combine(Paths.ConfigPath, "HexQuickStackStorage.favorites.txt"); internal static void Initialize() { LoadFavoriteItems(); } internal static bool IsFavorite(ItemData item) { if (item == null || item.m_shared == null) { return false; } return FavoriteItemNames.Contains(item.m_shared.m_name); } internal static void Favorite(ItemData item) { if (item != null && item.m_shared != null && FavoriteItemNames.Add(item.m_shared.m_name)) { SaveFavoriteItems(); } } internal static void Unfavorite(ItemData item) { if (item != null && item.m_shared != null && FavoriteItemNames.Remove(item.m_shared.m_name)) { SaveFavoriteItems(); } } private static void LoadFavoriteItems() { FavoriteItemNames.Clear(); if (!File.Exists(FavoriteFilePath)) { return; } string[] array = File.ReadAllLines(FavoriteFilePath); for (int i = 0; i < array.Length; i++) { string text = array[i].Trim(); if (!string.IsNullOrEmpty(text)) { FavoriteItemNames.Add(text); } } } private static void SaveFavoriteItems() { Directory.CreateDirectory(Paths.ConfigPath); List<string> list = new List<string>(FavoriteItemNames); list.Sort(StringComparer.Ordinal); File.WriteAllLines(FavoriteFilePath, list); } } internal static class InventorySortService { internal static void SortPlayerInventory() { Player localPlayer = Player.m_localPlayer; if (!((Object)(object)localPlayer == (Object)null)) { Inventory inventory = ((Humanoid)localPlayer).GetInventory(); if (inventory != null) { int vanillaInventoryHeight = GetVanillaInventoryHeight(localPlayer); Sort(inventory, vanillaInventoryHeight, isPlayerInventory: true); } } } internal static void SortContainer(Container container) { if (!((Object)(object)container == (Object)null)) { Inventory inventory = container.GetInventory(); if (inventory != null) { Sort(inventory, inventory.GetHeight(), isPlayerInventory: false); } } } private static void Sort(Inventory inventory, int validHeight, bool isPlayerInventory) { //IL_0061: Unknown result type (might be due to invalid IL or missing references) //IL_0184: Unknown result type (might be due to invalid IL or missing references) //IL_0189: Unknown result type (might be due to invalid IL or missing references) List<ItemData> allItems = inventory.GetAllItems(); if (allItems == null || allItems.Count <= 1) { return; } int width = inventory.GetWidth(); if (width <= 0 || validHeight <= 0) { return; } List<ItemData> list = new List<ItemData>(allItems.Count); HashSet<(int, int)> hashSet = new HashSet<(int, int)>(); foreach (ItemData item in allItems) { if (item != null && item.m_shared != null && IsPositionWithinBounds(item.m_gridPos, width, validHeight)) { if (isPlayerInventory && item.m_equipped) { hashSet.Add((item.m_gridPos.x, item.m_gridPos.y)); } else if (isPlayerInventory && ItemStateService.IsHotbarItem(item)) { hashSet.Add((item.m_gridPos.x, item.m_gridPos.y)); } else if (isPlayerInventory && FavoriteService.IsFavorite(item)) { hashSet.Add((item.m_gridPos.x, item.m_gridPos.y)); } else { list.Add(item); } } } list.Sort(CompareItems); ConsolidateStacks(inventory, list); list.Sort(CompareItems); int num = 0; for (int i = (isPlayerInventory ? 1 : 0); i < validHeight; i++) { if (num >= list.Count) { break; } for (int j = 0; j < width; j++) { if (num >= list.Count) { break; } if (!hashSet.Contains((j, i))) { list[num].m_gridPos = new Vector2i(j, i); num++; } } } InventoryOperationsService.NotifyChanged(inventory); } private static void ConsolidateStacks(Inventory inventory, List<ItemData> items) { for (int i = 0; i < items.Count; i++) { ItemData val = items[i]; if (val == null || val.m_shared == null || val.m_shared.m_maxStackSize <= 1) { continue; } int num = i + 1; while (num < items.Count) { ItemData val2 = items[num]; if (!CanStackTogether(val, val2)) { num++; continue; } int num2 = val.m_shared.m_maxStackSize - val.m_stack; if (num2 <= 0) { break; } int num3 = Math.Min(num2, val2.m_stack); val.m_stack += num3; val2.m_stack -= num3; if (val2.m_stack <= 0) { inventory.RemoveItem(val2); items.RemoveAt(num); } else { num++; } } } } private static bool CanStackTogether(ItemData targetItem, ItemData sourceItem) { if (targetItem == null || sourceItem == null || targetItem.m_shared == null || sourceItem.m_shared == null) { return false; } if (targetItem == sourceItem) { return false; } if (targetItem.m_shared.m_name != sourceItem.m_shared.m_name) { return false; } if (targetItem.m_quality != sourceItem.m_quality) { return false; } if (targetItem.m_worldLevel != sourceItem.m_worldLevel) { return false; } return targetItem.m_stack < targetItem.m_shared.m_maxStackSize; } private static int GetVanillaInventoryHeight(Player player) { string s = default(string); if (player.TryGetUniqueKeyValue("invrows", ref s) && int.TryParse(s, out var result)) { return Mathf.Clamp(result, 0, 9); } return 4; } private static bool IsPositionWithinBounds(Vector2i position, int width, int height) { //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_0012: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Unknown result type (might be due to invalid IL or missing references) if (position.x >= 0 && position.x < width && position.y >= 0) { return position.y < height; } return false; } private static int CompareItems(ItemData firstItem, ItemData secondItem) { //IL_0011: Unknown result type (might be due to invalid IL or missing references) ref ItemType itemType = ref firstItem.m_shared.m_itemType; object target = secondItem.m_shared.m_itemType; int num = ((Enum)Unsafe.As<ItemType, ItemType>(ref itemType)/*cast due to .constrained prefix*/).CompareTo(target); if (num != 0) { return num; } num = string.Compare(firstItem.m_shared.m_name, secondItem.m_shared.m_name, StringComparison.Ordinal); if (num != 0) { return num; } num = secondItem.m_quality.CompareTo(firstItem.m_quality); if (num != 0) { return num; } return secondItem.m_stack.CompareTo(firstItem.m_stack); } } internal static class ItemStateService { internal static void ToggleFavorite(Player player, ItemData item) { if (!((Object)(object)player == (Object)null) && item != null && item.m_shared != null) { if (FavoriteService.IsFavorite(item)) { FavoriteService.Unfavorite(item); return; } TrashService.Unmark(item); FavoriteService.Favorite(item); } } internal static void ToggleTrash(Player player, ItemData item) { if (!((Object)(object)player == (Object)null) && item != null && item.m_shared != null && TrashService.IsVanillaInventoryItem(player, item)) { if (IsHotbarItem(item)) { ((Character)player).Message((MessageType)2, "Hotbar items cannot be marked as trash.", 0, (Sprite)null, false); return; } if (item.m_equipped) { ((Character)player).Message((MessageType)2, "Equipped items cannot be marked as trash.", 0, (Sprite)null, false); return; } if (TrashService.IsMarked(item)) { TrashService.Unmark(item); return; } FavoriteService.Unfavorite(item); TrashService.Mark(item); } } internal static bool CanDelete(ItemData item) { if (item == null) { return false; } if (item.m_equipped) { return false; } if (IsHotbarItem(item)) { return false; } if (FavoriteService.IsFavorite(item)) { return false; } return true; } internal static bool IsHotbarItem(ItemData item) { if (item != null) { return item.m_gridPos.y == 0; } return false; } } internal static class QuickStackService { private const int DefaultVanillaInventoryRows = 4; private static readonly FieldInfo ContainerNViewField = typeof(Container).GetField("m_nview", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); internal static void QuickStack(Player player) { if ((Object)(object)player == (Object)null) { return; } Inventory inventory = ((Humanoid)player).GetInventory(); if (inventory == null) { return; } int vanillaInventoryHeight = GetVanillaInventoryHeight(player); List<ItemData> quickStackableItems = GetQuickStackableItems(player, inventory, vanillaInventoryHeight); if (quickStackableItems.Count == 0) { return; } List<Container> nearbyContainers = ContainerService.GetNearbyContainers(player); bool flag = false; foreach (Container item in nearbyContainers) { if (QuickStackIntoContainer(item, quickStackableItems, inventory, allowInUse: false)) { flag = true; } if (quickStackableItems.Count == 0) { break; } } if (flag) { ((Character)player).Message((MessageType)1, "Items auto stacked", 0, (Sprite)null, false); } } internal static void QuickStack(Player player, Container container) { if ((Object)(object)player == (Object)null || (Object)(object)container == (Object)null) { return; } Inventory inventory = ((Humanoid)player).GetInventory(); if (inventory != null) { int vanillaInventoryHeight = GetVanillaInventoryHeight(player); List<ItemData> quickStackableItems = GetQuickStackableItems(player, inventory, vanillaInventoryHeight); if (quickStackableItems.Count != 0 && QuickStackIntoContainer(container, quickStackableItems, inventory, allowInUse: true)) { ((Character)player).Message((MessageType)1, "Items auto stacked", 0, (Sprite)null, false); } } } private static bool QuickStackIntoContainer(Container container, List<ItemData> quickStackableItems, Inventory playerInventory, bool allowInUse) { if ((Object)(object)container == (Object)null) { return false; } ZNetView containerNView = GetContainerNView(container); if ((Object)(object)containerNView == (Object)null || !containerNView.IsValid()) { return false; } if (!allowInUse && IsContainerInUse(container, containerNView)) { return false; } containerNView.ClaimOwnership(); Inventory inventory = container.GetInventory(); if (inventory == null) { return false; } bool flag = !allowInUse; if (flag) { SetContainerInUse(containerNView, isInUse: true); } try { return QuickStackItems(quickStackableItems, playerInventory, inventory); } finally { if (flag) { SetContainerInUse(containerNView, isInUse: false); } } } private static List<ItemData> GetQuickStackableItems(Player player, Inventory playerInventory, int vanillaHeight) { List<ItemData> list = new List<ItemData>(); foreach (ItemData allItem in playerInventory.GetAllItems()) { if (allItem != null && allItem.m_gridPos.y >= 0 && allItem.m_gridPos.y < vanillaHeight && !ItemStateService.IsHotbarItem(allItem) && !((Humanoid)player).IsItemEquiped(allItem) && !FavoriteService.IsFavorite(allItem) && (!IsTrophy(allItem) || Plugin.EnableAutoStoreTrophies)) { list.Add(allItem); } } return list; } private static bool QuickStackItems(List<ItemData> quickStackableItems, Inventory playerInventory, Inventory containerInventory) { //IL_00cc: Unknown result type (might be due to invalid IL or missing references) //IL_00d1: Unknown result type (might be due to invalid IL or missing references) //IL_00d3: 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_010a: Unknown result type (might be due to invalid IL or missing references) bool flag = false; for (int num = quickStackableItems.Count - 1; num >= 0; num--) { ItemData val = quickStackableItems[num]; if (val == null) { quickStackableItems.RemoveAt(num); } else { bool num2 = IsTrophy(val); bool flag2 = containerInventory.ContainsItemByName(val.m_shared.m_name); bool flag3 = num2 && containerInventory.GetAllItems().Exists(IsTrophy); if (flag2 || flag3) { while (val.m_stack > 0) { ItemData val2 = InventoryOperationsService.FindFreeStackItem(containerInventory, val); if (val2 == null) { break; } int num3 = val2.m_shared.m_maxStackSize - val2.m_stack; int num4 = Mathf.Min(val.m_stack, num3); val2.m_stack += num4; val.m_stack -= num4; flag = true; } while (val.m_stack > 0) { Vector2i val3 = InventoryOperationsService.FindEmptySlot(containerInventory, val); if (val3.x < 0) { break; } int num5 = Mathf.Min(val.m_stack, val.m_shared.m_maxStackSize); ItemData val4 = val.Clone(); val4.m_stack = num5; val4.m_gridPos = val3; containerInventory.GetAllItems().Add(val4); val.m_stack -= num5; flag = true; } if (val.m_stack == 0) { playerInventory.RemoveItem(val); quickStackableItems.RemoveAt(num); } } } } if (flag) { InventoryOperationsService.NotifyChanged(playerInventory); InventoryOperationsService.NotifyChanged(containerInventory); } return flag; } private static ZNetView GetContainerNView(Container container) { if ((Object)(object)container == (Object)null || ContainerNViewField == null) { return null; } object? value = ContainerNViewField.GetValue(container); return (ZNetView)((value is ZNetView) ? value : null); } private static bool IsContainerInUse(Container container, ZNetView nview) { if (container.IsInUse() || ((Object)(object)container.m_wagon != (Object)null && container.m_wagon.InUse())) { return true; } ZDO zDO = nview.GetZDO(); if (zDO == null) { return false; } return zDO.GetInt(ZDOVars.s_inUse, 0) == 1; } private static void SetContainerInUse(ZNetView nview, bool isInUse) { //IL_0026: Unknown result type (might be due to invalid IL or missing references) ZDO zDO = nview.GetZDO(); if (zDO != null) { zDO.Set(ZDOVars.s_inUse, isInUse ? 1 : 0, false); ZDOMan.instance.ForceSendZDO(ZNet.GetUID(), zDO.m_uid); } } private static int GetVanillaInventoryHeight(Player player) { string s = default(string); if (player.TryGetUniqueKeyValue("invrows", ref s) && int.TryParse(s, out var result)) { return Mathf.Clamp(result, 0, 9); } return 4; } private static bool IsTrophy(ItemData item) { //IL_001a: 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_002e: Invalid comparison between Unknown and I4 if (item == null) { return false; } return (int)(item.m_shared?.m_itemType).GetValueOrDefault() == 13; } } internal static class TrashService { private const string JunkFileName = "HexQuickStackStorage.junk.txt"; private static readonly HashSet<string> JunkItemNames = new HashSet<string>(StringComparer.Ordinal); private static readonly FieldInfo DragItemField = AccessTools.Field(typeof(InventoryGui), "m_dragItem"); private static readonly FieldInfo DragInventoryField = AccessTools.Field(typeof(InventoryGui), "m_dragInventory"); private static readonly FieldInfo DragAmountField = AccessTools.Field(typeof(InventoryGui), "m_dragAmount"); private static readonly MethodInfo SetupDragItemMethod = AccessTools.Method(typeof(InventoryGui), "SetupDragItem", (Type[])null, (Type[])null); private static string JunkFilePath => Path.Combine(Paths.ConfigPath, "HexQuickStackStorage.junk.txt"); internal static void Initialize() { LoadJunkItems(); } internal static bool IsMarked(ItemData item) { if (item == null || item.m_shared == null) { return false; } return JunkItemNames.Contains(item.m_shared.m_name); } internal static void Mark(ItemData item) { if (item != null && item.m_shared != null && JunkItemNames.Add(item.m_shared.m_name)) { SaveJunkItems(); } } internal static void Unmark(ItemData item) { if (item != null && item.m_shared != null && JunkItemNames.Remove(item.m_shared.m_name)) { SaveJunkItems(); } } internal static void DeleteDraggedItem(InventoryGui inventoryGui, Player player) { if ((Object)(object)inventoryGui == (Object)null || (Object)(object)player == (Object)null) { return; } object? obj = DragItemField?.GetValue(inventoryGui); ItemData val = (ItemData)((obj is ItemData) ? obj : null); object? obj2 = DragInventoryField?.GetValue(inventoryGui); Inventory val2 = (Inventory)((obj2 is Inventory) ? obj2 : null); if (val == null || val2 == null) { return; } Inventory inventory = ((Humanoid)player).GetInventory(); if (val2 != inventory || !IsVanillaInventoryItem(player, val)) { return; } if (!ItemStateService.CanDelete(val)) { ShowProtectedItemMessage(player); return; } int num = Mathf.Min((!(DragAmountField != null)) ? 1 : ((int)DragAmountField.GetValue(inventoryGui)), val.m_stack); if (val2.RemoveItem(val, num)) { SetupDragItemMethod?.Invoke(inventoryGui, new object[3] { null, null, 1 }); ShowItemsDeletedMessage(player); } } internal static void DeleteMarkedItems(Player player) { if ((Object)(object)player == (Object)null) { return; } Inventory inventory = ((Humanoid)player).GetInventory(); if (inventory == null) { return; } List<ItemData> list = new List<ItemData>(inventory.GetAllItems()); bool flag = false; bool flag2 = false; foreach (ItemData item in list) { if (item != null && item.m_shared != null && IsMarked(item) && IsVanillaInventoryItem(player, item)) { if (!ItemStateService.CanDelete(item)) { flag = true; } else if (inventory.RemoveItem(item)) { flag2 = true; } } } if (flag) { ShowProtectedItemMessage(player); } if (flag2) { ShowItemsDeletedMessage(player); } } internal static bool IsVanillaInventoryItem(Player player, ItemData item) { if ((Object)(object)player == (Object)null || item == null) { return false; } int vanillaInventoryHeight = GetVanillaInventoryHeight(player); if (item.m_gridPos.y >= 0) { return item.m_gridPos.y < vanillaInventoryHeight; } return false; } private static int GetVanillaInventoryHeight(Player player) { string s = default(string); if (player.TryGetUniqueKeyValue("invrows", ref s) && int.TryParse(s, out var result)) { return Mathf.Clamp(result, 0, 9); } return 4; } private static void LoadJunkItems() { JunkItemNames.Clear(); if (!File.Exists(JunkFilePath)) { return; } string[] array = File.ReadAllLines(JunkFilePath); for (int i = 0; i < array.Length; i++) { string text = array[i].Trim(); if (!string.IsNullOrEmpty(text)) { JunkItemNames.Add(text); } } } private static void SaveJunkItems() { Directory.CreateDirectory(Paths.ConfigPath); List<string> list = new List<string>(JunkItemNames); list.Sort(StringComparer.Ordinal); File.WriteAllLines(JunkFilePath, list); } private static void ShowItemsDeletedMessage(Player player) { ((Character)player).Message((MessageType)2, "Items Deleted", 0, (Sprite)null, false); } private static void ShowProtectedItemMessage(Player player) { ((Character)player).Message((MessageType)2, "Can't delete equipped, hotbar, or favorited items.", 0, (Sprite)null, false); } } } namespace HexQuickStackStorage.Components { internal sealed class QuickStackTooltipComponent : MonoBehaviour, IPointerEnterHandler, IEventSystemHandler, IPointerExitHandler { private const string TooltipText = "Quick Stack is unavailable while a container is open."; private GameObject _tooltipObject; private bool _tooltipEnabled; internal bool TooltipEnabled { get { return _tooltipEnabled; } set { _tooltipEnabled = value; if (!_tooltipEnabled) { HideTooltip(); } } } public void OnPointerEnter(PointerEventData eventData) { if (TooltipEnabled) { ShowTooltip(); } } public void OnPointerExit(PointerEventData eventData) { HideTooltip(); } private void ShowTooltip() { //IL_0041: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Expected O, but got Unknown //IL_0076: Unknown result type (might be due to invalid IL or missing references) //IL_0086: Unknown result type (might be due to invalid IL or missing references) //IL_009a: Unknown result type (might be due to invalid IL or missing references) //IL_009f: Unknown result type (might be due to invalid IL or missing references) //IL_00c4: Unknown result type (might be due to invalid IL or missing references) //IL_0116: Unknown result type (might be due to invalid IL or missing references) //IL_0121: Unknown result type (might be due to invalid IL or missing references) //IL_0136: Unknown result type (might be due to invalid IL or missing references) //IL_014b: Unknown result type (might be due to invalid IL or missing references) //IL_0155: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)_tooltipObject != (Object)null)) { GameObject val = new GameObject("com.hex.quickstackstorage.QuickStackTooltip", new Type[3] { typeof(RectTransform), typeof(CanvasRenderer), typeof(Image) }); val.transform.SetParent(((Component)this).transform.parent, false); _tooltipObject = val; RectTransform component = val.GetComponent<RectTransform>(); component.sizeDelta = new Vector2(360f, 40f); ((Transform)component).position = ((Component)this).transform.position + new Vector3(0f, 45f, 0f); Image component2 = val.GetComponent<Image>(); ((Graphic)component2).color = new Color(0f, 0f, 0f, 0.9f); ((Graphic)component2).raycastTarget = false; TMP_Text componentInChildren = ((Component)this).GetComponentInChildren<TMP_Text>(true); if ((Object)(object)componentInChildren == (Object)null) { Object.Destroy((Object)(object)val); _tooltipObject = null; return; } GameObject obj = Object.Instantiate<GameObject>(((Component)componentInChildren).gameObject, val.transform); ((Object)obj).name = "com.hex.quickstackstorage.QuickStackTooltip.Text"; RectTransform component3 = obj.GetComponent<RectTransform>(); component3.anchorMin = Vector2.zero; component3.anchorMax = Vector2.one; component3.offsetMin = new Vector2(8f, 4f); component3.offsetMax = new Vector2(-8f, -4f); ((Transform)component3).localScale = Vector3.one; TMP_Text component4 = obj.GetComponent<TMP_Text>(); component4.text = "Quick Stack is unavailable while a container is open."; component4.fontSize = 16f; component4.fontStyle = (FontStyles)0; component4.alignment = (TextAlignmentOptions)514; ((Graphic)component4).raycastTarget = false; component4.text = "Quick Stack is unavailable while a container is open."; component4.fontSize = 16f; component4.fontStyle = (FontStyles)0; component4.alignment = (TextAlignmentOptions)514; ((Graphic)component4).raycastTarget = false; } } private void HideTooltip() { if (!((Object)(object)_tooltipObject == (Object)null)) { Object.Destroy((Object)(object)_tooltipObject); _tooltipObject = null; } } private void OnDisable() { HideTooltip(); } } } namespace HexQuickStackStorage.UI { internal class DialogDragHandler : MonoBehaviour, IBeginDragHandler, IEventSystemHandler, IDragHandler { private RectTransform _target; private Vector2 _pointerOffset; internal void Initialize(RectTransform target) { _target = target; } public void OnBeginDrag(PointerEventData eventData) { //IL_002c: 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_004d: Unknown result type (might be due to invalid IL or missing references) //IL_004e: Unknown result type (might be due to invalid IL or missing references) //IL_0053: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)_target == (Object)null)) { Transform parent = ((Transform)_target).parent; RectTransform val = (RectTransform)(object)((parent is RectTransform) ? parent : null); Vector2 val2 = default(Vector2); if (!((Object)(object)val == (Object)null) && RectTransformUtility.ScreenPointToLocalPointInRectangle(val, eventData.position, eventData.pressEventCamera, ref val2)) { _pointerOffset = _target.anchoredPosition - val2; } } } public void OnDrag(PointerEventData eventData) { //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Unknown result type (might be due to invalid IL or missing references) //IL_0049: Unknown result type (might be due to invalid IL or missing references) //IL_004e: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)_target == (Object)null)) { Transform parent = ((Transform)_target).parent; RectTransform val = (RectTransform)(object)((parent is RectTransform) ? parent : null); Vector2 val2 = default(Vector2); if (!((Object)(object)val == (Object)null) && RectTransformUtility.ScreenPointToLocalPointInRectangle(val, eventData.position, eventData.pressEventCamera, ref val2)) { _target.anchoredPosition = val2 + _pointerOffset; } } } } internal static class DialogUiController { private static GameObject _deleteConfirmationDialog; private static Toggle _dontShowAgainToggle; internal static void ShowDeleteConfirmation(InventoryGui inventoryGui, UnityAction onConfirm) { if ((Object)(object)inventoryGui == (Object)null) { Plugin.Log.LogWarning((object)"InventoryGui is null. Unable to show delete confirmation."); return; } if ((Object)(object)Menu.instance == (Object)null || (Object)(object)Menu.instance.m_logoutDialog == (Object)null) { Plugin.Log.LogWarning((object)"Could not find Valheim logout confirmation dialog."); return; } if ((Object)(object)_deleteConfirmationDialog == (Object)null) { _deleteConfirmationDialog = Object.Instantiate<GameObject>(((Component)Menu.instance.m_logoutDialog).gameObject, ((Component)inventoryGui).transform); ((Object)_deleteConfirmationDialog).name = "com.hex.quickstackstorage.DeleteConfirmation"; ConfigureDeleteConfirmationDialog(); } if ((Object)(object)_dontShowAgainToggle != (Object)null) { _dontShowAgainToggle.isOn = false; } ConfigureDeleteConfirmationActions(onConfirm); _deleteConfirmationDialog.SetActive(true); _deleteConfirmationDialog.transform.SetAsLastSibling(); } private static void ConfigureDeleteConfirmationDialog() { //IL_00a2: Unknown result type (might be due to invalid IL or missing references) //IL_00ac: Expected O, but got Unknown //IL_00b6: Unknown result type (might be due to invalid IL or missing references) //IL_00c0: Expected O, but got Unknown if ((Object)(object)_deleteConfirmationDialog == (Object)null) { return; } Transform val = _deleteConfirmationDialog.transform.Find("dialog"); if ((Object)(object)val == (Object)null) { Plugin.Log.LogWarning((object)"Could not find dialog on delete confirmation."); return; } Transform obj = val.Find("Quit"); TMP_Text val2 = ((obj != null) ? ((Component)obj).GetComponent<TMP_Text>() : null); Transform obj2 = val.Find("Button_yes"); Button val3 = ((obj2 != null) ? ((Component)obj2).GetComponent<Button>() : null); Transform obj3 = val.Find("Button_no"); Button val4 = ((obj3 != null) ? ((Component)obj3).GetComponent<Button>() : null); if ((Object)(object)val2 != (Object)null) { val2.text = "Delete items?"; } if ((Object)(object)val3 != (Object)null) { val3.onClick = new ButtonClickedEvent(); } if ((Object)(object)val4 != (Object)null) { val4.onClick = new ButtonClickedEvent(); SetButtonText(((Component)val4).gameObject, "Cancel"); } RectTransform val5 = (RectTransform)(object)((val is RectTransform) ? val : null); if ((Object)(object)val5 != (Object)null) { DialogDragHandler dialogDragHandler = ((Component)val).gameObject.GetComponent<DialogDragHandler>(); if ((Object)(object)dialogDragHandler == (Object)null) { dialogDragHandler = ((Component)val).gameObject.AddComponent<DialogDragHandler>(); } dialogDragHandler.Initialize(val5); } CreateDontShowAgainToggle(val, val2, val3, val4); } private static void ConfigureDeleteConfirmationActions(UnityAction onConfirm) { //IL_0066: Unknown result type (might be due to invalid IL or missing references) //IL_0070: Expected O, but got Unknown //IL_007d: Unknown result type (might be due to invalid IL or missing references) //IL_0087: Expected O, but got Unknown //IL_0091: Unknown result type (might be due to invalid IL or missing references) //IL_009b: Expected O, but got Unknown //IL_00a8: Unknown result type (might be due to invalid IL or missing references) //IL_00b2: Expected O, but got Unknown Transform val = _deleteConfirmationDialog.transform.Find("dialog"); if ((Object)(object)val == (Object)null) { return; } Transform obj = val.Find("Button_yes"); Button val2 = ((obj != null) ? ((Component)obj).GetComponent<Button>() : null); Transform obj2 = val.Find("Button_no"); Button val3 = ((obj2 != null) ? ((Component)obj2).GetComponent<Button>() : null); if ((Object)(object)val2 != (Object)null) { val2.onClick = new ButtonClickedEvent(); ((UnityEvent)val2.onClick).AddListener((UnityAction)delegate { if ((Object)(object)_dontShowAgainToggle != (Object)null && _dontShowAgainToggle.isOn) { Plugin.SetDeleteConfirmationEnabled(enabled: false); } HideDeleteConfirmation(); UnityAction obj3 = onConfirm; if (obj3 != null) { obj3.Invoke(); } }); } if ((Object)(object)val3 != (Object)null) { val3.onClick = new ButtonClickedEvent(); ((UnityEvent)val3.onClick).AddListener(new UnityAction(HideDeleteConfirmation)); } } private static void HideDeleteConfirmation() { if ((Object)(object)_deleteConfirmationDialog != (Object)null) { _deleteConfirmationDialog.SetActive(false); } } private static void SetButtonText(GameObject buttonObject, string text) { TMP_Text componentInChildren = buttonObject.GetComponentInChildren<TMP_Text>(true); if ((Object)(object)componentInChildren != (Object)null) { componentInChildren.text = text; componentInChildren.alignment = (TextAlignmentOptions)514; return; } Text componentInChildren2 = buttonObject.GetComponentInChildren<Text>(true); if ((Object)(object)componentInChildren2 != (Object)null) { componentInChildren2.text = text; componentInChildren2.alignment = (TextAnchor)4; } } private static void CreateDontShowAgainToggle(Transform dialog, TMP_Text textTemplate, Button yesButton, Button cancelButton) { //IL_004c: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Expected O, but got Unknown //IL_0070: Unknown result type (might be due to invalid IL or missing references) //IL_0085: Unknown result type (might be due to invalid IL or missing references) //IL_009a: Unknown result type (might be due to invalid IL or missing references) //IL_00af: Unknown result type (might be due to invalid IL or missing references) //IL_0155: Unknown result type (might be due to invalid IL or missing references) //IL_019a: Unknown result type (might be due to invalid IL or missing references) //IL_01a0: Expected O, but got Unknown //IL_01c3: Unknown result type (might be due to invalid IL or missing references) //IL_01d8: Unknown result type (might be due to invalid IL or missing references) //IL_01ed: Unknown result type (might be due to invalid IL or missing references) //IL_01f8: Unknown result type (might be due to invalid IL or missing references) //IL_020c: Unknown result type (might be due to invalid IL or missing references) //IL_0232: Unknown result type (might be due to invalid IL or missing references) //IL_0261: Unknown result type (might be due to invalid IL or missing references) //IL_0266: Unknown result type (might be due to invalid IL or missing references) //IL_0278: Unknown result type (might be due to invalid IL or missing references) //IL_027f: Unknown result type (might be due to invalid IL or missing references) //IL_028a: 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_02b3: Unknown result type (might be due to invalid IL or missing references) //IL_02c6: Unknown result type (might be due to invalid IL or missing references) //IL_00e1: 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_00f2: Unknown result type (might be due to invalid IL or missing references) //IL_0317: Unknown result type (might be due to invalid IL or missing references) //IL_0323: Unknown result type (might be due to invalid IL or missing references) //IL_0339: Unknown result type (might be due to invalid IL or missing references) //IL_0345: Unknown result type (might be due to invalid IL or missing references) //IL_035b: Unknown result type (might be due to invalid IL or missing references) //IL_0367: Unknown result type (might be due to invalid IL or missing references) //IL_0373: 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_0133: Unknown result type (might be due to invalid IL or missing references) //IL_0138: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_dontShowAgainToggle != (Object)null) { return; } if ((Object)(object)textTemplate == (Object)null) { Plugin.Log.LogWarning((object)"Could not find Valheim text template for delete confirmation toggle."); return; } GameObject val = new GameObject("com.hex.quickstackstorage.DontShowAgainToggle", new Type[2] { typeof(RectTransform), typeof(Toggle) }); val.transform.SetParent(dialog, false); RectTransform component = val.GetComponent<RectTransform>(); component.anchorMin = new Vector2(0.5f, 0.5f); component.anchorMax = new Vector2(0.5f, 0.5f); component.pivot = new Vector2(0.5f, 0.5f); component.sizeDelta = new Vector2(290f, 30f); float num = -80f; Rect rect; if ((Object)(object)yesButton != (Object)null) { Transform transform = ((Component)yesButton).transform; RectTransform val2 = (RectTransform)(object)((transform is RectTransform) ? transform : null); if ((Object)(object)val2 != (Object)null) { float y = val2.anchoredPosition.y; rect = val2.rect; num = y - ((Rect)(ref rect)).height * 0.5f; } } else if ((Object)(object)cancelButton != (Object)null) { Transform transform2 = ((Component)cancelButton).transform; RectTransform val3 = (RectTransform)(object)((transform2 is RectTransform) ? transform2 : null); if ((Object)(object)val3 != (Object)null) { float y2 = val3.anchoredPosition.y; rect = val3.rect; num = y2 - ((Rect)(ref rect)).height * 0.5f; } } component.anchoredPosition = new Vector2(0f, num - 25f); _dontShowAgainToggle = val.GetComponent<Toggle>(); _dontShowAgainToggle.isOn = false; GameObject val4 = new GameObject("com.hex.quickstackstorage.DontShowAgainToggle.CheckboxBackground", new Type[2] { typeof(RectTransform), typeof(Image) }); val4.transform.SetParent(val.transform, false); RectTransform component2 = val4.GetComponent<RectTransform>(); component2.anchorMin = new Vector2(0f, 0.5f); component2.anchorMax = new Vector2(0f, 0.5f); component2.pivot = new Vector2(0f, 0.5f); component2.anchoredPosition = Vector2.zero; component2.sizeDelta = new Vector2(20f, 20f); Image component3 = val4.GetComponent<Image>(); ((Graphic)component3).color = new Color(0.15f, 0.15f, 0.15f, 1f); GameObject val5 = new GameObject("com.hex.quickstackstorage.DontShowAgainToggle.Checkmark", new Type[2] { typeof(RectTransform), typeof(Image) }); val5.transform.SetParent(val4.transform, false); RectTransform component4 = val5.GetComponent<RectTransform>(); component4.anchorMin = Vector2.zero; component4.anchorMax = Vector2.one; component4.offsetMin = new Vector2(4f, 4f); component4.offsetMax = new Vector2(-4f, -4f); Image component5 = val5.GetComponent<Image>(); ((Graphic)component5).color = Color.white; ((Selectable)_dontShowAgainToggle).targetGraphic = (Graphic)(object)component3; _dontShowAgainToggle.graphic = (Graphic)(object)component5; GameObject obj = Object.Instantiate<GameObject>(((Component)textTemplate).gameObject, val.transform); ((Object)obj).name = "com.hex.quickstackstorage.DontShowAgainToggle.Label"; RectTransform component6 = obj.GetComponent<RectTransform>(); if ((Object)(object)component6 != (Object)null) { component6.anchorMin = Vector2.zero; component6.anchorMax = Vector2.one; component6.pivot = new Vector2(0.5f, 0.5f); component6.anchoredPosition = Vector2.zero; component6.offsetMin = new Vector2(30f, 0f); component6.offsetMax = Vector2.zero; ((Transform)component6).localScale = Vector3.one; } TMP_Text component7 = obj.GetComponent<TMP_Text>(); if ((Object)(object)component7 != (Object)null) { component7.text = "Don't show this confirmation again."; component7.fontSize = 16f; component7.fontStyle = (FontStyles)0; component7.alignment = (TextAlignmentOptions)4097; ((Graphic)component7).raycastTarget = false; } } } internal static class InventoryUiController { private const string SortButtonName = "com.hex.quickstackstorage.SortButton"; private const string QuickStackButtonName = "com.hex.quickstackstorage.QuickStackButton"; private const string ContainerSortButtonName = "com.hex.quickstackstorage.ContainerSortButton"; private const string TrashButtonName = "com.hex.quickstackstorage.TrashButton"; private const float ButtonSize = 36f; private const float ButtonSpacing = 4f; private const float TrashIconSize = 32f; private const float TrashIconXOffset = 4f; private const float TrashIconYOffset = 0f; private static readonly FieldInfo CurrentContainerField = AccessTools.Field(typeof(InventoryGui), "m_currentContainer"); private static readonly FieldInfo DragItemField = AccessTools.Field(typeof(InventoryGui), "m_dragItem"); private static InventoryGui _inventoryGui; private static Button _quickStackButton; private static QuickStackTooltipComponent _quickStackTooltip; internal static void Initialize(InventoryGui inventoryGui) { if (!((Object)(object)inventoryGui == (Object)null)) { _inventoryGui = inventoryGui; CreateButtons(); } } internal static Container GetCurrentContainer() { if ((Object)(object)_inventoryGui == (Object)null) { return null; } object? obj = CurrentContainerField?.GetValue(_inventoryGui); return (Container)((obj is Container) ? obj : null); } internal static void SetContainerSortButtonVisible(bool visible) { if ((Object)(object)_inventoryGui == (Object)null || (Object)(object)_inventoryGui.m_stackAllButton == (Object)null) { return; } Transform parent = ((Component)_inventoryGui.m_stackAllButton).transform.parent; if (!((Object)(object)parent == (Object)null)) { Transform val = parent.Find("com.hex.quickstackstorage.ContainerSortButton"); if ((Object)(object)val != (Object)null) { ((Component)val).gameObject.SetActive(visible); } } } internal static void SetQuickStackButtonInteractable(bool interactable) { if ((Object)(object)_quickStackButton != (Object)null) { ((Selectable)_quickStackButton).interactable = interactable; } if ((Object)(object)_quickStackTooltip != (Object)null) { _quickStackTooltip.TooltipEnabled = !interactable; } } private static void CreateButtons() { //IL_004f: Unknown result type (might be due to invalid IL or missing references) //IL_0059: Expected O, but got Unknown //IL_006c: Unknown result type (might be due to invalid IL or missing references) //IL_0076: Expected O, but got Unknown //IL_00cc: Unknown result type (might be due to invalid IL or missing references) //IL_00d6: Expected O, but got Unknown if ((Object)(object)_inventoryGui == (Object)null || (Object)(object)_inventoryGui.m_player == (Object)null || (Object)(object)_inventoryGui.m_takeAllButton == (Object)null) { return; } Button takeAllButton = _inventoryGui.m_takeAllButton; CreateActionButton(takeAllButton, "com.hex.quickstackstorage.SortButton", "S", 0, new UnityAction(OnSortClicked)); _quickStackButton = CreateActionButton(takeAllButton, "com.hex.quickstackstorage.QuickStackButton", "Q", 1, new UnityAction(OnQuickStackClicked)); if ((Object)(object)_quickStackButton != (Object)null) { _quickStackTooltip = ((Component)_quickStackButton).GetComponent<QuickStackTooltipComponent>(); if ((Object)(object)_quickStackTooltip == (Object)null) { _quickStackTooltip = ((Component)_quickStackButton).gameObject.AddComponent<QuickStackTooltipComponent>(); } } CreateContainerSortButton(); if (Plugin.EnableTrashFeature) { CreateTrashButton(new UnityAction(OnTrashClicked)); } } private static Button CreateActionButton(Button template, string buttonName, string text, int index, UnityAction onClick) { Transform val = ((Component)_inventoryGui.m_player).transform.Find(buttonName); if ((Object)(object)val != (Object)null) { return ((Component)val).GetComponent<Button>(); } GameObject val2 = Object.Instantiate<GameObject>(((Component)template).gameObject, ((Component)_inventoryGui.m_player).transform); ((Object)val2).name = buttonName; Button component = val2.GetComponent<Button>(); if ((Object)(object)component == (Object)null) { Object.Destroy((Object)(object)val2); return null; } ((UnityEventBase)component.onClick).RemoveAllListeners(); ((UnityEvent)component.onClick).AddListener(onClick); SetButtonText(val2, text); StyleActionButton(val2); PositionActionButton(val2, index); val2.SetActive(true); return component; } private static Button CreateContainerSortButton() { //IL_00ab: Unknown result type (might be due to invalid IL or missing references) //IL_00b5: Expected O, but got Unknown if ((Object)(object)_inventoryGui == (Object)null || (Object)(object)_inventoryGui.m_stackAllButton == (Object)null) { return null; } Button stackAllButton = _inventoryGui.m_stackAllButton; Transform parent = ((Component)stackAllButton).transform.parent; if ((Object)(object)parent == (Object)null) { return null; } Transform val = parent.Find("com.hex.quickstackstorage.ContainerSortButton"); if ((Object)(object)val != (Object)null) { return ((Component)val).GetComponent<Button>(); } GameObject val2 = Object.Instantiate<GameObject>(((Component)stackAllButton).gameObject, parent); ((Object)val2).name = "com.hex.quickstackstorage.ContainerSortButton"; Button component = val2.GetComponent<Button>(); if ((Object)(object)component == (Object)null) { Object.Destroy((Object)(object)val2); return null; } ((UnityEventBase)component.onClick).RemoveAllListeners(); ((UnityEvent)component.onClick).AddListener(new UnityAction(OnContainerSortClicked)); SetButtonText(val2, "S"); PositionContainerSortButton(val2, ((Component)stackAllButton).gameObject); val2.SetActive(false); return component; } private static Button CreateTrashButton(UnityAction onClick) { if (!Plugin.EnableTrashFeature) { return null; } Transform val = FindChildRecursive(((Component)_inventoryGui).transform, "com.hex.quickstackstorage.TrashButton"); if ((Object)(object)val != (Object)null) { return ((Component)val).GetComponent<Button>(); } RectTransform val2 = FindStatusTab("armor"); RectTransform val3 = FindStatusTab("weight"); if ((Object)(object)val2 == (Object)null || (Object)(object)val3 == (Object)null) { return null; } GameObject val4 = Object.Instantiate<GameObject>(((Component)val3).gameObject, ((Transform)val3).parent); ((Object)val4).name = "com.hex.quickstackstorage.TrashButton"; RectTransform component = val4.GetComponent<RectTransform>(); Transform val5 = val4.transform.Find("weight_icon"); Transform val6 = val4.transform.Find("weight_text"); if ((Object)(object)val6 != (Object)null) { ((Component)val6).gameObject.SetActive(false); } if ((Object)(object)val5 != (Object)null) { ((Component)val5).gameObject.SetActive(false); } CreateTrashIcon(val4.transform); Button val7 = val4.GetComponent<Button>(); if ((Object)(object)val7 == (Object)null) { val7 = val4.AddComponent<Button>(); } Image component2 = val4.GetComponent<Image>(); if ((Object)(object)component2 != (Object)null) { ((Selectable)val7).targetGraphic = (Graphic)(object)component2; } ((UnityEventBase)val7.onClick).RemoveAllListeners(); ((UnityEvent)val7.onClick).AddListener(onClick); PositionTrashButton(component, val2, val3); int siblingIndex = Mathf.Min(((Transform)val2).GetSiblingIndex(), ((Transform)val3).GetSiblingIndex()); ((Transform)component).SetSiblingIndex(siblingIndex); val4.SetActive(true); return val7; } private static void CreateTrashIcon(Transform parent) { //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_0036: 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_0060: Unknown result type (might be due to invalid IL or missing references) //IL_0075: Unknown result type (might be due to invalid IL or missing references) //IL_0089: Unknown result type (might be due to invalid IL or missing references) //IL_0093: Unknown result type (might be due to invalid IL or missing references) //IL_00b3: Unknown result type (might be due to invalid IL or missing references) //IL_00c8: Unknown result type (might be due to invalid IL or missing references) //IL_00d3: Unknown result type (might be due to invalid IL or missing references) //IL_00dd: Unknown result type (might be due to invalid IL or missing references) //IL_00e7: Unknown result type (might be due to invalid IL or missing references) //IL_0107: Unknown result type (might be due to invalid IL or missing references) //IL_011c: Unknown result type (might be due to invalid IL or missing references) //IL_0127: Unknown result type (might be due to invalid IL or missing references) //IL_0131: Unknown result type (might be due to invalid IL or missing references) //IL_013b: Unknown result type (might be due to invalid IL or missing references) //IL_015b: Unknown result type (might be due to invalid IL or missing references) //IL_0170: Unknown result type (might be due to invalid IL or missing references) //IL_017b: Unknown result type (might be due to invalid IL or missing references) //IL_0185: Unknown result type (might be due to invalid IL or missing references) //IL_018f: Unknown result type (might be due to invalid IL or missing references) //IL_019f: Unknown result type (might be due to invalid IL or missing references) GameObject val = new GameObject("com.hex.quickstackstorage.TrashIcon", new Type[1] { typeof(RectTransform) }); RectTransform component = val.GetComponent<RectTransform>(); ((Transform)component).SetParent(parent, false); component.anchorMin = new Vector2(0.5f, 0.5f); component.anchorMax = new Vector2(0.5f, 0.5f); component.pivot = new Vector2(0.5f, 0.5f); component.sizeDelta = new Vector2(32f, 32f); component.anchoredPosition = new Vector2(4f, 0f); RectTransform component2 = CreateIconPart(val.transform, "com.hex.quickstackstorage.TrashIcon.Body").GetComponent<RectTransform>(); component2.anchorMin = new Vector2(0.2f, 0.1f); component2.anchorMax = new Vector2(0.8f, 0.7f); component2.offsetMin = Vector2.zero; component2.offsetMax = Vector2.zero; RectTransform component3 = CreateIconPart(val.transform, "com.hex.quickstackstorage.TrashIcon.Lid").GetComponent<RectTransform>(); component3.anchorMin = new Vector2(0.1f, 0.74f); component3.anchorMax = new Vector2(0.9f, 0.84f); component3.offsetMin = Vector2.zero; component3.offsetMax = Vector2.zero; RectTransform component4 = CreateIconPart(val.transform, "com.hex.quickstackstorage.TrashIcon.Handle").GetComponent<RectTransform>(); component4.anchorMin = new Vector2(0.36f, 0.85f); component4.anchorMax = new Vector2(0.64f, 0.96f); component4.offsetMin = Vector2.zero; component4.offsetMax = Vector2.zero; CreateTrashSlot(val.transform, 0.35f); CreateTrashSlot(val.transform, 0.5f); CreateTrashSlot(val.transform, 0.65f); } private static GameObject CreateIconPart(Transform parent, string name) { //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_004e: Unknown result type (might be due to invalid IL or missing references) //IL_005f: Expected O, but got Unknown GameObject val = new GameObject(name, new Type[2] { typeof(RectTransform), typeof(Image) }); ((Transform)val.GetComponent<RectTransform>()).SetParent(parent, false); Image component = val.GetComponent<Image>(); ((Graphic)component).color = new Color(0.72f, 0.72f, 0.72f, 1f); ((Graphic)component).raycastTarget = false; return val; } private static void CreateTrashSlot(Transform parent, float x) { //IL_0025: 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_003f: Unknown result type (might be due to invalid IL or missing references) //IL_0050: Unknown result type (might be due to invalid IL or missing references) //IL_0064: Unknown result type (might be due to invalid IL or missing references) //IL_0088: Unknown result type (might be due to invalid IL or missing references) GameObject val = new GameObject("com.hex.quickstackstorage.TrashIcon.Slot", new Type[2] { typeof(RectTransform), typeof(Image) }); RectTransform component = val.GetComponent<RectTransform>(); ((Transform)component).SetParent(parent, false); component.anchorMin = new Vector2(x, 0.18f); component.anchorMax = new Vector2(x, 0.6f); component.sizeDelta = new Vector2(2f, 0f); Image component2 = val.GetComponent<Image>(); ((Graphic)component2).color = new Color(0.2f, 0.2f, 0.2f, 1f); ((Graphic)component2).raycastTarget = false; } private static void PositionTrashButton(RectTransform trashRect, RectTransform armorRect, RectTransform weightRect) { //IL_001e: 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_0036: 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_004d: 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_0058: Unknown result type (might be due to invalid IL or missing references) //IL_0062: Unknown result type (might be due to invalid IL or missing references) //IL_0067: Unknown result type (might be due to invalid IL or missing references) //IL_0069: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)trashRect == (Object)null) && !((Object)(object)armorRect == (Object)null) && !((Object)(object)weightRect == (Object)null)) { trashRect.anchorMin = weightRect.anchorMin; trashRect.anchorMax = weightRect.anchorMax; trashRect.pivot = weightRect.pivot; trashRect.sizeDelta = weightRect.sizeDelta; Vector3 position = (((Transform)armorRect).position + ((Transform)weightRect).position) * 0.5f; ((Transform)trashRect).position = position; } } private static void PositionContainerSortButton(GameObject buttonObject, GameObject templateObject) { //IL_0023: 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_0044: Unknown result type (might be due to invalid IL or missing references) //IL_0059: Unknown result type (might be due to invalid IL or missing references) //IL_0064: Unknown result type (might be due to invalid IL or missing references) //IL_006f: Unknown result type (might be due to invalid IL or missing references) //IL_0074: Unknown result type (might be due to invalid IL or missing references) //IL_007d: Unknown result type (might be due to invalid IL or missing references) //IL_0099: 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) RectTransform component = buttonObject.GetComponent<RectTransform>(); RectTransform component2 = templateObject.GetComponent<RectTransform>(); if (!((Object)(object)component == (Object)null) && !((Object)(object)component2 == (Object)null)) { component.anchorMin = component2.anchorMin; component.anchorMax = component2.anchorMax; component.pivot = new Vector2(0.5f, 0.5f); component.sizeDelta = new Vector2(36f, 36f); float x = component2.anchoredPosition.x; Rect rect = component2.rect; float num = x - ((Rect)(ref rect)).width * component2.pivot.x; component.anchoredPosition = new Vector2(num - 4f - 18f, component2.anchoredPosition.y); } } private static RectTransform FindStatusTab(string namePart) { RectTransform[] componentsInChildren = ((Component)_inventoryGui).GetComponentsInChildren<RectTransform>(true); foreach (RectTransform val in componentsInChildren) { if (!((Object)(object)val == (Object)null) && ((Object)val).name.IndexOf(namePart, StringComparison.OrdinalIgnoreCase) >= 0) { return val; } } return null; } private static Transform FindChildRecursive(Transform parent, string childName) { //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Expected O, but got Unknown if ((Object)(object)parent == (Object)null) { return null; } foreach (Transform item in parent) { Transform val = item; if (((Object)val).name == childName) { return val; } Transform val2 = FindChildRecursive(val, childName); if ((Object)(object)val2 != (Object)null) { return val2; } } return null; } private static void SetButtonText(GameObject buttonObject, string text) { TMP_Text componentInChildren = buttonObject.GetComponentInChildren<TMP_Text>(true); if ((Object)(object)componentInChildren != (Object)null) { componentInChildren.text = text; componentInChildren.alignment = (TextAlignmentOptions)514; return; } Text componentInChildren2 = buttonObject.GetComponentInChildren<Text>(true); if ((Object)(object)componentInChildren2 != (Object)null) { componentInChildren2.text = text; componentInChildren2.alignment = (TextAnchor)4; } } private static void StyleActionButton(GameObject buttonObject) { //IL_001c: Unknown result type (might be due to invalid IL or missing references) RectTransform component = buttonObject.GetComponent<RectTransform>(); if (!((Object)(object)component == (Object)null)) { component.sizeDelta = new Vector2(36f, 36f); Image component2 = buttonObject.GetComponent<Image>(); if ((Object)(object)component2 != (Object)null) { component2.type = (Type)1; } } } private static void PositionActionButton(GameObject buttonObject, int index) { //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_005f: Unknown result type (might be due to invalid IL or missing references) //IL_006a: Unknown result type (might be due to invalid IL or missing references) //IL_006f: Unknown result type (might be due to invalid IL or missing references) //IL_0089: Unknown result type (might be due to invalid IL or missing references) //IL_008e: Unknown result type (might be due to invalid IL or missing references) //IL_00a2: Unknown result type (might be due to invalid IL or missing references) RectTransform component = buttonObject.GetComponent<RectTransform>(); RectTransform component2 = ((Component)_inventoryGui.m_player).GetComponent<RectTransform>(); if (!((Object)(object)component == (Object)null) && !((Object)(object)component2 == (Object)null)) { component.anchorMin = new Vector2(0f, 1f); component.anchorMax = new Vector2(0f, 1f); component.pivot = new Vector2(0f, 1f); Rect rect = component2.rect; float num = ((Rect)(ref rect)).width + 8f + (float)index * 40f; rect = component2.rect; float num2 = 0f - ((Rect)(ref rect)).height + 36f; component.anchoredPosition = new Vector2(num, num2); } } private static void OnSortClicked() { if (!((Object)(object)Player.m_localPlayer == (Object)null)) { InventorySortService.SortPlayerInventory(); } } private static void OnContainerSortClicked() { Container currentContainer = GetCurrentContainer(); if (!((Object)(object)currentContainer == (Object)null)) { InventorySortService.SortContainer(currentContainer); } } private static void OnQuickStackClicked() { Player localPlayer = Player.m_localPlayer; if (!((Object)(object)localPlayer == (Object)null)) { QuickStackService.QuickStack(localPlayer); } } private static void OnTrashClicked() { //IL_0068: Unknown result type (might be due to invalid IL or missing references) //IL_006e: Expected O, but got Unknown //IL_0059: Unknown result type (might be due to invalid IL or missing references) //IL_005f: Expected O, but got Unknown if (!Plugin.EnableTrashFeature) { return; } Player player = Player.m_localPlayer; if (!((Object)(object)player == (Object)null) && !((Object)(object)_inventoryGui == (Object)null)) { UnityAction val = ((!(DragItemField?.GetValue(_inventoryGui) is ItemData)) ? ((UnityAction)delegate { TrashService.DeleteMarkedItems(player); }) : ((UnityAction)delegate { TrashService.DeleteDraggedItem(_inventoryGui, player); })); if (Plugin.EnableDeleteConfirmation) { DialogUiController.ShowDeleteConfirmation(_inventoryGui, val); } else { val.Invoke(); } } } } internal static class InventoryBorderRenderer { private const float BorderThickness = 2f; private static readonly FieldInfo ElementsField = AccessTools.Field(typeof(InventoryGrid), "m_elements"); internal static void Refresh(InventoryGrid grid, string borderName, Color borderColor, Func<ItemData, bool> shouldShowBorder) { //IL_007a: 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) if ((Object)(object)grid == (Object)null || grid.GetInventory() == null || shouldShowBorder == null) { return; } Player localPlayer = Player.m_localPlayer; if ((Object)(object)localPlayer == (Object)null || grid.GetInventory() != ((Humanoid)localPlayer).GetInventory() || !(ElementsField?.GetValue(grid) is List<InventoryElement> list)) { return; } int width = grid.GetInventory().GetWidth(); foreach (InventoryElement item in list) { if (!((Object)(object)item == (Object)null)) { SetBorderVisible(item, borderName, borderColor, visible: false); } } foreach (ItemData allItem in grid.GetInventory().GetAllItems()) { if (allItem == null || !shouldShowBorder(allItem)) { continue; } int num = allItem.m_gridPos.y * width + allItem.m_gridPos.x; if (num >= 0 && num < list.Count) { InventoryElement val = list[num]; if ((Object)(object)val != (Object)null) { SetBorderVisible(val, borderName, borderColor, visible: true); } } } } private static void SetBorderVisible(InventoryElement element, string borderName, Color borderColor, bool visible) { //IL_0032: Unknown result type (might be due to invalid IL or missing references) Transform val = ((Component)element).transform.Find(borderName); GameObject val2 = (((Object)(object)val != (Object)null) ? ((Component)val).gameObject : null); if ((Object)(object)val2 == (Object)null && visible) { val2 = CreateBorder(((Component)element).transform, borderName, borderColor); } if ((Object)(object)val2 != (Object)null) { val2.SetActive(visible); } } private static GameObject CreateBorder(Transform parent, string borderName, Color borderColor) { //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_0029: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_0054: Unknown result type (might be due to invalid IL or missing references) //IL_0069: Unknown result type (might be due to invalid IL or missing references) //IL_0078: Unknown result type (might be due to invalid IL or missing references) //IL_0087: Unknown result type (might be due to invalid IL or missing references) //IL_008c: Unknown result type (might be due to invalid IL or missing references) //IL_0091: 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_00ac: 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_00c0: Unknown result type (might be due to invalid IL or missing references) //IL_00cf: Unknown result type (might be due to invalid IL or missing references) //IL_00d4: Unknown result type (might be due to invalid IL or missing references) //IL_00da: Unknown result type (might be due to invalid IL or missing references) //IL_00ef: 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) //IL_0103: Unknown result type (might be due to invalid IL or missing references) //IL_0112: Unknown result type (might be due to invalid IL or missing references) //IL_0117: Unknown result type (might be due to invalid IL or missing references) //IL_011d: Unknown result type (might be due to invalid IL or missing references) //IL_0132: Unknown result type (might be due to invalid IL or missing references) //IL_0141: Unknown result type (might be due to invalid IL or missing references) //IL_0150: Unknown result type (might be due to invalid IL or missing references) //IL_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_0167: Expected O, but got Unknown GameObject val = new GameObject(borderName, new Type[1] { typeof(RectTransform) }); RectTransform component = val.GetComponent<RectTransform>(); ((Transform)component).SetParent(parent, false); component.anchorMin = Vector2.zero; component.anchorMax = Vector2.one; component.offsetMin = Vector2.zero; component.offsetMax = Vector2.zero; CreateEdge(val.transform, "Top", new Vector2(0f, 1f), new Vector2(1f, 1f), new Vector2(0f, -2f), Vector2.zero, borderColor); CreateEdge(val.transform, "Bottom", new Vector2(0f, 0f), new Vector2(1f, 0f), Vector2.zero, new Vector2(0f, 2f), borderColor); CreateEdge(val.transform, "Left", new Vector2(0f, 0f), new Vector2(0f, 1f), Vector2.zero, new Vector2(2f, 0f), borderColor); CreateEdge(val.transform, "Right", new Vector2(1f, 0f), new Vector2(1f, 1f), new Vector2(-2f, 0f), Vector2.zero, borderColor); ((Transform)component).SetAsLastSibling(); return val; } private static void CreateEdge(Transform parent, string name, Vector2 anchorMin, Vector2 anchorMax, Vector2 offsetMin, Vector2 offsetMax, Color borderColor) { //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_0035: 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) //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_0057: Unknown result type (might be due to invalid IL or missing references) GameObject val = new GameObject(name, new Type[2] { typeof(RectTransform), typeof(Image) }); RectTransform component = val.GetComponent<RectTransform>(); ((Transform)component).SetParent(parent, false); component.anchorMin = anchorMin; component.anchorMax = anchorMax; component.offsetMin = offsetMin; component.offsetMax = offsetMax; Image component2 = val.GetComponent<Image>(); ((Graphic)component2).color = borderColor; ((Graphic)component2).raycastTarget = false; } } } namespace HexQuickStackStorage.Services { internal static class InventoryOperationsService { private static readonly MethodInfo ChangedMethod = typeof(Inventory).GetMethod("Changed", BindingFlags.Instance | BindingFlags.NonPublic, null, new Type[2] { typeof(bool), typeof(bool) }, null); private static readonly MethodInfo FindFreeStackItemMethod = typeof(Inventory).GetMethod("FindFreeStackItem", BindingFlags.Instance | BindingFlags.NonPublic, null, new Type[3] { typeof(string), typeof(int), typeof(int) }, null); private static readonly MethodInfo FindEmptySlotMethod = typeof(Inventory).GetMethod("FindEmptySlot", BindingFlags.Instance | BindingFlags.NonPublic, null, new Type[1] { typeof(bool) }, null); private static readonly MethodInfo TopFirstMethod = typeof(Inventory).GetMethod("TopFirst", BindingFlags.Instance | BindingFlags.NonPublic, null, new Type[1] { typeof(ItemData) }, null); private static readonly object[] ChangedArguments = new object[2] { false, false }; internal static void NotifyChanged(Inventory inventory) { if (inventory != null) { ChangedMethod?.Invoke(inventory, ChangedArguments); } } internal static ItemData FindFreeStackItem(Inventory inventory, ItemData item) { if (inventory == null || item == null || FindFreeStackItemMethod == null) { return null; } object? obj = FindFreeStackItemMethod.Invoke(inventory, new object[3] { item.m_shared.m_name, item.m_quality, item.m_worldLevel }); return (ItemData)((obj is ItemData) ? obj : null); } internal static Vector2i FindEmptySlot(Inventory inventory, ItemData item) { //IL_0022: 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 (inventory == null || item == null || FindEmptySlotMethod == null || TopFirstMethod == null) { return new Vector2i(-1, -1); } bool flag = (bool)TopFirstMethod.Invoke(inventory, new object[1] { item }); return (Vector2i)FindEmptySlotMethod.Invoke(inventory, new object[1] { flag }); } } } namespace HexQuickStackStorage.Patches { [HarmonyPatch(typeof(Container))] internal static class ContainerPatch { [HarmonyPatch("RPC_OpenResponse")] [HarmonyPostfix] private static void RPC_OpenResponsePostfix(Container __instance, bool granted) { if (granted && Plugin.EnableChestAutoSorting) { InventorySortService.SortContainer(__instance); } } [HarmonyPatch("RPC_StackResponse")] [HarmonyPrefix] private static bool RPC_StackResponsePrefix(Container __instance, bool granted) { if (!granted) { return true; } Player localPlayer = Player.m_localPlayer; if ((Object)(object)localPlayer == (Object)null) { return false; } QuickStackService.QuickStack(localPlayer, __instance); return false; } } [HarmonyPatch] internal static class InventoryGridPatch { [HarmonyPatch(typeof(InventoryGui), "OnRightClickItem")] [HarmonyPrefix] private static bool OnRightClickItemPrefix(InventoryGrid grid, ItemData item) { //IL_005b: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Unknown result type (might be due to invalid IL or missing references) Player localPlayer = Player.m_localPlayer; if ((Object)(object)localPlayer == (Object)null || (Object)(object)grid == (Object)null || item == null) { return true; } if (grid.GetInventory() != ((Humanoid)localPlayer).GetInventory()) { return true; } if (!TrashService.IsVanillaInventoryItem(localPlayer, item)) { return true; } if (Plugin.EnableTrashFeature && ZInput.GetKey(Plugin.TrashModifierKey, true)) { ItemStateService.ToggleTrash(localPlayer, item); RefreshItemStateBorders(grid); return false; } if (ZInput.GetKey(Plugin.FavoriteModifierKey, true)) { ItemStateService.ToggleFavorite(localPlayer, item); RefreshItemStateBorders(grid); return false; } return true; } [HarmonyPatch(typeof(InventoryGrid), "UpdateGui")] [HarmonyPostfix] private static void UpdateGuiPostfix(InventoryGrid __instance) { RefreshItemStateBorders(__instance); } private static void RefreshItemStateBorders(InventoryGrid grid) { //IL_002b: 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_0069: Unknown result type (might be due to invalid IL or missing references) if (Plugin.EnableTrashFeature) { InventoryBorderRenderer.Refresh(grid, "HexTrashBorder", Color.red, TrashService.IsMarked); } else { InventoryBorderRenderer.Refresh(grid, "HexTrashBorder", Color.red, (ItemData item) => false); } InventoryBorderRenderer.Refresh(grid, "HexFavoriteBorder", new Color(1f, 0.75f, 0f), FavoriteService.IsFavorite); } } [HarmonyPatch] internal static class InventoryGuiPatch { [HarmonyPatch(typeof(InventoryGui), "Awake")] [HarmonyPostfix] private static void AwakePostfix(InventoryGui __instance) { InventoryUiController.Initialize(__instance); } [HarmonyPatch(typeof(InventoryGui), "OnStackAll")] [HarmonyPrefix] private static bool OnStackAllPrefix() { Player localPlayer = Player.m_localPlayer; if ((Object)(object)localPlayer == (Object)null) { return true; } Container currentContainer = InventoryUiController.GetCurrentContainer(); if ((Object)(object)currentContainer == (Object)null) { return true; } QuickStackService.QuickStack(localPlayer, currentContainer); return false; } [HarmonyPatch(typeof(InventoryGui), "Show")] [HarmonyPostfix] private static void ShowPostfix(Container container) { bool num = (Object)(object)container != (Object)null; InventoryUiController.SetContainerSortButtonVisible(num); InventoryUiController.SetQuickStackButtonInteractable(!num); } [HarmonyPatch(typeof(InventoryGui), "CloseContainer")] [HarmonyPostfix] private static void CloseContainerPostfix() { InventoryUiController.SetContainerSortButtonVisible(visible: false); InventoryUiController.SetQuickStackButtonInteractable(interactable: true); } } } 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 ServerSync { [PublicAPI] internal abstract class OwnConfigEntryBase { public object? LocalBaseValue; public bool SynchronizedConfig = true; public abstract ConfigEntryBase BaseConfig { get; } } [PublicAPI] internal class SyncedConfigEntry<T>(ConfigEntry<T> sourceConfig) : OwnConfigEntryBase() { public readonly ConfigEntry<T> SourceConfig = sourceConfig; public override ConfigEntryBase BaseConfig => (ConfigEntryBase)(object)SourceConfig; public T Value { get { return SourceConfig.Value; } set { SourceConfig.Value = value; } } public void AssignLocalValue(T value) { if (LocalBaseValue == null) { Value = value; } else { LocalBaseValue = value; } } } internal abstract class CustomSyncedValueBase { public object? LocalBaseValue; public readonly string Identifier; public readonly Type Type; private object? boxedValue; protected bool localIsOwner; public readonly int Priority; public object? BoxedValue { get { return boxedValue; } set { boxedValue = value; this.ValueChanged?.Invoke(); } } public event Action? ValueChanged; protected CustomSyncedValueBase(ConfigSync configSync, string identifier, Type type, int priority) { Priority = priority; Identifier = identifier; Type = type; configSync.AddCustomValue(this); localIsOwner = configSync.IsSourceOfTruth; configSync.SourceOfTruthChanged += delegate(bool truth) { localIsOwner = truth; }; } } [PublicAPI] internal sealed class CustomSyncedValue<T> : CustomSyncedValueBase { public T Value { get { return (T)base.BoxedValue; } set { base.BoxedValue = value; } } public CustomSyncedValue(ConfigSync configSync, string identifier, T value = default(T), int priority = 0) : base(configSync, identifier, typeof(T), priority) { Value = value; } public void AssignLocalValue(T value) { if (localIsOwner) { Value = value; } else { LocalBaseValue = value; } } } internal class ConfigurationManagerAttributes { [UsedImplicitly] public bool? ReadOnly = false; } [PublicAPI] internal class ConfigSync { [HarmonyPatch(typeof(ZRpc), "HandlePackage")] private static class SnatchCurrentlyHandlingRPC { public static ZRpc? currentRpc; [HarmonyPrefix] private static void Prefix(ZRpc __instance) { currentRpc = __instance; } } [HarmonyPatch(typeof(ZNet), "Awake")] internal static class RegisterRPCPatch { [HarmonyPostfix] private static void Postfix(ZNet __instance) { isServer = __instance.IsServer(); foreach (ConfigSync configSync2 in configSyncs) { ZRoutedRpc.instance.Register<ZPackage>(configSync2.Name + " ConfigSync", (Action<long, ZPackage>)configSync2.RPC_FromOtherClientConfigSync); if (isServer) { configSync2.InitialSyncDone = true; Debug.Log((object)("Registered '" + configSync2.Name + " ConfigSync' RPC - waiting for incoming connections")); } } if (isServer) { ((MonoBehaviour)__instance).StartCoroutine(WatchAdminListChanges()); } static void SendAdmin(List<ZNetPeer> peers, bool isAdmin) { ZPackage package = ConfigsToPackage(null, null, new PackageEntry[1] { new PackageEntry { section = "Internal", key = "lockexempt", type = typeof(bool), value = isAdmin } }); ConfigSync configSync = configSyncs.First(); if (configSync != null) { ((MonoBehaviour)ZNet.instance).StartCoroutine(configSync.sendZPackage(peers, package)); } } static IEnumerator WatchAdminListChanges() { MethodInfo listContainsId = AccessTools.DeclaredMethod(typeof(ZNet), "ListContainsId", (Type[])null, (Type[])null); SyncedList adminList = (SyncedList)AccessTools.DeclaredField(typeof(ZNet), "m_adminList").GetValue(ZNet.instance); List<string> CurrentList = new List<string>(adminList.GetList()); while (true) { yield return (object)new WaitForSeconds(30f); if (!adminList.GetList().SequenceEqual(CurrentList)) { CurrentList = new List<string>(adminList.GetList()); List<ZNetPeer> adminPeer = ZNet.instance.GetPeers().Where(delegate(ZNetPeer p) { string hostName = p.m_rpc.GetSocket().GetHostName(); return ((object)listContainsId == null) ? adminList.Contains(hostName) : ((bool)listContainsId.Invoke(ZNet.instance, new object[2] { adminList, hostName })); }).ToList(); List<ZNetPeer> nonAdminPeer = ZNet.instance.GetPeers().Except(adminPeer).ToList(); SendAdmin(nonAdminPeer, isAdmin: false); SendAdmin(adminPeer, isAdmin: true); } } } } } [HarmonyPatch(typeof(ZNet), "OnNewConnection")] private static class RegisterClientRPCPatch { [HarmonyPostfix] private static void Postfix(ZNet __instance, ZNetPeer peer) { if (__instance.IsServer()) { return; } foreach (ConfigSync configSync in configSyncs) { peer.m_rpc.Register<ZPackage>(configSync.Name + " ConfigSync", (Action<ZRpc, ZPackage>)configSync.RPC_FromServerConfigSync); } } } private class ParsedConfigs { public readonly Dictionary<OwnConfigEntryBase, object?> configValues = new Dictionary<OwnConfigEntryBase, object>(); public readonly Dictionary<CustomSyncedValueBase, object?> customValues = new Dictionary<CustomSyncedValueBase, object>(); } [HarmonyPatch(typeof(ZNet), "Shutdown")] private class ResetConfigsOnShutdown { [HarmonyPostfix] private static void Postfix() { ProcessingServerUpdate = true; foreach (ConfigSync configSync in configSyncs) { configSync.resetConfigsFromServer(); configSync.IsSourceOfTruth = true; configSync.InitialSyncDone = false; } ProcessingServerUpdate = false; } } [HarmonyPatch(typeof(ZNet), "RPC_PeerInfo")] private class SendConfigsAfterLogin { private class BufferingSocket : ZPlayFabSocket, ISocket { public volatile bool finished = false; public volatile int versionMatchQueued = -1; public readonly List<ZPackage> Package = new List<ZPackage>(); public readonly ISocket Original; public BufferingSocket(ISocket original) { Original = original; ((ZPlayFabSocket)this)..ctor(); } public bool IsConnected() { return Original.IsConnected(); } public ZPackage Recv() { return Original.Recv(); } public int GetSendQueueSize() { return Original.GetSendQueueSize(); } public int GetCurrentSendRate() { return Original.GetCurrentSendRate(); } public bool IsHost() { return Original.IsHost(); } public void Dispose() { Original.Dispose(); } public bool GotNewData() { return Original.GotNewData(); } public void Close() { Original.Close(); } public string GetEndPointString() { return Original.GetEndPointString(); } public void GetAndResetStats(out int totalSent, out int totalRecv) { Original.GetAndResetStats(ref totalSent, ref totalRecv); } public void GetConnectionQuality(out float localQuality, out float remoteQuality, out int ping, out float outByteSec, out float inByteSec) { Original.GetConnectionQuality(ref localQuality, ref remoteQuality, ref ping, ref outByteSec, ref inByteSec); } public ISocket Accept() { return Original.Accept(); } public int GetHostPort() { return Original.GetHostPort(); } public bool Flush() { return Original.Flush(); } public string GetHostName() { return Original.GetHostName(); } public void VersionMatch() { if (finished) { Original.VersionMatch(); } else { versionMatchQueued = Package.Count; } } public void Send(ZPackage pkg) { //IL_0057: Unknown result type (might be due to invalid IL or missing references) //IL_005d: Expected O, but got Unknown int pos = pkg.GetPos(); pkg.SetPos(0); int num = pkg.ReadInt(); if ((num == StringExtensionMethods.GetStableHashCode("PeerInfo") || num == StringExtensionMethods.GetStableHashCode("RoutedRPC") || num == StringExtensionMethods.GetStableHashCode("ZDOData")) && !finished) { ZPackage val = new ZPackage(pkg.GetArray()); val.SetPos(pos); Package.Add(val); } else { pkg.SetPos(pos); Original.Send(pkg); } } } [HarmonyPriority(800)] [HarmonyPrefix] private static void Prefix(ref Dictionary<Assembly, BufferingSocket>? __state, ZNet __instance, ZRpc rpc) { //IL_0078: Unknown result type (might be due to invalid IL or missing references) //IL_007e: Invalid comparison between Unknown and I4 if (!__instance.IsServer()) { return; } BufferingSocket bufferingSocket = new BufferingSocket(rpc.GetSocket()); AccessTools.DeclaredField(typeof(ZRpc), "m_socket").SetValue(rpc, bufferingSocket); object? obj = AccessTools.DeclaredMethod(typeof(ZNet), "GetPeer", new Type[1] { typeof(ZRpc) }, (Type[])null).Invoke(__instance, new object[1] { rpc }); ZNetPeer val = (ZNetPeer)((obj is ZNetPeer) ? obj : null); if (val != null && (int)ZNet.m_onlineBackend > 0) { FieldInfo fieldInfo = AccessTools.DeclaredField(typeof(ZNetPeer), "m_socket"); object? value = fieldInfo.GetValue(val); ZPlayFabSocket val2 = (ZPlayFabSocket)((value is ZPlayFabSocket) ? value : null); if (val2 != null) { typeof(ZPlayFabSocket).GetField("m_remotePlayerId").SetValue(bufferingSocket, val2.m_remotePlayerId); } fieldInfo.SetValue(val, bufferingSocket); } if (__state == null) { __state = new Dictionary<Assembly, BufferingSocket>(); } __state[Assembly.GetExecutingAssembly()] = bufferingSocket; } [HarmonyPostfix] private static void Postfix(Dictionary<Assembly, BufferingSocket> __state, ZNet __instance, ZRpc rpc) { ZNetPeer peer; if (__instance.IsServer()) { object obj = AccessTools.DeclaredMethod(typeof(ZNet), "GetPeer", new Type[1] { typeof(ZRpc) }, (Type[])null).Invoke(__instance, new object[1] { rpc }); peer = (ZNetPeer)((obj is ZNetPeer) ? obj : null); if (peer == null) { SendBufferedData(); } else { ((MonoBehaviour)__instance).StartCoroutine(sendAsync()); } } void SendBufferedData() { if (rpc.GetSocket() is BufferingSocket bufferingSocket) { AccessTools.DeclaredField(typeof(ZRpc), "m_socket").SetValue(rpc, bufferingSocket.Original); object? obj2 = AccessTools.DeclaredMethod(typeof(ZNet), "GetPeer", new Type[1] { typeof(ZRpc) }, (Type[])null).Invoke(__instance, new object[1] { rpc }); ZNetPeer val = (ZNetPeer)((obj2 is ZNetPeer) ? obj2 : null); if (val != null) { AccessTools.DeclaredField(typeof(ZNetPeer), "m_socket").SetValue(val, bufferingSocket.Ori