using System; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using BepInEx; using BepInEx.Bootstrap; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; using Jotunn.Utils; using Microsoft.CodeAnalysis; using UnityEngine; using UnityEngine.UI; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: IgnoresAccessChecksTo("assembly_guiutils")] [assembly: IgnoresAccessChecksTo("assembly_utils")] [assembly: IgnoresAccessChecksTo("assembly_valheim")] [assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")] [assembly: AssemblyCompany("NathansQol.QuickStack")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("0.2.2.0")] [assembly: AssemblyInformationalVersion("0.2.2+d4126be973f0be660e31d2112d3f9998b67c1334")] [assembly: AssemblyProduct("NathansQol.QuickStack")] [assembly: AssemblyTitle("NathansQol.QuickStack")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("0.2.2.0")] [module: UnverifiableCode] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace NathansQol.QuickStack { internal static class ChestFinder { internal static List InRange(Vector3 center, float radius) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) List list = new List(); Piece.GetAllPiecesInRadius(center, radius, list); List list2 = new List(); foreach (Piece item in list) { Container component = ((Component)item).GetComponent(); if ((Object)(object)component != (Object)null) { list2.Add(component); } } return list2; } } internal static class ItemLock { private const string Key = "nathan.quickstack.locked"; internal static bool IsLocked(ItemData item) { return item?.m_customData.ContainsKey("nathan.quickstack.locked") ?? false; } internal static void Toggle(ItemData item) { if (!item.m_customData.Remove("nathan.quickstack.locked")) { item.m_customData["nathan.quickstack.locked"] = "1"; } } internal static void Unlock(ItemData item) { item.m_customData.Remove("nathan.quickstack.locked"); } } internal sealed class KeyBindingsBridge { private const string LibraryGuid = "nathan.qol.keybindings"; private const int MinimumApiVersion = 1; private readonly object _binding; private readonly Func _ownDown; private readonly Func _ownPressed; private readonly Func _ownUp; private readonly MethodInfo _isDown; private readonly MethodInfo _isPressed; private readonly MethodInfo _isUp; public bool Registered => _binding != null; private KeyBindingsBridge(object binding, Func down, Func pressed, Func up) { _binding = binding; _ownDown = down; _ownPressed = pressed; _ownUp = up; if (binding != null) { Type type = binding.GetType(); _isDown = type.GetMethod("IsDown", Type.EmptyTypes); _isPressed = type.GetMethod("IsPressed", Type.EmptyTypes); _isUp = type.GetMethod("IsUp", Type.EmptyTypes); } } public bool IsDown() { if (_binding == null || !(_isDown != null)) { return _ownDown(); } return (bool)_isDown.Invoke(_binding, null); } public bool IsPressed() { if (_binding == null || !(_isPressed != null)) { return _ownPressed(); } return (bool)_isPressed.Invoke(_binding, null); } public bool IsUp() { if (_binding == null || !(_isUp != null)) { return _ownUp(); } return (bool)_isUp.Invoke(_binding, null); } public static KeyBindingsBridge Register(BaseUnityPlugin plugin, ConfigEntry shortcut, string label, string defaultGamepad = "None") { return new KeyBindingsBridge(TryRegister(plugin, shortcut, label, defaultGamepad), delegate { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Unknown result type (might be due to invalid IL or missing references) KeyboardShortcut value = shortcut.Value; return ((KeyboardShortcut)(ref value)).IsDown(); }, delegate { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Unknown result type (might be due to invalid IL or missing references) KeyboardShortcut value = shortcut.Value; return ((KeyboardShortcut)(ref value)).IsPressed(); }, delegate { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Unknown result type (might be due to invalid IL or missing references) KeyboardShortcut value = shortcut.Value; return ((KeyboardShortcut)(ref value)).IsUp(); }); } public static KeyBindingsBridge Register(BaseUnityPlugin plugin, ConfigEntry key, string label, string defaultGamepad = "None") { return new KeyBindingsBridge(TryRegister(plugin, key, label, defaultGamepad), () => (int)key.Value != 0 && Input.GetKeyDown(key.Value), () => (int)key.Value != 0 && Input.GetKey(key.Value), () => (int)key.Value != 0 && Input.GetKeyUp(key.Value)); } private static object TryRegister(BaseUnityPlugin plugin, object entry, string label, string defaultGamepad) { try { if (!Chainloader.PluginInfos.TryGetValue("nathan.qol.keybindings", out var value) || (Object)(object)value.Instance == (Object)null) { return null; } Assembly assembly = ((object)value.Instance).GetType().Assembly; Type type = assembly.GetType("NathansQol.KeyBindings.KeyBindings"); Type type2 = assembly.GetType("NathansQol.KeyBindings.GamepadButton"); if (type == null || type2 == null) { return null; } FieldInfo field = type.GetField("ApiVersion", BindingFlags.Static | BindingFlags.Public); if (field == null || (int)field.GetRawConstantValue() < 1) { return null; } int num = (int)field.GetRawConstantValue(); string text = defaultGamepad ?? "None"; if (num >= 2) { MethodInfo method = type.GetMethod("Register", new Type[4] { typeof(PluginInfo), entry.GetType(), typeof(string), typeof(string) }); if (method != null) { return method.Invoke(null, new object[4] { plugin.Info, entry, label, text }); } } object obj; try { obj = Enum.Parse(type2, text.Split(new char[1] { '+' })[0].Trim(), ignoreCase: true); } catch (ArgumentException) { obj = Enum.Parse(type2, "None"); } return type.GetMethod("Register", new Type[4] { typeof(PluginInfo), entry.GetType(), typeof(string), type2 })?.Invoke(null, new object[4] { plugin.Info, entry, label, obj }); } catch (Exception ex2) { ManualLogSource val = Logger.CreateLogSource(plugin.Info.Metadata.Name); val.LogWarning((object)("Could not register '" + label + "' with the Key Bindings mod: " + ex2.Message)); Logger.Sources.Remove((ILogSource)(object)val); return null; } } } internal static class LockIcon { private static Sprite _sprite; internal static Sprite Sprite => _sprite ?? (_sprite = Load()); private static Sprite Load() { //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_0044: Expected O, but got Unknown //IL_00bc: Unknown result type (might be due to invalid IL or missing references) //IL_00cb: Unknown result type (might be due to invalid IL or missing references) byte[] array; using (Stream stream = Assembly.GetExecutingAssembly().GetManifestResourceStream("lock.png")) { using MemoryStream memoryStream = new MemoryStream(); stream.CopyTo(memoryStream); array = memoryStream.ToArray(); } Texture2D val = new Texture2D(2, 2, (TextureFormat)4, false); typeof(ImageConversion).GetMethod("LoadImage", new Type[3] { typeof(Texture2D), typeof(byte[]), typeof(bool) }).Invoke(null, new object[3] { val, array, false }); return Sprite.Create(val, new Rect(0f, 0f, (float)((Texture)val).width, (float)((Texture)val).height), new Vector2(0.5f, 0.5f)); } } [HarmonyPatch(typeof(InventoryGrid), "UpdateGui")] internal static class LockOverlayPatch { private const string OverlayName = "QuickStackLock"; private static void Postfix(InventoryGrid __instance) { //IL_004b: Unknown result type (might be due to invalid IL or missing references) //IL_0057: Unknown result type (might be due to invalid IL or missing references) Player localPlayer = Player.m_localPlayer; Inventory inventory = __instance.GetInventory(); if (!QuickStackPlugin.Enabled.Value || (Object)(object)localPlayer == (Object)null || inventory == null) { return; } bool flag = inventory == ((Humanoid)localPlayer).GetInventory(); foreach (InventoryElement element in __instance.m_elements) { ItemData itemAt = inventory.GetItemAt(element.Position.x, element.Position.y); bool flag2 = flag && ItemLock.IsLocked(itemAt); Transform val = ((Component)element).transform.Find("QuickStackLock"); if ((Object)(object)val == (Object)null) { if (!flag2) { continue; } val = CreateOverlay(element); } ((Component)val).gameObject.SetActive(flag2); } } private static Transform CreateOverlay(InventoryElement element) { //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_003c: 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_0047: 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_0049: Unknown result type (might be due to invalid IL or missing references) //IL_005b: Unknown result type (might be due to invalid IL or missing references) //IL_0061: 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_0063: 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_006f: Unknown result type (might be due to invalid IL or missing references) //IL_007a: Unknown result type (might be due to invalid IL or missing references) //IL_008e: Unknown result type (might be due to invalid IL or missing references) //IL_0098: Unknown result type (might be due to invalid IL or missing references) GameObject val = new GameObject("QuickStackLock", new Type[2] { typeof(RectTransform), typeof(Image) }); val.transform.SetParent(((Component)element).transform, false); RectTransform val2 = (RectTransform)val.transform; Vector2 val3 = default(Vector2); ((Vector2)(ref val3))..ctor(1f, 1f); val2.pivot = val3; Vector2 anchorMin = (val2.anchorMax = val3); val2.anchorMin = anchorMin; val2.anchoredPosition = new Vector2(-4f, -4f); val2.sizeDelta = new Vector2(22f, 22f); Image component = val.GetComponent(); component.sprite = LockIcon.Sprite; ((Graphic)component).raycastTarget = false; return val.transform; } } [HarmonyPatch(typeof(Player), "Update")] internal static class QuickStackHotkeyPatch { private static void Postfix(Player __instance) { //IL_0037: Unknown result type (might be due to invalid IL or missing references) if (!QuickStackPlugin.Enabled.Value || (Object)(object)__instance != (Object)(object)Player.m_localPlayer || !((Character)__instance).TakeInput() || !QuickStackPlugin.StackBinding.IsDown()) { return; } List list = ChestFinder.InRange(((Component)__instance).transform.position, QuickStackPlugin.Radius.Value); QuickStackPlugin.Log.LogDebug((object)$"Quick stack: {list.Count} chest(s) in range"); if (list.Count == 0) { ((Character)__instance).Message((MessageType)2, "No chests nearby", 0, (Sprite)null, false); return; } foreach (Container item in list) { if (item.GetInventory() != null) { item.StackAll(); } } } } [HarmonyPatch(typeof(InventoryGui), "OnSelectedItem")] internal static class LockToggleClickPatch { private static bool Prefix(InventoryGui __instance, InventoryGrid grid, ItemData item) { if (!QuickStackPlugin.Enabled.Value) { return true; } if (item == null) { return true; } if ((Object)(object)grid != (Object)(object)__instance.m_playerGrid) { return true; } if ((Object)(object)__instance.m_dragGo != (Object)null) { return true; } if (!QuickStackPlugin.LockBinding.IsPressed() && !QuickStackPlugin.LockBinding.IsUp()) { return true; } ItemLock.Toggle(item); string text = (ItemLock.IsLocked(item) ? "locked" : "unlocked"); string text2 = Localization.instance.Localize(item.m_shared.m_name); ((Character)Player.m_localPlayer).Message((MessageType)1, text2 + " " + text, 0, (Sprite)null, false); return false; } } [HarmonyPatch(typeof(Inventory), "StackAll")] internal static class StackAllScopePatch { internal static bool Active; private static void Prefix() { Active = true; } private static void Finalizer() { Active = false; } } [HarmonyPatch(typeof(Humanoid), "IsItemEquiped")] internal static class LockedLooksEquippedPatch { private static void Postfix(ItemData item, ref bool __result) { if (StackAllScopePatch.Active && ItemLock.IsLocked(item)) { __result = true; } } } [HarmonyPatch(typeof(Inventory), "Changed")] internal static class ClearLocksOutsidePlayerPatch { private static void Postfix(Inventory __instance) { Player localPlayer = Player.m_localPlayer; if (!QuickStackPlugin.Enabled.Value || (Object)(object)localPlayer == (Object)null || __instance == ((Humanoid)localPlayer).GetInventory()) { return; } foreach (ItemData allItem in __instance.GetAllItems()) { ItemLock.Unlock(allItem); } } } [BepInPlugin("nathan.qol.quickstack", "Nathans Quick Stack", "0.2.2")] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] [NetworkCompatibility(/*Could not decode attribute arguments.*/)] public class QuickStackPlugin : BaseUnityPlugin { public const string PluginGuid = "nathan.qol.quickstack"; public const string PluginName = "Nathans Quick Stack"; public const string PluginVersion = "0.2.2"; internal static ManualLogSource Log; internal static ConfigEntry Enabled; internal static ConfigEntry StackKey; internal static KeyBindingsBridge StackBinding; internal static ConfigEntry Radius; internal static ConfigEntry LockShortcut; internal static KeyBindingsBridge LockBinding; private void Awake() { //IL_004b: Unknown result type (might be due to invalid IL or missing references) //IL_008d: Unknown result type (might be due to invalid IL or missing references) //IL_0097: Expected O, but got Unknown //IL_00bf: Unknown result type (might be due to invalid IL or missing references) //IL_010c: Unknown result type (might be due to invalid IL or missing references) Log = ((BaseUnityPlugin)this).Logger; Enabled = ((BaseUnityPlugin)this).Config.Bind("General", "Enabled", true, "Turns the mod on or off (quick stack, item locks and the padlock icons). Takes effect immediately."); StackKey = ((BaseUnityPlugin)this).Config.Bind("Hotkeys", "StackKey", new KeyboardShortcut((KeyCode)103, (KeyCode[])(object)new KeyCode[1] { (KeyCode)306 }), "Quick stack your inventory into the chests nearby."); Radius = ((BaseUnityPlugin)this).Config.Bind("General", "Radius", 10f, new ConfigDescription("How far away (in meters) chests are used.", (AcceptableValueBase)(object)new AcceptableValueRange(1f, 50f), Array.Empty())); LockShortcut = ((BaseUnityPlugin)this).Config.Bind("Hotkeys", "LockShortcut", new KeyboardShortcut((KeyCode)323, (KeyCode[])(object)new KeyCode[1] { (KeyCode)308 }), "Click an item in your inventory with this shortcut to lock or unlock it (default: Alt + left mouse button)."); StackBinding = KeyBindingsBridge.Register((BaseUnityPlugin)(object)this, StackKey, "Quick stack into nearby chests"); LockBinding = KeyBindingsBridge.Register((BaseUnityPlugin)(object)this, LockShortcut, "Lock or unlock an item (click it)"); new Harmony("nathan.qol.quickstack").PatchAll(); Log.LogInfo((object)"Nathans Quick Stack 0.2.2 loaded"); } } } namespace System.Runtime.CompilerServices { [AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)] internal sealed class IgnoresAccessChecksToAttribute : Attribute { public IgnoresAccessChecksToAttribute(string assemblyName) { } } }