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 System.Text; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; using Microsoft.CodeAnalysis; using Pigeon; using Pigeon.Movement; using Sparroh.UI; using TMPro; using UnityEngine; using UnityEngine.EventSystems; using UnityEngine.Events; using UnityEngine.InputSystem; using UnityEngine.UI; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: AssemblyCompany("Sparroh")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.0.6.0")] [assembly: AssemblyInformationalVersion("1.0.6")] [assembly: AssemblyProduct("ConsumableHotkeys")] [assembly: AssemblyTitle("ConsumableHotkeys")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.0.6.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; } } } public static class ConfigManager { private const float DebounceSeconds = 0.25f; private static ConfigFile config; private static ManualLogSource logger; private static FileSystemWatcher configWatcher; private static volatile bool pendingRefresh; private static volatile bool reloadPending; private static float lastReloadTime; public static ConfigEntry EnableHotkeys { get; private set; } public static ConfigEntry EnableHUD { get; private set; } public static ConfigEntry PersonalAccessTokenHotkey { get; private set; } public static ConfigEntry PremiumLootLicenseHotkey { get; private set; } public static ConfigEntry BootlegReplicatorHotkey { get; private set; } public static ConfigEntry ClearanceCertificateHotkey { get; private set; } public static HudAnchors Anchors { get; private set; } public static ConfigColor ActiveColor { get; private set; } public static ConfigColor InactiveColor { get; private set; } public static void Initialize(ConfigFile configFile, ManualLogSource log) { //IL_00fc: Unknown result type (might be due to invalid IL or missing references) //IL_011f: Unknown result type (might be due to invalid IL or missing references) config = configFile; logger = log; EnableHotkeys = config.Bind("Consumables", "Enable Hotkeys", true, "Enables hotkey functionality for consumables."); EnableHUD = config.Bind("Consumables", "Enable HUD", true, "Enables the HUD display for consumable statuses."); PersonalAccessTokenHotkey = config.Bind("Consumables", "PersonalAccessToken Key", (Key)22, "Hotkey for Personal Access Token."); PremiumLootLicenseHotkey = config.Bind("Consumables", "PremiumLootLicense Key", (Key)24, "Hotkey for Premium Loot License."); BootlegReplicatorHotkey = config.Bind("Consumables", "BootlegReplicator Key", (Key)25, "Hotkey for Bootleg Replicator."); ClearanceCertificateHotkey = config.Bind("Consumables", "ClearanceCertificate Key", (Key)26, "Hotkey for Clearance Certificate."); Anchors = HudAnchors.Bind(config, "HUD", 0.2561931f, 0.9362161f, "HUD Positioning"); ActiveColor = ConfigColor.Bind(config, "Colors", "Active Color", UIColors.Shamrock, "Rich-text color for active consumables (hex RRGGBB or #RRGGBB)."); InactiveColor = ConfigColor.Bind(config, "Colors", "Inactive Color", UIColors.Rose, "Rich-text color for inactive consumables (hex RRGGBB or #RRGGBB)."); EnableHotkeys.SettingChanged += OnSettingChanged; EnableHUD.SettingChanged += OnSettingChanged; PersonalAccessTokenHotkey.SettingChanged += OnSettingChanged; PremiumLootLicenseHotkey.SettingChanged += OnSettingChanged; BootlegReplicatorHotkey.SettingChanged += OnSettingChanged; ClearanceCertificateHotkey.SettingChanged += OnSettingChanged; ActiveColor.Entry.SettingChanged += OnSettingChanged; InactiveColor.Entry.SettingChanged += OnSettingChanged; try { SetupFileWatcher(); } catch (Exception ex) { logger.LogError((object)("Error setting up config file watcher: " + ex.Message)); } } public static void Tick() { if (!reloadPending || Time.unscaledTime - lastReloadTime < 0.25f) { return; } reloadPending = false; lastReloadTime = Time.unscaledTime; try { config.Reload(); pendingRefresh = true; logger.LogInfo((object)"Config reloaded from disk."); } catch (Exception ex) { logger.LogError((object)("Error reloading config: " + ex.Message)); } } public static bool ConsumePendingRefresh() { if (!pendingRefresh) { return false; } pendingRefresh = false; return true; } public static void Dispose() { if (EnableHotkeys != null) { EnableHotkeys.SettingChanged -= OnSettingChanged; } if (EnableHUD != null) { EnableHUD.SettingChanged -= OnSettingChanged; } if (PersonalAccessTokenHotkey != null) { PersonalAccessTokenHotkey.SettingChanged -= OnSettingChanged; } if (PremiumLootLicenseHotkey != null) { PremiumLootLicenseHotkey.SettingChanged -= OnSettingChanged; } if (BootlegReplicatorHotkey != null) { BootlegReplicatorHotkey.SettingChanged -= OnSettingChanged; } if (ClearanceCertificateHotkey != null) { ClearanceCertificateHotkey.SettingChanged -= OnSettingChanged; } try { ConfigColor activeColor = ActiveColor; if (((activeColor != null) ? activeColor.Entry : null) != null) { ActiveColor.Entry.SettingChanged -= OnSettingChanged; } ConfigColor inactiveColor = InactiveColor; if (((inactiveColor != null) ? inactiveColor.Entry : null) != null) { InactiveColor.Entry.SettingChanged -= OnSettingChanged; } } catch { } if (configWatcher != null) { configWatcher.EnableRaisingEvents = false; configWatcher.Changed -= OnConfigFileChanged; configWatcher.Created -= OnConfigFileChanged; configWatcher.Renamed -= OnConfigFileChanged; configWatcher.Dispose(); configWatcher = null; } } private static void SetupFileWatcher() { configWatcher = new FileSystemWatcher(Paths.ConfigPath, "sparroh.consumablehotkeys.cfg"); configWatcher.NotifyFilter = NotifyFilters.FileName | NotifyFilters.Size | NotifyFilters.LastWrite; configWatcher.Changed += OnConfigFileChanged; configWatcher.Created += OnConfigFileChanged; configWatcher.Renamed += OnConfigFileChanged; configWatcher.EnableRaisingEvents = true; } private static void OnConfigFileChanged(object sender, FileSystemEventArgs e) { reloadPending = true; } private static void OnSettingChanged(object sender, EventArgs e) { pendingRefresh = true; } } public class ConsumableHotkeysMod { private class ConsumableStatus { public bool IsActive { get; set; } public int UsesRemaining { get; set; } = -1; public int MaxUses { get; set; } = -1; } private const string PersonalAccessTokenName = "Personal Access Token"; private const string PremiumLootLicenseName = "Premium Loot License"; private const string BootlegReplicatorName = "Bootleg Replicator"; private const string ClearanceCertificateName = "Clearance Certificate"; private const int ClearanceCertificateMaxUses = 5; private const float HudPollIntervalSeconds = 0.25f; private static FieldInfo _storageSlotsField; private static FieldInfo _slotItemField; private static FieldInfo _onPrimaryActionField; private static bool _reflectionResolved; private readonly Dictionary consumableStatuses; private readonly Dictionary resourceCache = new Dictionary(); private readonly string[] lastLineTexts = new string[4]; private HudHandle hud; private float nextHudPollTime; private bool hudRefreshRequested = true; private bool resourceCacheBuilt; private int lastHudStateHash; private bool hasHudStateHash; private InputActionMap controls; private InputAction patAction; private InputAction pllAction; private InputAction replicatorAction; private InputAction clearanceAction; private Action patPerformed; private Action pllPerformed; private Action replicatorPerformed; private Action clearancePerformed; public static ConsumableHotkeysMod Instance { get; private set; } private bool IsHudAlive { get { if (HudHandle.IsValid(hud) && hud.Lines != null) { return hud.Lines.Length >= 4; } return false; } } public ConsumableHotkeysMod() { Instance = this; try { consumableStatuses = new Dictionary { { "Personal Access Token", new ConsumableStatus() }, { "Premium Loot License", new ConsumableStatus() }, { "Bootleg Replicator", new ConsumableStatus() }, { "Clearance Certificate", new ConsumableStatus { MaxUses = 5, UsesRemaining = 5 } } }; SetupHotkeyActions(); } catch (Exception ex) { SparrohPlugin.Logger.LogError((object)("Failed to initialize ConsumableHotkeys: " + ex.Message)); } } public void OnConfigChanged() { if (!ConfigManager.EnableHUD.Value && HudHandle.IsValid(hud)) { DestroyHud(); } InvalidateHudTextCache(); hudRefreshRequested = true; UpdateHudVisibility(); RefreshHotkeyActions(); } public void RequestHudRefresh() { hudRefreshRequested = true; } public void UpdateHudVisibility() { if (!IsHudAlive) { ClearDestroyedHud(); } else { hud.SetActive(ConfigManager.EnableHUD.Value); } } private void InvalidateHudTextCache() { for (int i = 0; i < lastLineTexts.Length; i++) { lastLineTexts[i] = null; } hasHudStateHash = false; } private void ClearDestroyedHud() { if (hud != null) { hud = null; InvalidateHudTextCache(); } } private void DestroyHud() { if (hud != null) { if (hud.IsAlive) { hud.Destroy(); } hud = null; } InvalidateHudTextCache(); } private void CreateHUD() { //IL_007a: Unknown result type (might be due to invalid IL or missing references) if (IsHudAlive) { return; } ClearDestroyedHud(); if (!((Object)(object)Player.LocalPlayer == (Object)null) && !((Object)(object)Player.LocalPlayer.PlayerLook == (Object)null) && !((Object)(object)Player.LocalPlayer.PlayerLook.Reticle == (Object)null)) { hud = HudBuilder.Create("TicketStatusHUD").ParentToReticle(true).Anchor(ConfigManager.Anchors.XValue, ConfigManager.Anchors.YValue) .Pivot(new Vector2(0f, 1f)) .Size(420f, 100f, true) .AddLines(4, 16f, (TextAlignmentOptions)257) .Build(); if (IsHudAlive) { hud.EnableReposition("sparroh.consumablehotkeys", "Consumable Hotkeys", ConfigManager.Anchors); InvalidateHudTextCache(); hudRefreshRequested = true; UpdateHudVisibility(); } } } public void Update() { try { if (ConfigManager.EnableHUD == null || !ConfigManager.EnableHUD.Value) { if (IsHudAlive) { hud.SetActive(false); } return; } if (hud != null && !IsHudAlive) { ClearDestroyedHud(); } if ((Object)(object)Player.LocalPlayer == (Object)null || (Object)(object)Player.LocalPlayer.PlayerLook == (Object)null || (Object)(object)Player.LocalPlayer.PlayerLook.Reticle == (Object)null) { return; } if (!IsHudAlive) { CreateHUD(); } else if (consumableStatuses != null) { float unscaledTime = Time.unscaledTime; if (hudRefreshRequested || !(unscaledTime < nextHudPollTime)) { nextHudPollTime = unscaledTime + 0.25f; hudRefreshRequested = false; RefreshHudIfNeeded(); } } } catch (Exception ex) { SparrohPlugin.Logger.LogError((object)("Error in ConsumableHotkeys.Update(): " + ex.Message)); } } private void SetupHotkeyActions() { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Expected O, but got Unknown //IL_008b: 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) //IL_00a9: Unknown result type (might be due to invalid IL or missing references) //IL_00b6: Unknown result type (might be due to invalid IL or missing references) //IL_00c7: 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_00e5: 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) controls = new InputActionMap("ConsumableHotkeys"); patAction = InputActionSetupExtensions.AddAction(controls, "PersonalAccessToken", (InputActionType)1, (string)null, (string)null, (string)null, (string)null, (string)null); pllAction = InputActionSetupExtensions.AddAction(controls, "PremiumLootLicense", (InputActionType)1, (string)null, (string)null, (string)null, (string)null, (string)null); replicatorAction = InputActionSetupExtensions.AddAction(controls, "BootlegReplicator", (InputActionType)1, (string)null, (string)null, (string)null, (string)null, (string)null); clearanceAction = InputActionSetupExtensions.AddAction(controls, "ClearanceCertificate", (InputActionType)1, (string)null, (string)null, (string)null, (string)null, (string)null); InputActionSetupExtensions.AddBinding(patAction, KeyToBindingPath(ConfigManager.PersonalAccessTokenHotkey.Value), (string)null, (string)null, (string)null); InputActionSetupExtensions.AddBinding(pllAction, KeyToBindingPath(ConfigManager.PremiumLootLicenseHotkey.Value), (string)null, (string)null, (string)null); InputActionSetupExtensions.AddBinding(replicatorAction, KeyToBindingPath(ConfigManager.BootlegReplicatorHotkey.Value), (string)null, (string)null, (string)null); InputActionSetupExtensions.AddBinding(clearanceAction, KeyToBindingPath(ConfigManager.ClearanceCertificateHotkey.Value), (string)null, (string)null, (string)null); patPerformed = delegate { OnHotkeyPerformed("Personal Access Token"); }; pllPerformed = delegate { OnHotkeyPerformed("Premium Loot License"); }; replicatorPerformed = delegate { OnHotkeyPerformed("Bootleg Replicator"); }; clearancePerformed = delegate { OnHotkeyPerformed("Clearance Certificate"); }; patAction.performed += patPerformed; pllAction.performed += pllPerformed; replicatorAction.performed += replicatorPerformed; clearanceAction.performed += clearancePerformed; ApplyHotkeyMapEnabled(); } private void RefreshHotkeyActions() { //IL_0015: 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_0054: Unknown result type (might be due to invalid IL or missing references) if (controls == null) { return; } try { ApplyBinding(patAction, ConfigManager.PersonalAccessTokenHotkey.Value); ApplyBinding(pllAction, ConfigManager.PremiumLootLicenseHotkey.Value); ApplyBinding(replicatorAction, ConfigManager.BootlegReplicatorHotkey.Value); ApplyBinding(clearanceAction, ConfigManager.ClearanceCertificateHotkey.Value); ApplyHotkeyMapEnabled(); } catch (Exception ex) { SparrohPlugin.Logger.LogError((object)("Failed to refresh hotkey bindings: " + ex.Message)); } } private void ApplyHotkeyMapEnabled() { if (controls == null) { return; } if (ConfigManager.EnableHotkeys != null && ConfigManager.EnableHotkeys.Value) { if (!controls.enabled) { controls.Enable(); } } else if (controls.enabled) { controls.Disable(); } } private static void ApplyBinding(InputAction action, Key key) { //IL_0004: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Unknown result type (might be due to invalid IL or missing references) if (action != null) { string text = KeyToBindingPath(key); if (action.bindings.Count == 0) { InputActionSetupExtensions.AddBinding(action, text, (string)null, (string)null, (string)null); } else { InputActionRebindingExtensions.ApplyBindingOverride(action, 0, text); } } } internal unsafe static string KeyToBindingPath(Key key) { //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_000c: Invalid comparison between Unknown and I4 //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Invalid comparison between Unknown and I4 //IL_001a: 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_001e: Unknown result type (might be due to invalid IL or missing references) if ((int)key == 0) { return string.Empty; } if ((int)key >= 50 && (int)key <= 49) { return $"/{(char)(48 + (key - 50))}"; } string text = ((object)(*(Key*)(&key))/*cast due to .constrained prefix*/).ToString(); if (text.Length == 0) { return string.Empty; } StringBuilder stringBuilder = new StringBuilder(text.Length + 12); stringBuilder.Append("/"); stringBuilder.Append(char.ToLowerInvariant(text[0])); if (text.Length > 1) { stringBuilder.Append(text, 1, text.Length - 1); } return stringBuilder.ToString(); } private void OnHotkeyPerformed(string consumableName) { try { if (ConfigManager.EnableHotkeys != null && ConfigManager.EnableHotkeys.Value && !ShouldBlockHotkeys()) { UseConsumable(consumableName); } } catch (Exception ex) { SparrohPlugin.Logger.LogError((object)("Error handling hotkey for " + consumableName + ": " + ex.Message)); } } private void DisposeHotkeyActions() { if (controls == null) { return; } try { if (patAction != null && patPerformed != null) { patAction.performed -= patPerformed; } if (pllAction != null && pllPerformed != null) { pllAction.performed -= pllPerformed; } if (replicatorAction != null && replicatorPerformed != null) { replicatorAction.performed -= replicatorPerformed; } if (clearanceAction != null && clearancePerformed != null) { clearanceAction.performed -= clearancePerformed; } controls.Disable(); controls.Dispose(); } catch (Exception ex) { SparrohPlugin.Logger.LogError((object)("Error disposing hotkey actions: " + ex.Message)); } finally { controls = null; patAction = null; pllAction = null; replicatorAction = null; clearanceAction = null; patPerformed = null; pllPerformed = null; replicatorPerformed = null; clearancePerformed = null; } } private void RefreshHudIfNeeded() { //IL_00fb: 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_0116: Unknown result type (might be due to invalid IL or missing references) //IL_011b: Unknown result type (might be due to invalid IL or missing references) //IL_0201: Unknown result type (might be due to invalid IL or missing references) //IL_01f5: Unknown result type (might be due to invalid IL or missing references) //IL_0237: Unknown result type (might be due to invalid IL or missing references) //IL_022b: Unknown result type (might be due to invalid IL or missing references) //IL_026d: 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_02b9: Unknown result type (might be due to invalid IL or missing references) //IL_02ad: Unknown result type (might be due to invalid IL or missing references) if (IsHudAlive && consumableStatuses != null && PlayerData.Instance != null) { EnsureResourceCache(); bool flag = PlayerData.Instance.GetFlag("pa_token") == 1; bool flag2 = PlayerData.Instance.GetFlag("equip_loot") == 1; bool flag3 = PlayerData.Instance.GetFlag("r_replicator") == 1; int flag4 = PlayerData.Instance.GetFlag("dur_drops"); consumableStatuses["Personal Access Token"].IsActive = flag; consumableStatuses["Premium Loot License"].IsActive = flag2; consumableStatuses["Bootleg Replicator"].IsActive = flag3; consumableStatuses["Clearance Certificate"].IsActive = flag4 > 0; int currentItemCount = GetCurrentItemCount("Personal Access Token"); int currentItemCount2 = GetCurrentItemCount("Premium Loot License"); int currentItemCount3 = GetCurrentItemCount("Bootleg Replicator"); int currentItemCount4 = GetCurrentItemCount("Clearance Certificate"); int hashCode = ((object)ConfigManager.ActiveColor.Value/*cast due to .constrained prefix*/).GetHashCode(); int hashCode2 = ((object)ConfigManager.InactiveColor.Value/*cast due to .constrained prefix*/).GetHashCode(); int hashCode3 = flag.GetHashCode(); hashCode3 = (hashCode3 * 397) ^ flag2.GetHashCode(); hashCode3 = (hashCode3 * 397) ^ flag3.GetHashCode(); hashCode3 = (hashCode3 * 397) ^ flag4; hashCode3 = (hashCode3 * 397) ^ currentItemCount; hashCode3 = (hashCode3 * 397) ^ currentItemCount2; hashCode3 = (hashCode3 * 397) ^ currentItemCount3; hashCode3 = (hashCode3 * 397) ^ currentItemCount4; hashCode3 = (hashCode3 * 397) ^ hashCode; hashCode3 = (hashCode3 * 397) ^ hashCode2; if (!hasHudStateHash || hashCode3 != lastHudStateHash) { lastHudStateHash = hashCode3; hasHudStateHash = true; WriteHudLine(0, "PAT", flag ? "Active" : "Inactive", currentItemCount, flag ? ConfigManager.ActiveColor.Value : ConfigManager.InactiveColor.Value); WriteHudLine(1, "PLL", flag2 ? "Active" : "Inactive", currentItemCount2, flag2 ? ConfigManager.ActiveColor.Value : ConfigManager.InactiveColor.Value); WriteHudLine(2, "Replicator", flag3 ? "Active" : "Inactive", currentItemCount3, flag3 ? ConfigManager.ActiveColor.Value : ConfigManager.InactiveColor.Value); string statusText = ((flag4 == 0) ? "Inactive" : $"{flag4}/{5} Uses"); WriteHudLine(3, "Clearance", statusText, currentItemCount4, (flag4 > 0) ? ConfigManager.ActiveColor.Value : ConfigManager.InactiveColor.Value); } } } private void WriteHudLine(int index, string shortName, string statusText, int count, Color color) { //IL_0028: Unknown result type (might be due to invalid IL or missing references) if (index >= 0 && index < hud.Lines.Length) { string text = RichText.Labeled(shortName, $"{statusText} ({count})", color); if (!(lastLineTexts[index] == text)) { lastLineTexts[index] = text; hud.Lines[index].Text = text; } } } private void EnsureResourceCache() { if (resourceCacheBuilt || (Object)(object)Global.Instance == (Object)null || Global.Instance.PlayerResources == null) { return; } resourceCache.Clear(); bool flag = false; PlayerResource[] playerResources = Global.Instance.PlayerResources; foreach (PlayerResource val in playerResources) { flag = true; if (!((Object)(object)val == (Object)null) && !string.IsNullOrEmpty(val.Name) && consumableStatuses != null && consumableStatuses.ContainsKey(val.Name)) { resourceCache[val.Name] = val; } } if (resourceCache.Count > 0 || flag) { resourceCacheBuilt = true; } } private int GetCurrentItemCount(string itemName) { if (PlayerData.Instance == null) { return 0; } if (resourceCache.TryGetValue(itemName, out var value) && (Object)(object)value != (Object)null) { return PlayerData.Instance.GetResource(value); } if ((Object)(object)Global.Instance == (Object)null || Global.Instance.PlayerResources == null) { return 0; } PlayerResource[] playerResources = Global.Instance.PlayerResources; foreach (PlayerResource val in playerResources) { if (!((Object)(object)val == (Object)null) && !(val.Name != itemName)) { resourceCache[itemName] = val; return PlayerData.Instance.GetResource(val); } } return 0; } private static bool ShouldBlockHotkeys() { if ((Object)(object)Player.LocalPlayer == (Object)null) { return true; } try { if ((Object)(object)Menu.Instance != (Object)null && Menu.Instance.IsOpen) { return true; } if (PlayerInput.IsMenuEnabled) { return true; } if (!PlayerInput.IsPlayerEnabled) { return true; } if ((Object)(object)GameManager.Instance != (Object)null && (Object)(object)GameManager.Instance.WindowSystem != (Object)null && GameManager.Instance.WindowSystem.Count > 0) { return true; } } catch { } if (IsTextInputFocused()) { return true; } if (ModMenuOpenDetector.IsAnyOpen()) { return true; } return false; } private static bool IsTextInputFocused() { try { EventSystem current = EventSystem.current; if ((Object)(object)current == (Object)null) { return false; } GameObject currentSelectedGameObject = current.currentSelectedGameObject; if ((Object)(object)currentSelectedGameObject == (Object)null) { return false; } TMP_InputField component = currentSelectedGameObject.GetComponent(); if ((Object)(object)component != (Object)null && component.isFocused) { return true; } InputField component2 = currentSelectedGameObject.GetComponent(); if ((Object)(object)component2 != (Object)null && component2.isFocused) { return true; } } catch { } return false; } private void UseConsumable(string name) { TryActivateConsumableByName(name); UpdateConsumableStatus(name); hudRefreshRequested = true; nextHudPollTime = 0f; } private void TryActivateConsumableByName(string name) { EnsureActivationReflection(); StorageWindow[] array = Object.FindObjectsOfType(); foreach (StorageWindow storageWindow in array) { if (TryActivateFromStorageWindow(storageWindow, name)) { return; } } TryDirectActivation(name); } private static void EnsureActivationReflection() { if (!_reflectionResolved) { _reflectionResolved = true; _storageSlotsField = typeof(StorageWindow).GetField("slots", BindingFlags.Instance | BindingFlags.NonPublic); _slotItemField = typeof(StorageSlot).GetField("item", BindingFlags.Instance | BindingFlags.NonPublic); _onPrimaryActionField = typeof(PlayerResource).GetField("onPrimaryAction", BindingFlags.Instance | BindingFlags.NonPublic); } } private bool TryActivateFromStorageWindow(StorageWindow storageWindow, string itemName) { try { if (_storageSlotsField == null || _slotItemField == null) { return false; } if (!(_storageSlotsField.GetValue(storageWindow) is StorageSlot[] array)) { return false; } StorageSlot[] array2 = array; InputAction val3 = default(InputAction); string text = default(string); foreach (StorageSlot obj in array2) { object? value = _slotItemField.GetValue(obj); IInventoryItem val = (IInventoryItem)((value is IInventoryItem) ? value : null); if (val == null) { continue; } PlayerResource val2 = (PlayerResource)(object)((val is PlayerResource) ? val : null); if (val2 != null && !(val2.Name != itemName) && val.ItemCount > 0 && ((IHoverInfo)val).GetPrimaryBinding(ref val3, ref text)) { object? obj2 = _onPrimaryActionField?.GetValue(val2); UnityEvent val4 = (UnityEvent)((obj2 is UnityEvent) ? obj2 : null); if (val4 != null) { val4.Invoke(); return true; } } } } catch (Exception ex) { SparrohPlugin.Logger.LogError((object)("Error activating " + itemName + " from storage: " + ex.Message)); } return false; } private void TryDirectActivation(string itemName) { if (PlayerData.Instance == null || IsConsumableActive(itemName)) { return; } EnsureResourceCache(); PlayerResource value = null; if (!resourceCache.TryGetValue(itemName, out value) || (Object)(object)value == (Object)null) { if (Global.Instance?.PlayerResources == null) { return; } PlayerResource[] playerResources = Global.Instance.PlayerResources; foreach (PlayerResource val in playerResources) { if (!((Object)(object)val == (Object)null) && !(val.Name != itemName)) { value = val; resourceCache[itemName] = val; break; } } } if (!((Object)(object)value == (Object)null) && PlayerData.Instance.GetResource(value) > 0 && PlayerData.Instance.TryRemoveResource(value, 1)) { ActivateConsumableByFlag(itemName); } } private bool IsConsumableActive(string name) { if (PlayerData.Instance == null) { return false; } return name switch { "Personal Access Token" => PlayerData.Instance.GetFlag("pa_token") == 1, "Bootleg Replicator" => PlayerData.Instance.GetFlag("r_replicator") == 1, "Premium Loot License" => PlayerData.Instance.GetFlag("equip_loot") == 1, "Clearance Certificate" => PlayerData.Instance.GetFlag("dur_drops") > 0, _ => false, }; } private void ActivateConsumableByFlag(string name) { if (PlayerData.Instance != null) { switch (name) { case "Personal Access Token": PlayerData.Instance.SetFlag("pa_token", 1); break; case "Bootleg Replicator": PlayerData.Instance.SetFlag("r_replicator", 1); break; case "Premium Loot License": PlayerData.Instance.SetFlag("equip_loot", 1); break; case "Clearance Certificate": PlayerData.Instance.SetFlag("dur_drops", 5); break; } } } private void UpdateConsumableStatus(string name) { if (consumableStatuses != null && consumableStatuses.TryGetValue(name, out var value)) { value.IsActive = IsConsumableActive(name); } } public void UpdateConsumableStatuses() { if (consumableStatuses == null) { return; } foreach (KeyValuePair consumableStatus in consumableStatuses) { consumableStatus.Value.IsActive = IsConsumableActive(consumableStatus.Key); } hudRefreshRequested = true; } public void OnDestroy() { try { DisposeHotkeyActions(); } catch (Exception ex) { SparrohPlugin.Logger.LogError((object)("Error disposing hotkeys: " + ex.Message)); } try { DestroyHud(); } catch (Exception ex2) { SparrohPlugin.Logger.LogError((object)("Error in ConsumableHotkeys.OnDestroy(): " + ex2.Message)); } } } [HarmonyPatch] public static class ConsumablePatches { [HarmonyPostfix] [HarmonyPatch(typeof(PlayerData), "SetFlag", new Type[] { typeof(string), typeof(int) })] public static void PostfixSetFlag(string id, int value) { if (id != null && id.Length >= 7 && id.Length <= 12 && (!(id != "pa_token") || !(id != "r_replicator") || !(id != "equip_loot") || !(id != "dur_drops"))) { ConsumableHotkeysMod.Instance?.RequestHudRefresh(); } } [HarmonyPostfix] [HarmonyPatch(typeof(MissionManager), "OnUpgradeCollected")] public static void PostfixOnUpgradeCollected(UpgradeInstance upgrade) { if (((upgrade != null) ? upgrade.Gear : null) != null && PlayerData.Instance != null) { int flag = PlayerData.Instance.GetFlag("dur_drops"); if (flag > 0) { PlayerData.Instance.SetFlag("dur_drops", flag - 1); } } } } internal static class ModMenuOpenDetector { private static readonly string[] KnownTypeNames = new string[11] { "ModConfigGUI", "HudRepositionMode", "CheatMenu", "CheatMenuGUI", "CheatMenuPlus", "CheatMenuUI", "ForceModifiers", "ForceModifiersGUI", "ForceModifiersMenu", "ForceModifierMenu", "ForceModifiersUI" }; private static readonly string[] OpenMemberNames = new string[6] { "IsVisible", "IsOpen", "IsActive", "IsHeld", "Visible", "Open" }; private static readonly List OpenProps = new List(); private static readonly List OpenFields = new List(); private static bool resolved; public static bool IsAnyOpen() { EnsureResolved(); bool flag = default(bool); for (int i = 0; i < OpenProps.Count; i++) { try { object value = OpenProps[i].GetValue(null); int num; if (value is bool) { flag = (bool)value; num = 1; } else { num = 0; } if (((uint)num & (flag ? 1u : 0u)) != 0) { return true; } } catch { } } bool flag2 = default(bool); for (int j = 0; j < OpenFields.Count; j++) { try { object value = OpenFields[j].GetValue(null); int num2; if (value is bool) { flag2 = (bool)value; num2 = 1; } else { num2 = 0; } if (((uint)num2 & (flag2 ? 1u : 0u)) != 0) { return true; } } catch { } } return false; } private static void EnsureResolved() { if (resolved) { return; } resolved = true; Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies(); foreach (Assembly assembly in assemblies) { for (int j = 0; j < KnownTypeNames.Length; j++) { Type type; try { type = assembly.GetType(KnownTypeNames[j], throwOnError: false); } catch { continue; } if (!(type == null) && type.IsClass) { CollectOpenMembers(type); } } } } private static void CollectOpenMembers(Type type) { for (int i = 0; i < OpenMemberNames.Length; i++) { string name = OpenMemberNames[i]; try { PropertyInfo property = type.GetProperty(name, BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); if (property != null && property.PropertyType == typeof(bool) && property.CanRead) { OpenProps.Add(property); } } catch { } try { FieldInfo field = type.GetField(name, BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); if (field != null && field.FieldType == typeof(bool)) { OpenFields.Add(field); } } catch { } } } } [BepInPlugin("sparroh.consumablehotkeys", "ConsumableHotkeys", "1.0.6")] [BepInDependency(/*Could not decode attribute arguments.*/)] [MycoMod(/*Could not decode attribute arguments.*/)] public class SparrohPlugin : BaseUnityPlugin { public const string PluginGUID = "sparroh.consumablehotkeys"; public const string PluginName = "ConsumableHotkeys"; public const string PluginVersion = "1.0.6"; internal static ManualLogSource Logger; private ConsumableHotkeysMod consumableHotkeys; private Harmony harmony; private void Awake() { //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_004e: Expected O, but got Unknown Logger = ((BaseUnityPlugin)this).Logger; try { ConfigManager.Initialize(((BaseUnityPlugin)this).Config, Logger); } catch (Exception ex) { Logger.LogError((object)("Failed to initialize config: " + ex.Message)); return; } try { harmony = new Harmony("sparroh.consumablehotkeys"); } catch (Exception ex2) { Logger.LogError((object)("Failed to create Harmony instance: " + ex2.Message)); return; } try { consumableHotkeys = new ConsumableHotkeysMod(); } catch (Exception ex3) { Logger.LogError((object)("Failed to initialize ConsumableHotkeys: " + ex3.Message)); } try { harmony.PatchAll(); } catch (Exception ex4) { Logger.LogError((object)("Failed to apply Harmony patches: " + ex4.Message)); } Logger.LogInfo((object)"ConsumableHotkeys loaded successfully."); } private void Update() { try { ConfigManager.Tick(); if (ConfigManager.ConsumePendingRefresh() && consumableHotkeys != null) { consumableHotkeys.OnConfigChanged(); } if (consumableHotkeys != null) { consumableHotkeys.Update(); } } catch (Exception ex) { Logger.LogError((object)("Error in ConsumableHotkeys.Update(): " + ex.Message)); } } private void OnDestroy() { try { if (consumableHotkeys != null) { consumableHotkeys.OnDestroy(); } } catch (Exception ex) { Logger.LogError((object)("Error in ConsumableHotkeys.OnDestroy(): " + ex.Message)); } try { ConfigManager.Dispose(); } catch (Exception ex2) { Logger.LogError((object)("Error disposing config: " + ex2.Message)); } try { if (harmony != null) { harmony.UnpatchSelf(); } } catch (Exception ex3) { Logger.LogError((object)("Error unpatching Harmony: " + ex3.Message)); } } } namespace ConsumableHotkeys { public static class MyPluginInfo { public const string PLUGIN_GUID = "ConsumableHotkeys"; public const string PLUGIN_NAME = "ConsumableHotkeys"; public const string PLUGIN_VERSION = "1.0.6"; } } namespace System.Runtime.CompilerServices { [AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)] internal sealed class IgnoresAccessChecksToAttribute : Attribute { public IgnoresAccessChecksToAttribute(string assemblyName) { } } }