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.Configuration; using BepInEx.Logging; using HarmonyLib; using Microsoft.CodeAnalysis; using UnityEngine; using UnityEngine.UI; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: IgnoresAccessChecksTo("assembly_utils")] [assembly: IgnoresAccessChecksTo("assembly_valheim")] [assembly: TargetFramework(".NETFramework,Version=v4.6.2", FrameworkDisplayName = ".NET Framework 4.6.2")] [assembly: AssemblyCompany("Dasone")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyDescription("Toggle between your last two used Valheim hotbar slots, plus an anchored slot.")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0+db043d4a5a648c4f192033f938864fb47e77e722")] [assembly: AssemblyProduct("Quick Swap")] [assembly: AssemblyTitle("QuickSwap")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.0.0.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; } } } [AttributeUsage(AttributeTargets.All)] public sealed class ConfigurationManagerAttributes : Attribute { public int? Order; } namespace QuickSwap { internal static class AnchorMarker { private const string MarkerName = "QuickSwapAnchorMarker"; private const float BadgeWidth = 24f; private const float BadgeHeight = 17f; private const float BadgeMargin = 1f; private const string ArrowsName = "Arrows"; private static readonly List Markers = new List(); internal static void Apply(HotkeyBar bar) { //IL_0030: 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_005a: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)bar == (Object)null || bar.m_elements == null || bar.m_elements.Count == 0) { return; } int num = (IsMainHotbar(bar) ? AnchorIndex() : (-1)); Color colour = ModConfig.MarkerColor(); for (int i = 0; i < bar.m_elements.Count; i++) { GameObject go = bar.m_elements[i].m_go; if ((Object)(object)go != (Object)null) { Mark(go, i == num, colour); } } } internal static void Apply(InventoryGrid grid) { //IL_0036: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_008d: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)grid == (Object)null || grid.m_elements == null) { return; } InventoryGui instance = InventoryGui.instance; if ((Object)(object)instance == (Object)null || (Object)(object)instance.m_playerGrid != (Object)(object)grid) { return; } int num = AnchorIndex(); Color colour = ModConfig.MarkerColor(); foreach (Element element in grid.m_elements) { if (element != null && !((Object)(object)element.m_go == (Object)null)) { Mark(element.m_go, element.m_pos.y == 0 && element.m_pos.x == num, colour); } } } internal static void RemoveAll() { foreach (GameObject marker in Markers) { if ((Object)(object)marker != (Object)null) { Object.Destroy((Object)(object)marker); } } Markers.Clear(); } private static int AnchorIndex() { if (!ModConfig.ShowAnchorMarker.Value) { return -1; } return ModConfig.AnchorSlot.Value - 1; } private static void Mark(GameObject host, bool wanted, Color colour) { //IL_005b: 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_0069: Unknown result type (might be due to invalid IL or missing references) GameObject val = FindMarker(host); if ((Object)(object)val == (Object)null) { if (!wanted) { return; } val = CreateMarker(host); } if (val.activeSelf != wanted) { val.SetActive(wanted); } if (!wanted) { return; } Transform val2 = val.transform.Find("Arrows"); if (!((Object)(object)val2 == (Object)null)) { Image component = ((Component)val2).GetComponent(); if ((Object)(object)component != (Object)null && ((Graphic)component).color != colour) { ((Graphic)component).color = colour; } } } private static bool IsMainHotbar(HotkeyBar bar) { List items = bar.m_items; if (items == null || items.Count == 0) { return false; } for (int i = 0; i < items.Count; i++) { if (items[i] == null || items[i].m_gridPos.y != 0) { return false; } } return true; } private static GameObject FindMarker(GameObject host) { Transform val = host.transform.Find("QuickSwapAnchorMarker"); if (!((Object)(object)val == (Object)null)) { return ((Component)val).gameObject; } return null; } private static GameObject CreateMarker(GameObject host) { //IL_005c: Unknown result type (might be due to invalid IL or missing references) //IL_0062: Expected O, but got Unknown //IL_0068: Unknown result type (might be due to invalid IL or missing references) //IL_006e: Expected O, but got Unknown //IL_0086: Unknown result type (might be due to invalid IL or missing references) //IL_009b: Unknown result type (might be due to invalid IL or missing references) //IL_00b0: Unknown result type (might be due to invalid IL or missing references) //IL_00c5: Unknown result type (might be due to invalid IL or missing references) //IL_00da: Unknown result type (might be due to invalid IL or missing references) //IL_0100: Unknown result type (might be due to invalid IL or missing references) //IL_0143: Unknown result type (might be due to invalid IL or missing references) //IL_0149: Expected O, but got Unknown //IL_014f: Unknown result type (might be due to invalid IL or missing references) //IL_0156: Expected O, but got Unknown //IL_0161: Unknown result type (might be due to invalid IL or missing references) //IL_016d: Unknown result type (might be due to invalid IL or missing references) //IL_0183: Unknown result type (might be due to invalid IL or missing references) //IL_0199: Unknown result type (might be due to invalid IL or missing references) //IL_01c9: Unknown result type (might be due to invalid IL or missing references) Markers.RemoveAll((GameObject marker) => (Object)(object)marker == (Object)null); GameObject val = new GameObject("QuickSwapAnchorMarker", new Type[3] { typeof(RectTransform), typeof(CanvasRenderer), typeof(Image) }); RectTransform val2 = (RectTransform)val.transform; ((Transform)val2).SetParent(host.transform, false); val2.anchorMin = new Vector2(1f, 0f); val2.anchorMax = new Vector2(1f, 0f); val2.pivot = new Vector2(1f, 0f); val2.sizeDelta = new Vector2(24f, 17f); val2.anchoredPosition = new Vector2(-1f, 1f); Image component = val.GetComponent(); ((Graphic)component).color = new Color(0f, 0f, 0f, 0.72f); ((Graphic)component).raycastTarget = false; GameObject val3 = new GameObject("Arrows", new Type[3] { typeof(RectTransform), typeof(CanvasRenderer), typeof(Image) }); RectTransform val4 = (RectTransform)val3.transform; ((Transform)val4).SetParent((Transform)(object)val2, false); val4.anchorMin = Vector2.zero; val4.anchorMax = Vector2.one; val4.offsetMin = new Vector2(2f, 2f); val4.offsetMax = new Vector2(-2f, -2f); Image component2 = val3.GetComponent(); component2.sprite = MarkerSprite.Get(); component2.preserveAspect = true; ((Graphic)component2).raycastTarget = false; ((Graphic)component2).color = ModConfig.MarkerColor(); ((Transform)val2).SetAsLastSibling(); Markers.Add(val); return val; } } internal static class GameGuards { internal static bool AcceptsGameplayInput(Player player) { if ((Object)(object)player == (Object)null || !((Character)player).TakeInput()) { return false; } if (Hud.IsPieceSelectionVisible() || Hud.InRadial()) { return false; } return true; } } internal static class MarkerSprite { private const string ResourceName = "QuickSwap.anchor-arrows.png"; private static Sprite _sprite; private static Texture2D _texture; private static bool _failed; internal static Sprite Get() { //IL_003e: 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_0056: Expected O, but got Unknown //IL_00af: Unknown result type (might be due to invalid IL or missing references) //IL_00be: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_sprite != (Object)null || _failed) { return _sprite; } byte[] array = ReadResource(); if (array == null) { _failed = true; QuickSwapPlugin.Log.LogError((object)"Embedded resource 'QuickSwap.anchor-arrows.png' is missing; the anchored slot will show a plain marker."); return null; } _texture = new Texture2D(2, 2, (TextureFormat)4, false) { filterMode = (FilterMode)1, wrapMode = (TextureWrapMode)1 }; if (!LoadImage(_texture, array)) { Object.Destroy((Object)(object)_texture); _texture = null; _failed = true; QuickSwapPlugin.Log.LogError((object)"Could not decode 'QuickSwap.anchor-arrows.png'."); return null; } _sprite = Sprite.Create(_texture, new Rect(0f, 0f, (float)((Texture)_texture).width, (float)((Texture)_texture).height), new Vector2(0.5f, 0.5f)); return _sprite; } internal static void Unload() { if ((Object)(object)_sprite != (Object)null) { Object.Destroy((Object)(object)_sprite); } if ((Object)(object)_texture != (Object)null) { Object.Destroy((Object)(object)_texture); } _sprite = null; _texture = null; _failed = false; } private static bool LoadImage(Texture2D texture, byte[] bytes) { MethodInfo method = typeof(ImageConversion).GetMethod("LoadImage", BindingFlags.Static | BindingFlags.Public, null, new Type[2] { typeof(Texture2D), typeof(byte[]) }, null); if (method == null) { QuickSwapPlugin.Log.LogError((object)"ImageConversion.LoadImage(Texture2D, byte[]) not found."); return false; } return (bool)method.Invoke(null, new object[2] { texture, bytes }); } private static byte[] ReadResource() { Assembly assembly = typeof(MarkerSprite).Assembly; using Stream stream = assembly.GetManifestResourceStream("QuickSwap.anchor-arrows.png"); if (stream == null) { return null; } using MemoryStream memoryStream = new MemoryStream(); stream.CopyTo(memoryStream); return memoryStream.ToArray(); } } internal static class ModConfig { internal static ConfigEntry Enabled; internal static ConfigEntry QuickSwapKey; internal static ConfigEntry AnchorSwapKey; internal static ConfigEntry SetAnchorBind; internal static ConfigEntry AnchorSlot; internal static ConfigEntry ShowAnchorMarker; internal static ConfigEntry AnchorMarkerColor; internal static ConfigEntry OnlyTrackEquipment; internal static ConfigEntry ShowMessages; private const string DefaultMarkerColour = "#FFD24AF2"; private static Color _cachedColour; private static string _cachedColourText; internal static void Init(ConfigFile config) { //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Expected O, but got Unknown //IL_004e: 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_007e: Expected O, but got Unknown //IL_009e: 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_00ce: Expected O, but got Unknown //IL_00ee: Unknown result type (might be due to invalid IL or missing references) //IL_0114: Unknown result type (might be due to invalid IL or missing references) //IL_011e: Expected O, but got Unknown //IL_0156: Unknown result type (might be due to invalid IL or missing references) //IL_0160: Expected O, but got Unknown //IL_0192: Unknown result type (might be due to invalid IL or missing references) //IL_019c: Expected O, but got Unknown //IL_01d2: Unknown result type (might be due to invalid IL or missing references) //IL_01dc: Expected O, but got Unknown //IL_020e: Unknown result type (might be due to invalid IL or missing references) //IL_0218: Expected O, but got Unknown //IL_024a: Unknown result type (might be due to invalid IL or missing references) //IL_0254: Expected O, but got Unknown Enabled = config.Bind("1 - General", "Enabled", true, new ConfigDescription("Master switch. Turn off to disable all Quick Swap hotkeys without uninstalling.", (AcceptableValueBase)null, new object[1] { new ConfigurationManagerAttributes { Order = 100 } })); QuickSwapKey = config.Bind("2 - Keys", "Quick swap key", new KeyboardShortcut((KeyCode)113, Array.Empty()), new ConfigDescription("Your main swap key. Toggles between the last two hotbar slots you used - and, unless you give the anchor its own key below, between the anchor and the last other slot whenever a slot is anchored.", (AcceptableValueBase)null, new object[1] { new ConfigurationManagerAttributes { Order = 90 } })); AnchorSwapKey = config.Bind("2 - Keys", "Anchor swap key", new KeyboardShortcut((KeyCode)113, (KeyCode[])(object)new KeyCode[1] { (KeyCode)308 }), new ConfigDescription("Swaps to the anchored slot and back. Leave this unbound and the quick swap key handles the anchor instead; bind it and it takes the anchor over completely, leaving the quick swap key on plain last-two-slots swapping. Defaults to the same combination as the set anchor bind, which is not a clash: that one only does anything while the inventory is open, this one only while it is closed.", (AcceptableValueBase)null, new object[1] { new ConfigurationManagerAttributes { Order = 80 } })); SetAnchorBind = config.Bind("2 - Keys", "Set anchor bind", new KeyboardShortcut((KeyCode)113, (KeyCode[])(object)new KeyCode[1] { (KeyCode)308 }), new ConfigDescription("Press this while hovering a top-row hotbar slot in the open inventory to anchor it. Press it on the anchored slot again to clear the anchor. Only does anything while the inventory is open, so it can safely share a combination with the anchor swap key.", (AcceptableValueBase)null, new object[1] { new ConfigurationManagerAttributes { Order = 70 } })); AnchorSlot = config.Bind("3 - Anchor", "Anchored slot", 0, new ConfigDescription("Hotbar slot the anchor keys use. 0 means no anchor set. Usually set in-game with the set anchor bind rather than here.", (AcceptableValueBase)(object)new AcceptableValueRange(0, 8), new object[1] { new ConfigurationManagerAttributes { Order = 60 } })); ShowAnchorMarker = config.Bind("3 - Anchor", "Show anchor marker", true, new ConfigDescription("Show the swap-arrows badge on the anchored slot, both on the on-screen hotbar and in the top row of the open inventory.", (AcceptableValueBase)null, new object[1] { new ConfigurationManagerAttributes { Order = 50 } })); AnchorMarkerColor = config.Bind("3 - Anchor", "Marker colour", "#FFD24AF2", new ConfigDescription("Colour of the badge arrows, as #RRGGBB or #RRGGBBAA.", (AcceptableValueBase)null, new object[1] { new ConfigurationManagerAttributes { Order = 40 } })); OnlyTrackEquipment = config.Bind("4 - Behaviour", "Only remember equipment", true, new ConfigDescription("When on, using a consumable (food, mead, arrows) does not overwrite your swap history, so the swap key keeps toggling between your actual tools and weapons.", (AcceptableValueBase)null, new object[1] { new ConfigurationManagerAttributes { Order = 30 } })); ShowMessages = config.Bind("4 - Behaviour", "Show HUD messages", true, new ConfigDescription("Show a short message in the top-left corner when the anchored slot changes.", (AcceptableValueBase)null, new object[1] { new ConfigurationManagerAttributes { Order = 20 } })); } internal unsafe static bool HasDedicatedAnchorKey() { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_000a: 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) //IL_001c: Unknown result type (might be due to invalid IL or missing references) KeyboardShortcut value = AnchorSwapKey.Value; if (!value.IsBound()) { return false; } return !((object)(*(KeyboardShortcut*)(&value))/*cast due to .constrained prefix*/).Equals((object?)QuickSwapKey.Value); } internal static Color MarkerColor() { //IL_0018: 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) string value = AnchorMarkerColor.Value; if (value == _cachedColourText) { return _cachedColour; } _cachedColourText = value; if (string.IsNullOrEmpty(value) || !ColorUtility.TryParseHtmlString(value, ref _cachedColour)) { ColorUtility.TryParseHtmlString("#FFD24AF2", ref _cachedColour); } return _cachedColour; } } internal static class Notifier { internal static void Show(string text) { if (ModConfig.ShowMessages.Value && !string.IsNullOrEmpty(text)) { MessageHud instance = MessageHud.instance; if ((Object)(object)instance != (Object)null) { instance.ShowMessage((MessageType)1, text, 0, (Sprite)null, false); } } } } [BepInPlugin("dev.samspel.quickswap", "Quick Swap", "1.0.0")] [BepInProcess("valheim.exe")] public class QuickSwapPlugin : BaseUnityPlugin { public const string ModGuid = "dev.samspel.quickswap"; public const string ModName = "Quick Swap"; public const string ModVersion = "1.0.0"; internal static ManualLogSource Log; private Harmony _harmony; private Player _lastLocalPlayer; private void Awake() { //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Expected O, but got Unknown Log = ((BaseUnityPlugin)this).Logger; ModConfig.Init(((BaseUnityPlugin)this).Config); _harmony = new Harmony("dev.samspel.quickswap"); _harmony.PatchAll(typeof(QuickSwapPlugin).Assembly); Log.LogInfo((object)"Quick Swap 1.0.0 loaded (Release build, 2026-09-05 11:01:08)."); LogBindings(); } private void OnDestroy() { AnchorMarker.RemoveAll(); MarkerSprite.Unload(); Harmony harmony = _harmony; if (harmony != null) { harmony.UnpatchSelf(); } Log.LogInfo((object)"Quick Swap unloaded."); } private void Update() { //IL_0042: Unknown result type (might be due to invalid IL or missing references) Player localPlayer = Player.m_localPlayer; if ((Object)(object)localPlayer != (Object)(object)_lastLocalPlayer) { _lastLocalPlayer = localPlayer; SwapController.Reset(); } if ((Object)(object)localPlayer == (Object)null || !ModConfig.Enabled.Value) { return; } if (InventoryGui.IsVisible()) { if (ModConfig.SetAnchorBind.Value.Triggered()) { TrySetAnchorUnderCursor(); } } else if (GameGuards.AcceptsGameplayInput(localPlayer)) { HandleSwapKeys(); } } private static void HandleSwapKeys() { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_001d: 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_0030: Unknown result type (might be due to invalid IL or missing references) KeyboardShortcut value = ModConfig.QuickSwapKey.Value; KeyboardShortcut value2 = ModConfig.AnchorSwapKey.Value; bool flag = value.Triggered(); if (value2.Triggered() && (!flag || value2.ModifierCount() > value.ModifierCount())) { SwapController.AnchorSwap(); } else if (flag) { SwapController.QuickSwap(); } } private static void LogBindings() { //IL_001b: 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_004f: Unknown result type (might be due to invalid IL or missing references) //IL_008f: Unknown result type (might be due to invalid IL or missing references) //IL_00d8: Unknown result type (might be due to invalid IL or missing references) //IL_00a0: Unknown result type (might be due to invalid IL or missing references) //IL_00a5: Unknown result type (might be due to invalid IL or missing references) //IL_00ad: Unknown result type (might be due to invalid IL or missing references) //IL_00e9: Unknown result type (might be due to invalid IL or missing references) //IL_00fa: Unknown result type (might be due to invalid IL or missing references) Log.LogInfo((object)("Binds - quick swap: " + Describe(ModConfig.QuickSwapKey.Value) + " | anchor swap: " + Describe(ModConfig.AnchorSwapKey.Value) + " | set anchor: " + Describe(ModConfig.SetAnchorBind.Value) + " | anchor handled by the " + (ModConfig.HasDedicatedAnchorKey() ? "anchor swap" : "quick swap") + " key")); if (ModConfig.AnchorSwapKey.Value.IsBound() && ((object)ModConfig.AnchorSwapKey.Value/*cast due to .constrained prefix*/).Equals((object?)ModConfig.QuickSwapKey.Value)) { Log.LogWarning((object)"Quick swap and anchor swap are bound to the same key, so only quick swap fires. Give the anchor its own key, or leave it unbound and quick swap will handle it."); } if (!ModConfig.QuickSwapKey.Value.IsBound() && !ModConfig.AnchorSwapKey.Value.IsBound() && !ModConfig.SetAnchorBind.Value.IsBound()) { Log.LogWarning((object)"No keys are bound, so nothing will happen yet. Bind them under F1 -> Quick Swap."); } } private unsafe static string Describe(KeyboardShortcut shortcut) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) if (!shortcut.IsBound()) { return "unbound"; } return ((object)(*(KeyboardShortcut*)(&shortcut))/*cast due to .constrained prefix*/).ToString(); } private static void TrySetAnchorUnderCursor() { //IL_002f: 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_0035: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Unknown result type (might be due to invalid IL or missing references) InventoryGui instance = InventoryGui.instance; if ((Object)(object)instance == (Object)null || (Object)(object)instance.m_playerGrid == (Object)null) { return; } Element hoveredElement = instance.m_playerGrid.GetHoveredElement(); if (hoveredElement == null) { return; } Vector2i pos = hoveredElement.m_pos; if (pos.y == 0) { int num = pos.x + 1; if (ModConfig.AnchorSlot.Value == num) { ModConfig.AnchorSlot.Value = 0; Notifier.Show("Quick Swap: anchor cleared"); Log.LogInfo((object)"Anchor cleared."); } else { ModConfig.AnchorSlot.Value = num; Notifier.Show("Quick Swap: anchored to slot " + num); Log.LogInfo((object)("Anchored to slot " + num + ".")); } } } } internal static class Shortcuts { internal static bool Triggered(this KeyboardShortcut shortcut) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Unknown result type (might be due to invalid IL or missing references) if (!shortcut.IsBound() || !Input.GetKeyDown(((KeyboardShortcut)(ref shortcut)).MainKey)) { return false; } foreach (KeyCode modifier in ((KeyboardShortcut)(ref shortcut)).Modifiers) { if (!ModifierHeld(modifier)) { return false; } } return true; } internal static bool IsBound(this KeyboardShortcut shortcut) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Invalid comparison between Unknown and I4 return (int)((KeyboardShortcut)(ref shortcut)).MainKey > 0; } internal static int ModifierCount(this KeyboardShortcut shortcut) { //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Unknown result type (might be due to invalid IL or missing references) int num = 0; foreach (KeyCode modifier in ((KeyboardShortcut)(ref shortcut)).Modifiers) { num++; } return num; } private static bool ModifierHeld(KeyCode modifier) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Expected I4, but got Unknown if (Input.GetKey(modifier)) { return true; } return (modifier - 303) switch { 1 => Input.GetKey((KeyCode)303), 0 => Input.GetKey((KeyCode)304), 3 => Input.GetKey((KeyCode)305), 2 => Input.GetKey((KeyCode)306), 5 => Input.GetKey((KeyCode)307), 4 => Input.GetKey((KeyCode)308), _ => false, }; } } internal static class SwapController { internal static int Current { get; private set; } internal static int Previous { get; private set; } internal static void Reset() { Current = 0; Previous = 0; } internal static void Record(int slot) { if (slot > 0 && slot != Current) { Previous = Current; Current = slot; } } internal static void QuickSwap() { Player localPlayer = Player.m_localPlayer; if (!((Object)(object)localPlayer == (Object)null)) { SeedFromEquipped(localPlayer); int value = ModConfig.AnchorSlot.Value; if (value > 0 && !ModConfig.HasDedicatedAnchorKey()) { SwapAgainst(value); } else { Activate(Previous); } } } internal static void AnchorSwap() { Player localPlayer = Player.m_localPlayer; if (!((Object)(object)localPlayer == (Object)null)) { SeedFromEquipped(localPlayer); int value = ModConfig.AnchorSlot.Value; if (value <= 0) { Notifier.Show("Quick Swap: no anchored slot. Use the set anchor bind on a hotbar slot in your inventory."); } else { SwapAgainst(value); } } } private static void SwapAgainst(int anchor) { if (Current != anchor) { Activate(anchor); } else if (Previous <= 0) { Notifier.Show("Quick Swap: no other slot used yet to swap back to."); } else { Activate(Previous); } } private static void SeedFromEquipped(Player player) { if (Current > 0) { return; } Inventory inventory = ((Humanoid)player).GetInventory(); if (inventory == null) { return; } int width = inventory.GetWidth(); for (int i = 0; i < width; i++) { ItemData itemAt = inventory.GetItemAt(i, 0); if (itemAt != null && itemAt.m_equipped) { Current = i + 1; break; } } } private static void Activate(int slot) { Player localPlayer = Player.m_localPlayer; if (!((Object)(object)localPlayer == (Object)null) && slot > 0) { Inventory inventory = ((Humanoid)localPlayer).GetInventory(); if (inventory != null && slot <= inventory.GetWidth() && inventory.GetItemAt(slot - 1, 0) != null) { localPlayer.UseHotbarItem(slot); } } } } internal static class BuildInfo { internal const string BuildTime = "2026-09-05 11:01:08"; internal const string Configuration = "Release"; } } namespace QuickSwap.Patches { [HarmonyPatch(typeof(HotkeyBar), "UpdateIcons")] internal static class HotkeyBar_UpdateIcons_Patch { private static void Postfix(HotkeyBar __instance) { AnchorMarker.Apply(__instance); } } [HarmonyPatch(typeof(InventoryGrid), "UpdateGui")] internal static class InventoryGrid_UpdateGui_Patch { private static void Postfix(InventoryGrid __instance) { AnchorMarker.Apply(__instance); } } [HarmonyPatch(typeof(Player), "UseHotbarItem")] internal static class Player_UseHotbarItem_Patch { private static void Prefix(Player __instance, int index, out bool __state) { __state = false; if ((Object)(object)__instance == (Object)null || (Object)(object)__instance != (Object)(object)Player.m_localPlayer) { return; } Inventory inventory = ((Humanoid)__instance).GetInventory(); if (inventory != null) { ItemData itemAt = inventory.GetItemAt(index - 1, 0); if (itemAt != null && (!ModConfig.OnlyTrackEquipment.Value || itemAt.IsEquipable())) { __state = true; } } } private static void Postfix(int index, bool __state) { if (__state) { SwapController.Record(index); } } } } namespace System.Runtime.CompilerServices { [AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)] internal sealed class IgnoresAccessChecksToAttribute : Attribute { public IgnoresAccessChecksToAttribute(string assemblyName) { } } }