Please disclose if your mod was created primarily 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 QuickStackStore ItemDrawers Fix v1.0.6
QuickStackStore.ItemDrawersCompat.dll
Decompiled a month agousing System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; using Microsoft.CodeAnalysis; using UnityEngine; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")] [assembly: AssemblyCompany("QuickStackStore.ItemDrawersCompat")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0+287dc9c1ee3474f9f1f63bbd5daf2e59260ba07a")] [assembly: AssemblyProduct("QuickStackStore.ItemDrawersCompat")] [assembly: AssemblyTitle("QuickStackStore.ItemDrawersCompat")] [assembly: AssemblyVersion("1.0.0.0")] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Microsoft.CodeAnalysis.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] [Microsoft.CodeAnalysis.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] [Microsoft.CodeAnalysis.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 QuickStackStoreItemDrawersCompat { [BepInPlugin("pavel.quickstackstore.itemdrawers_compat", "QSS - ItemDrawers Compat (UseItem, MP-safe)", "1.0.3")] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] public sealed class QuickStackStoreItemDrawersCompatPlugin : BaseUnityPlugin { public const string ModGuid = "pavel.quickstackstore.itemdrawers_compat"; public const string ModName = "QSS - ItemDrawers Compat (UseItem, MP-safe)"; public const string ModVersion = "1.0.3"; internal static ConfigEntry<float> SearchRadius; internal static ConfigEntry<bool> IncludeHotbar; internal static ConfigEntry<int> MaxDrawersToCheck; internal static ConfigEntry<bool> PreferQssRadiusIfAvailable; internal static ConfigEntry<bool> FillEmptyDrawers; internal static ConfigEntry<bool> DebugLogging; private void Awake() { SearchRadius = ((BaseUnityPlugin)this).Config.Bind<float>("General", "SearchRadius", 10f, "Drawer search radius (meters). Used if PreferQssRadiusIfAvailable=false, or if QSS radius cannot be read."); IncludeHotbar = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "IncludeHotbar", false, "If true, quickstack will also move items from hotbar."); MaxDrawersToCheck = ((BaseUnityPlugin)this).Config.Bind<int>("General", "MaxDrawersToCheck", 200, "Safety limit: max number of drawers to evaluate (nearest first)."); PreferQssRadiusIfAvailable = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "PreferQssRadiusIfAvailable", true, "If true, tries to read QSS nearby-range config and use it instead of SearchRadius."); FillEmptyDrawers = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "FillEmptyDrawers", false, "If false: only drawers that are already set to the same item will be used. If true: if no matching drawer exists, may place into empty drawers."); DebugLogging = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "DebugLogging", false, "Enable debug logging."); Harmony.CreateAndPatchAll(Assembly.GetExecutingAssembly(), "pavel.quickstackstore.itemdrawers_compat"); ((BaseUnityPlugin)this).Logger.LogInfo((object)"QSS - ItemDrawers Compat (UseItem, MP-safe) v1.0.3 loaded"); } internal static void Dbg(string msg) { if (DebugLogging.Value) { Logger.CreateLogSource("QSS - ItemDrawers Compat (UseItem, MP-safe)").LogInfo((object)("[QSS-DrawersCompat] " + msg)); } } } [HarmonyPatch] internal static class QssReportPatch { [HarmonyTargetMethod] private static MethodBase? TargetMethod() { Type type = AccessTools.TypeByName("QuickStackStore.QuickStackModule"); if (!(type == null)) { return AccessTools.Method(type, "ReportQuickStackResult", new Type[2] { typeof(Player), typeof(int) }, (Type[])null); } return null; } [HarmonyPrefix] private static void Prefix(Player player, ref int movedCount) { try { if (!((Object)(object)player == (Object)null) && !(AccessTools.TypeByName("kg_ItemDrawers.DrawerComponent") == null)) { int num = DrawerQuickStacker.TryQuickStackIntoNearbyDrawers(player); if (num > 0) { movedCount += num; } } } catch (Exception arg) { Debug.LogError((object)$"[QSS-DrawersCompat] Error: {arg}"); } } } internal static class DrawerQuickStacker { private readonly struct DrawerInfo { public readonly Component Comp; public readonly float Distance; public readonly string CurrentPrefab; public readonly int CurrentAmount; public DrawerInfo(Component comp, float dist, string currentPrefab, int currentAmount) { Comp = comp; Distance = dist; CurrentPrefab = currentPrefab; CurrentAmount = currentAmount; } } private const string DrawerTypeName = "kg_ItemDrawers.DrawerComponent"; private static MethodInfo? _useItemMethod; private static MethodInfo? _getInventoryMethod; private static FieldInfo? _inventoryField; private static PropertyInfo? _piCurrentPrefab; private static PropertyInfo? _piCurrentAmount; private static Type? _qssUserConfigType; private static MethodInfo? _miGetPlayerConfig; private static MethodInfo? _miIsItemNameOrSlotFavorited; public static int TryQuickStackIntoNearbyDrawers(Player player) { Player player2 = player; Type type = AccessTools.TypeByName("kg_ItemDrawers.DrawerComponent"); if (type == null) { return 0; } if ((object)_useItemMethod == null) { _useItemMethod = AccessTools.Method(type, "UseItem", new Type[2] { typeof(Humanoid), typeof(ItemData) }, (Type[])null); } if (_useItemMethod == null) { return 0; } if ((object)_piCurrentPrefab == null) { _piCurrentPrefab = AccessTools.Property(type, "CurrentPrefab"); } if ((object)_piCurrentAmount == null) { _piCurrentAmount = AccessTools.Property(type, "CurrentAmount"); } float range = GetEffectiveRange(); if (range <= 0.05f) { return 0; } Object[] array = Object.FindObjectsByType(type, (FindObjectsSortMode)0); if (array == null || array.Length == 0) { return 0; } int num = Math.Max(1, QuickStackStoreItemDrawersCompatPlugin.MaxDrawersToCheck.Value); List<DrawerInfo> list = (from o in array select (Component)(object)((o is Component) ? o : null) into c where (Object)(object)c != (Object)null && (Object)(object)c.gameObject != (Object)null && c.gameObject.activeInHierarchy select new DrawerInfo(c, Vector3.Distance(((Component)player2).transform.position, c.transform.position), ReadCurrentPrefab(c), ReadCurrentAmount(c)) into x where x.Distance <= range orderby x.Distance select x).Take(num).ToList(); if (list.Count == 0) { return 0; } QuickStackStoreItemDrawersCompatPlugin.Dbg($"Nearby drawers found: {list.Count} (radius={range}, max={num})"); Inventory humanoidInventory = GetHumanoidInventory((Humanoid)(object)player2); if (humanoidInventory == null) { return 0; } List<ItemData> list2 = humanoidInventory.GetAllItems()?.ToList(); if (list2 == null || list2.Count == 0) { return 0; } bool includeHotbar = QuickStackStoreItemDrawersCompatPlugin.IncludeHotbar.Value; List<ItemData> list3 = (from i in list2 where i != null where i.m_stack > 0 where includeHotbar || !IsHotbarItem(i) where i.m_customData == null || i.m_customData.Count == 0 where (Object)(object)i.m_dropPrefab != (Object)null && !string.IsNullOrWhiteSpace(((Object)i.m_dropPrefab).name) where !IsQssFavorited(player2, i) select i).ToList(); if (list3.Count == 0) { return 0; } Dictionary<string, List<DrawerInfo>> dictionary = new Dictionary<string, List<DrawerInfo>>(StringComparer.Ordinal); List<DrawerInfo> list4 = new List<DrawerInfo>(); foreach (DrawerInfo item in list) { if (!string.IsNullOrEmpty(item.CurrentPrefab)) { if (!dictionary.TryGetValue(item.CurrentPrefab, out var value)) { value = new List<DrawerInfo>(); dictionary[item.CurrentPrefab] = value; } value.Add(item); } else { list4.Add(item); } } foreach (KeyValuePair<string, List<DrawerInfo>> item2 in dictionary) { item2.Value.Sort(delegate(DrawerInfo a, DrawerInfo b) { float distance3 = a.Distance; return distance3.CompareTo(b.Distance); }); } list4.Sort(delegate(DrawerInfo a, DrawerInfo b) { float distance2 = a.Distance; return distance2.CompareTo(b.Distance); }); bool value2 = QuickStackStoreItemDrawersCompatPlugin.FillEmptyDrawers.Value; int num2 = 0; foreach (ItemData item3 in list3) { if (item3 == null || !humanoidInventory.ContainsItem(item3)) { continue; } string name = ((Object)item3.m_dropPrefab).name; bool flag = false; if (dictionary.TryGetValue(name, out var value3) && value3.Count > 0) { foreach (DrawerInfo item4 in value3) { if (TryUseItem(player2, item3, item4.Comp)) { num2++; flag = true; break; } } } if (flag || !value2 || list4.Count <= 0) { continue; } foreach (DrawerInfo item5 in list4) { if (!TryUseItem(player2, item3, item5.Comp)) { continue; } num2++; flag = true; string text = ReadCurrentPrefab(item5.Comp); int num3 = ReadCurrentAmount(item5.Comp); if (!string.IsNullOrEmpty(text) && num3 > 0) { list4.Remove(item5); if (!dictionary.TryGetValue(text, out var value4)) { value4 = (dictionary[text] = new List<DrawerInfo>()); } value4.Add(new DrawerInfo(item5.Comp, item5.Distance, text, num3)); value4.Sort(delegate(DrawerInfo a, DrawerInfo b) { float distance = a.Distance; return distance.CompareTo(b.Distance); }); } break; } } if (num2 > 0) { QuickStackStoreItemDrawersCompatPlugin.Dbg($"Moved stacks into drawers: {num2}"); } return num2; } private static bool TryUseItem(Player player, ItemData item, Component drawerComp) { try { ZNetView component = drawerComp.GetComponent<ZNetView>(); if ((Object)(object)component != (Object)null && component.IsValid()) { component.ClaimOwnership(); } object obj = _useItemMethod.Invoke(drawerComp, new object[2] { player, item }); bool flag = default(bool); int num; if (obj is bool) { flag = (bool)obj; num = 1; } else { num = 0; } return (byte)((uint)num & (flag ? 1u : 0u)) != 0; } catch { return false; } } private static bool IsQssFavorited(Player player, ItemData item) { try { if ((object)_qssUserConfigType == null) { _qssUserConfigType = AccessTools.TypeByName("QuickStackStore.UserConfig"); } if (_qssUserConfigType == null) { return false; } if ((object)_miGetPlayerConfig == null) { _miGetPlayerConfig = AccessTools.Method(_qssUserConfigType, "GetPlayerConfig", new Type[1] { typeof(long) }, (Type[])null); } if (_miGetPlayerConfig == null) { return false; } if ((object)_miIsItemNameOrSlotFavorited == null) { _miIsItemNameOrSlotFavorited = AccessTools.Method(_qssUserConfigType, "IsItemNameOrSlotFavorited", new Type[1] { typeof(ItemData) }, (Type[])null); } if (_miIsItemNameOrSlotFavorited == null) { return false; } long playerID = player.GetPlayerID(); object obj = _miGetPlayerConfig.Invoke(null, new object[1] { playerID }); if (obj == null) { return false; } object obj2 = _miIsItemNameOrSlotFavorited.Invoke(obj, new object[1] { item }); bool flag = default(bool); int num; if (obj2 is bool) { flag = (bool)obj2; num = 1; } else { num = 0; } return (byte)((uint)num & (flag ? 1u : 0u)) != 0; } catch { return false; } } private static float GetEffectiveRange() { float result = Math.Max(0f, QuickStackStoreItemDrawersCompatPlugin.SearchRadius.Value); if (!QuickStackStoreItemDrawersCompatPlugin.PreferQssRadiusIfAvailable.Value) { return result; } float num = TryGetQssNearbyRangeOrNaN(); if (!float.IsNaN(num) && num > 0.05f) { return num; } return result; } private static float TryGetQssNearbyRangeOrNaN() { try { Type type = AccessTools.TypeByName("QuickStackStore.QSSConfig+QuickStackConfig"); if (type == null) { return float.NaN; } FieldInfo fieldInfo = AccessTools.Field(type, "QuickStackToNearbyRange"); if (fieldInfo == null) { return float.NaN; } object value = fieldInfo.GetValue(null); if (value == null) { return float.NaN; } PropertyInfo property = value.GetType().GetProperty("Value", BindingFlags.Instance | BindingFlags.Public); if (property == null) { return float.NaN; } return (property.GetValue(value) is float num) ? num : float.NaN; } catch { return float.NaN; } } private static Inventory? GetHumanoidInventory(Humanoid h) { try { if ((object)_getInventoryMethod == null) { _getInventoryMethod = AccessTools.Method(((object)h).GetType(), "GetInventory", Type.EmptyTypes, (Type[])null); } if (_getInventoryMethod != null) { object? obj = _getInventoryMethod.Invoke(h, Array.Empty<object>()); Inventory val = (Inventory)((obj is Inventory) ? obj : null); if (val != null) { return val; } } } catch { } try { if ((object)_inventoryField == null) { _inventoryField = AccessTools.Field(((object)h).GetType(), "m_inventory"); } if (_inventoryField != null) { object? value = _inventoryField.GetValue(h); Inventory val2 = (Inventory)((value is Inventory) ? value : null); if (val2 != null) { return val2; } } } catch { } return null; } private static bool IsHotbarItem(ItemData item) { try { FieldInfo fieldInfo = AccessTools.Field(((object)item).GetType(), "m_gridPos"); if (fieldInfo == null) { return false; } object value = fieldInfo.GetValue(item); if (value == null) { return false; } FieldInfo field = value.GetType().GetField("y", BindingFlags.Instance | BindingFlags.Public); if (field == null) { return false; } return field.GetValue(value) is int num && num == 0; } catch { return false; } } private static string ReadCurrentPrefab(Component drawerComp) { try { if (_piCurrentPrefab == null) { return string.Empty; } return (_piCurrentPrefab.GetValue(drawerComp) as string) ?? string.Empty; } catch { return string.Empty; } } private static int ReadCurrentAmount(Component drawerComp) { try { if (_piCurrentAmount == null) { return 0; } return (_piCurrentAmount.GetValue(drawerComp) is int num) ? num : 0; } catch { return 0; } } } }