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<bool> EnableHotkeys { get; private set; }
public static ConfigEntry<bool> EnableHUD { get; private set; }
public static ConfigEntry<Key> PersonalAccessTokenHotkey { get; private set; }
public static ConfigEntry<Key> PremiumLootLicenseHotkey { get; private set; }
public static ConfigEntry<Key> BootlegReplicatorHotkey { get; private set; }
public static ConfigEntry<Key> 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<bool>("Consumables", "Enable Hotkeys", true, "Enables hotkey functionality for consumables.");
EnableHUD = config.Bind<bool>("Consumables", "Enable HUD", true, "Enables the HUD display for consumable statuses.");
PersonalAccessTokenHotkey = config.Bind<Key>("Consumables", "PersonalAccessToken Key", (Key)22, "Hotkey for Personal Access Token.");
PremiumLootLicenseHotkey = config.Bind<Key>("Consumables", "PremiumLootLicense Key", (Key)24, "Hotkey for Premium Loot License.");
BootlegReplicatorHotkey = config.Bind<Key>("Consumables", "BootlegReplicator Key", (Key)25, "Hotkey for Bootleg Replicator.");
ClearanceCertificateHotkey = config.Bind<Key>("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<string, ConsumableStatus> consumableStatuses;
private readonly Dictionary<string, PlayerResource> resourceCache = new Dictionary<string, PlayerResource>();
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<CallbackContext> patPerformed;
private Action<CallbackContext> pllPerformed;
private Action<CallbackContext> replicatorPerformed;
private Action<CallbackContext> 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<string, ConsumableStatus>
{
{
"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 $"<Keyboard>/{(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("<Keyboard>/");
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<TMP_InputField>();
if ((Object)(object)component != (Object)null && component.isFocused)
{
return true;
}
InputField component2 = currentSelectedGameObject.GetComponent<InputField>();
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<StorageWindow>();
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<string, ConsumableStatus> 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<PropertyInfo> OpenProps = new List<PropertyInfo>();
private static readonly List<FieldInfo> OpenFields = new List<FieldInfo>();
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)
{
}
}
}