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 Pigeon; using Pigeon.Movement; using Sparroh.UI; using TMPro; using UnityEngine; using UnityEngine.Events; using UnityEngine.InputSystem; using UnityEngine.InputSystem.Controls; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")] [assembly: AssemblyCompany("ConsumableHotkeys")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0")] [assembly: AssemblyProduct("ConsumableHotkeys")] [assembly: AssemblyTitle("ConsumableHotkeys")] [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; } } } 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 ConfigEntry enableHotkeys; private ConfigEntry enableHUD; private ConfigEntry consumableHotkeysAnchorX; private ConfigEntry consumableHotkeysAnchorY; private ConfigColor activeColor; private ConfigColor inactiveColor; private ConfigEntry personalAccessTokenHotkey; private ConfigEntry premiumLootLicenseHotkey; private ConfigEntry bootlegReplicatorHotkey; private ConfigEntry clearanceCertificateHotkey; private HudHandle hud; private Dictionary consumableStatuses; private readonly ConfigFile configFile; private readonly Harmony harmony; public static ConsumableHotkeysMod Instance { get; private set; } private bool IsHudAlive { get { if (hud != null && (Object)(object)hud.GameObject != (Object)null && hud.Lines != null) { return hud.Lines.Length >= 4; } return false; } } public ConsumableHotkeysMod(ConfigFile configFile, Harmony harmony) { this.configFile = configFile; this.harmony = harmony; Instance = this; try { SetupConfig(); InitializeStatuses(); SetupConfigWatcher(); } catch (Exception ex) { SparrohPlugin.Logger.LogError((object)("Failed to initialize ConsumableHotkeys: " + ex.Message)); } } private void SetupConfig() { //IL_00cb: Unknown result type (might be due to invalid IL or missing references) //IL_00f0: Unknown result type (might be due to invalid IL or missing references) enableHotkeys = configFile.Bind("Consumables", "EnableHotkeys", true, "Enables hotkey functionality for consumables."); enableHUD = configFile.Bind("Consumables", "EnableHUD", true, "Enables the HUD display for consumable statuses."); consumableHotkeysAnchorX = configFile.Bind("HUD Positioning", "ConsumableHotkeysAnchorX", 0.2561931f, "X anchor position for ConsumableHotkeys (0-1)."); consumableHotkeysAnchorY = configFile.Bind("HUD Positioning", "ConsumableHotkeysAnchorY", 0.9362161f, "Y anchor position for ConsumableHotkeys (0-1)."); consumableHotkeysAnchorX.SettingChanged += OnAnchorChanged; consumableHotkeysAnchorY.SettingChanged += OnAnchorChanged; activeColor = ConfigColor.Bind(configFile, "Colors", "ActiveColor", UIColors.Shamrock, "Rich-text color for active consumables (hex RRGGBB or #RRGGBB)."); inactiveColor = ConfigColor.Bind(configFile, "Colors", "InactiveColor", UIColors.Rose, "Rich-text color for inactive consumables (hex RRGGBB or #RRGGBB)."); personalAccessTokenHotkey = configFile.Bind("Consumables", "PersonalAccessToken_Hotkey", (Key)22, "Hotkey for Personal Access Token."); premiumLootLicenseHotkey = configFile.Bind("Consumables", "PremiumLootLicense_Hotkey", (Key)24, "Hotkey for Premium Loot License."); bootlegReplicatorHotkey = configFile.Bind("Consumables", "BootlegReplicator_Hotkey", (Key)25, "Hotkey for Bootleg Replicator."); clearanceCertificateHotkey = configFile.Bind("Consumables", "ClearanceCertificate_Hotkey", (Key)26, "Hotkey for Clearance Certificate."); } private void InitializeStatuses() { 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 } } }; } private void Start() { if (enableHUD.Value) { CreateHUD(); } UpdateHudVisibility(); } public void UpdateHudVisibility() { if (!IsHudAlive) { ClearDestroyedHud(); } else { hud.SetActive(enableHUD.Value); } } private void OnAnchorChanged(object sender, EventArgs e) { if (IsHudAlive) { hud.SetAnchor(consumableHotkeysAnchorX.Value, consumableHotkeysAnchorY.Value); } } private void ClearDestroyedHud() { if (hud == null) { return; } try { if ((Object)(object)hud.Rect != (Object)null) { HudRepositionClient.Unregister("sparroh.consumablehotkeys"); } } catch { } hud = null; } private void CreateHUD() { //IL_007c: 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(consumableHotkeysAnchorX.Value, consumableHotkeysAnchorY.Value) .Pivot(new Vector2(0f, 1f)) .Size(420f, 100f, true) .AddLines(4, 16f, (TextAlignmentOptions)257) .Build(); if (IsHudAlive) { HudRepositionClient.Register("sparroh.consumablehotkeys", "Consumable Hotkeys", hud.Rect, consumableHotkeysAnchorX, consumableHotkeysAnchorY); UpdateHudVisibility(); } } } public void Update() { try { if (enableHotkeys != null && enableHotkeys.Value) { CheckHotkeys(); } if (enableHUD == null || !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)) { if (!IsHudAlive) { CreateHUD(); } else if (consumableStatuses != null) { UpdateHUDText(); } } } catch (Exception ex) { SparrohPlugin.Logger.LogError((object)("Error in ConsumableHotkeys.Update(): " + ex.Message)); } } private void UpdateHUDText() { //IL_00f0: Unknown result type (might be due to invalid IL or missing references) //IL_00e3: Unknown result type (might be due to invalid IL or missing references) //IL_00ab: Unknown result type (might be due to invalid IL or missing references) //IL_009e: Unknown result type (might be due to invalid IL or missing references) //IL_00f5: 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_016c: Unknown result type (might be due to invalid IL or missing references) if (!IsHudAlive || consumableStatuses == null) { return; } int i = 0; foreach (KeyValuePair consumableStatus in consumableStatuses) { if (i >= hud.Lines.Length) { break; } string arg; Color val; if (consumableStatus.Key.Contains("Clearance Certificate")) { int flag = PlayerData.Instance.GetFlag("dur_drops"); arg = ((flag == 0) ? "Inactive" : $"{flag}/{consumableStatus.Value.MaxUses} Uses"); val = ((flag > 0) ? activeColor.Value : inactiveColor.Value); } else { arg = (consumableStatus.Value.IsActive ? "Active" : "Inactive"); val = (consumableStatus.Value.IsActive ? activeColor.Value : inactiveColor.Value); } int currentItemCount = GetCurrentItemCount(consumableStatus.Key); string text = consumableStatus.Key.Replace("Personal Access Token", "PAT").Replace("Premium Loot License", "PLL").Replace("Bootleg Replicator", "Replicator") .Replace("Clearance Certificate", "Clearance"); hud.Lines[i].Text = RichText.Labeled(text, $"{arg} ({currentItemCount})", val); i++; } for (; i < hud.Lines.Length; i++) { hud.Lines[i].Text = ""; } } private int GetCurrentItemCount(string itemName) { PlayerResource[] playerResources = Global.Instance.PlayerResources; foreach (PlayerResource val in playerResources) { if (val.Name == itemName) { return PlayerData.Instance.GetResource(val); } } return 0; } private void CheckHotkeys() { //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_004e: Unknown result type (might be due to invalid IL or missing references) //IL_0065: Unknown result type (might be due to invalid IL or missing references) if (enableHotkeys.Value) { Keyboard current = Keyboard.current; if (current != null) { CheckHotkey(current, personalAccessTokenHotkey.Value, "Personal Access Token"); CheckHotkey(current, premiumLootLicenseHotkey.Value, "Premium Loot License"); CheckHotkey(current, bootlegReplicatorHotkey.Value, "Bootleg Replicator"); CheckHotkey(current, clearanceCertificateHotkey.Value, "Clearance Certificate"); } } } private void CheckHotkey(Keyboard keyboard, Key key, string consumableName) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) if (((ButtonControl)keyboard[key]).wasPressedThisFrame) { UseConsumable(consumableName); } } private void UseConsumable(string name) { TryActivateConsumableByName(name); UpdateConsumableStatus(name); } private void TryActivateConsumableByName(string name) { StorageWindow[] array = Object.FindObjectsOfType(); foreach (StorageWindow storageWindow in array) { if (TryActivateFromStorageWindow(storageWindow, name)) { return; } } TryDirectActivation(name); } private bool TryActivateFromStorageWindow(StorageWindow storageWindow, string itemName) { try { FieldInfo field = ((object)storageWindow).GetType().GetField("slots", BindingFlags.Instance | BindingFlags.NonPublic); if (field == null) { return false; } if (!(field.GetValue(storageWindow) is StorageSlot[] array)) { return false; } StorageSlot[] array2 = array; InputAction val4 = default(InputAction); string text = default(string); foreach (StorageSlot val in array2) { object? obj = ((object)val).GetType().GetField("item", BindingFlags.Instance | BindingFlags.NonPublic)?.GetValue(val); IInventoryItem val2 = (IInventoryItem)((obj is IInventoryItem) ? obj : null); PlayerResource val3 = (PlayerResource)(object)((val2 is PlayerResource) ? val2 : null); if (val2 == null || !((Object)(object)val3 != (Object)null) || !(val3.Name == itemName) || val2.ItemCount <= 0 || !((IHoverInfo)val2).GetPrimaryBinding(ref val4, ref text)) { continue; } FieldInfo field2 = ((object)val3).GetType().GetField("onPrimaryAction", BindingFlags.Instance | BindingFlags.NonPublic); if (field2 != null) { object? value = field2.GetValue(val3); UnityEvent val5 = (UnityEvent)((value is UnityEvent) ? value : null); if (val5 != null) { val5.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 (IsConsumableActive(itemName)) { return; } PlayerResource[] playerResources = Global.Instance.PlayerResources; foreach (PlayerResource val in playerResources) { if (val.Name == itemName) { if (PlayerData.Instance.GetResource(val) > 0 && PlayerData.Instance.TryRemoveResource(val, 1)) { ActivateConsumableByFlag(itemName); } break; } } } private bool IsConsumableActive(string name) { if (name.Contains("Personal Access Token")) { return PlayerData.Instance.GetFlag("pa_token") == 1; } if (name.Contains("Bootleg Replicator")) { return PlayerData.Instance.GetFlag("r_replicator") == 1; } if (name.Contains("Premium Loot License")) { return PlayerData.Instance.GetFlag("equip_loot") == 1; } if (name.Contains("Clearance Certificate")) { return PlayerData.Instance.GetFlag("dur_drops") > 0; } return false; } private void ActivateConsumableByFlag(string name) { if (name.Contains("Personal Access Token")) { PlayerData.Instance.SetFlag("pa_token", 1); } else if (name.Contains("Bootleg Replicator")) { PlayerData.Instance.SetFlag("r_replicator", 1); } else if (name.Contains("Premium Loot License")) { PlayerData.Instance.SetFlag("equip_loot", 1); } else if (name.Contains("Clearance Certificate")) { PlayerData.Instance.SetFlag("dur_drops", 5); } } private void UpdateConsumableStatus(string name) { if (consumableStatuses.TryGetValue(name, out var value)) { value.IsActive = IsConsumableActive(name); _ = value.IsActive; } } public void UpdateConsumableStatuses() { foreach (KeyValuePair consumableStatus in consumableStatuses) { consumableStatus.Value.IsActive = IsConsumableActive(consumableStatus.Key); } UpdateHUDText(); } private void SetupConfigWatcher() { string configFilePath = configFile.ConfigFilePath; FileSystemWatcher fileSystemWatcher = new FileSystemWatcher(Path.GetDirectoryName(configFilePath), Path.GetFileName(configFilePath)); fileSystemWatcher.Changed += delegate { configFile.Reload(); OnConfigReloaded(); }; fileSystemWatcher.EnableRaisingEvents = true; } private void OnConfigReloaded() { InitializeStatuses(); UpdateHudVisibility(); } public void OnDestroy() { try { HudRepositionClient.Unregister("sparroh.consumablehotkeys"); if (hud != null) { if ((Object)(object)hud.GameObject != (Object)null) { hud.Destroy(); } hud = null; } } catch (Exception ex) { SparrohPlugin.Logger.LogError((object)("Error in ConsumableHotkeys.OnDestroy(): " + ex.Message)); } } } [HarmonyPatch] public static class StorageSlotPatches { [HarmonyPostfix] [HarmonyPatch(typeof(StorageSlot), "Setup")] public static void PostfixSetup(StorageSlot __instance, IInventoryItem item) { if (item != null) { IInventoryItem obj = ((item is PlayerResource) ? item : null); if (obj != null) { _ = ((PlayerResource)obj).Name; } else _ = null; } } } [HarmonyPatch] public static class StorageWindowPatches { [HarmonyPostfix] [HarmonyPatch(typeof(StorageWindow), "Refresh")] public static void PostfixRefresh(StorageWindow __instance) { if (!(((object)__instance).GetType().GetField("slots", BindingFlags.Instance | BindingFlags.NonPublic)?.GetValue(__instance) is StorageSlot[] array)) { return; } StorageSlot[] array2 = array; foreach (StorageSlot val in array2) { object? obj = ((object)val).GetType().GetField("item", BindingFlags.Instance | BindingFlags.NonPublic)?.GetValue(val); IInventoryItem val2 = (IInventoryItem)((obj is IInventoryItem) ? obj : null); if (val2 != null && val2.ItemCount > 0) { IInventoryItem obj2 = ((val2 is PlayerResource) ? val2 : null); if (obj2 != null) { _ = ((PlayerResource)obj2).Name; } else _ = null; } } } } [HarmonyPatch] public static class DebugPatches { [HarmonyPostfix] [HarmonyPatch(typeof(PlayerData), "GetFlag", new Type[] { typeof(string) })] public static void PostfixGetFlag(PlayerData __instance, string id, ref int __result) { if (!id.ToLower().Contains("token") && !id.ToLower().Contains("license") && !id.ToLower().Contains("replicator") && !id.ToLower().Contains("certificate") && !id.ToLower().Contains("clearance") && !id.ToLower().Contains("permit") && !id.ToLower().Contains("document") && !id.ToLower().Contains("upgrade") && !id.ToLower().Contains("dur_") && !id.ToLower().Contains("pa_") && !id.ToLower().Contains("pl_") && !id.ToLower().Contains("cc_") && !id.ToLower().Contains("loot") && !id.ToLower().Contains("premium") && !id.Contains("p_l") && !id.Contains("c_c")) { id.Contains("r_r"); } } [HarmonyPostfix] [HarmonyPatch(typeof(PlayerData), "SetFlag", new Type[] { typeof(string), typeof(int) })] public static void PostfixSetFlag(PlayerData __instance, string id, int value) { if (!id.ToLower().Contains("token") && !id.ToLower().Contains("license") && !id.ToLower().Contains("replicator") && !id.ToLower().Contains("certificate") && !id.ToLower().Contains("pa_") && !id.ToLower().Contains("pl_") && !id.ToLower().Contains("cc_") && !id.ToLower().Contains("loot") && !id.ToLower().Contains("premium") && !id.Contains("p_l") && !id.Contains("c_c") && !id.Contains("r_r")) { return; } switch (id) { case "pa_token": case "r_replicator": case "equip_loot": case "dur_drops": if (value == 0) { ConsumableHotkeysMod.Instance?.UpdateConsumableStatuses(); } break; } } [HarmonyPostfix] [HarmonyPatch(typeof(PlayerData), "TryRemoveResource", new Type[] { typeof(PlayerResource), typeof(int) })] public static void PostfixTryRemoveResource(PlayerData __instance, PlayerResource resource, int amount, bool __result) { if (__result && amount > 0 && !resource.Name.Contains("Personal") && !resource.Name.Contains("Premium") && !resource.Name.Contains("Bootleg")) { resource.Name.Contains("Clearance"); } } [HarmonyPostfix] [HarmonyPatch(typeof(PlayerData), "AddResource")] public static void PostfixAddResource(PlayerData __instance, PlayerResource resource, int amount) { if (amount != 0 && !resource.Name.Contains("Personal") && !resource.Name.Contains("Premium") && !resource.Name.Contains("Bootleg")) { resource.Name.Contains("Clearance"); } } [HarmonyPostfix] [HarmonyPatch(typeof(MissionManager), "OnUpgradeCollected")] public static void PostfixOnUpgradeCollected(UpgradeInstance upgrade) { if (upgrade.Gear != null) { int flag = PlayerData.Instance.GetFlag("dur_drops"); if (flag > 0) { PlayerData.Instance.SetFlag("dur_drops", flag - 1); } } } } public static class HudRepositionClient { private const string ApiTypeName = "HudRepositionAPI"; private static Type _apiType; private static MethodInfo _register; private static MethodInfo _unregister; private static bool _available; public static bool IsAvailable { get { EnsureResolved(); return _available; } } public static void Register(string id, string displayName, RectTransform rect, ConfigEntry anchorX, ConfigEntry anchorY) { if (!_available) { EnsureResolved(force: true); } if (!_available || (Object)(object)rect == (Object)null || anchorX == null || anchorY == null) { return; } try { _register.Invoke(null, new object[5] { id, displayName, rect, anchorX, anchorY }); } catch (Exception ex) { Debug.LogWarning((object)("[HudRepositionClient] Register failed: " + (ex.InnerException?.Message ?? ex.Message))); } } public static void Unregister(string id) { if (!_available) { EnsureResolved(force: true); } if (!_available || string.IsNullOrEmpty(id)) { return; } try { _unregister.Invoke(null, new object[1] { id }); } catch (Exception) { } } private static void EnsureResolved(bool force = false) { if (_available && !force) { return; } _apiType = null; _register = null; _unregister = null; _available = false; Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies(); foreach (Assembly assembly in assemblies) { try { Type type = assembly.GetType("HudRepositionAPI", throwOnError: false); if (type != null) { _apiType = type; break; } } catch { } } if (_apiType == null) { return; } MethodInfo[] methods = _apiType.GetMethods(BindingFlags.Static | BindingFlags.Public); foreach (MethodInfo methodInfo in methods) { ParameterInfo[] parameters = methodInfo.GetParameters(); if (methodInfo.Name == "Register" && parameters.Length == 5 && parameters[0].ParameterType == typeof(string) && parameters[1].ParameterType == typeof(string) && typeof(RectTransform).IsAssignableFrom(parameters[2].ParameterType)) { _register = methodInfo; } else if (methodInfo.Name == "Unregister" && parameters.Length == 1 && parameters[0].ParameterType == typeof(string)) { _unregister = methodInfo; } } _available = _register != null && _unregister != null; } } [BepInPlugin("sparroh.consumablehotkeys", "ConsumableHotkeys", "1.0.0")] [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.0"; internal static ManualLogSource Logger; private Harmony harmony; private ConsumableHotkeysMod consumableHotkeys; private void Awake() { //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Expected O, but got Unknown Logger = ((BaseUnityPlugin)this).Logger; try { harmony = new Harmony("sparroh.consumablehotkeys"); } catch (Exception ex) { Logger.LogError((object)("Failed to create Harmony instance: " + ex.Message)); return; } ConfigFile configFile = ((BaseUnityPlugin)this).Config; try { FileSystemWatcher fileSystemWatcher = new FileSystemWatcher(Paths.ConfigPath, "sparroh.consumablehotkeys.cfg"); fileSystemWatcher.Changed += delegate { configFile.Reload(); }; fileSystemWatcher.EnableRaisingEvents = true; } catch (Exception ex2) { Logger.LogWarning((object)("Failed to set up config watcher: " + ex2.Message)); } try { consumableHotkeys = new ConsumableHotkeysMod(configFile, harmony); } 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 { if (consumableHotkeys != null) { consumableHotkeys.UpdateHudVisibility(); } } catch (Exception ex) { Logger.LogError((object)("Error in ConsumableHotkeys.UpdateHudVisibility(): " + ex.Message)); } try { if (consumableHotkeys != null) { consumableHotkeys.Update(); } } catch (Exception ex2) { Logger.LogError((object)("Error in ConsumableHotkeys.Update(): " + ex2.Message)); } } private void OnDestroy() { try { if (consumableHotkeys != null) { consumableHotkeys.OnDestroy(); } } catch (Exception ex) { Logger.LogError((object)("Error in ConsumableHotkeys.OnDestroy(): " + ex.Message)); } try { if (harmony != null) { harmony.UnpatchSelf(); } } catch (Exception ex2) { Logger.LogError((object)("Error unpatching Harmony: " + ex2.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.0"; } } namespace System.Runtime.CompilerServices { [AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)] internal sealed class IgnoresAccessChecksToAttribute : Attribute { public IgnoresAccessChecksToAttribute(string assemblyName) { } } }