Please disclose if any significant portion of your mod was created using AI tools by adding the 'AI Generated' category. Failing to do so may result in the mod being removed from Thunderstore.
Decompiled source of MoreHotbarSlots v1.0.0
BepInEx\plugins\DaanDeReus-MoreHotbarSlots\MoreHotbarSlots.dll
Decompiled a week agousing System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; using Microsoft.CodeAnalysis; using UnityEngine; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: IgnoresAccessChecksTo("Assembly-CSharp")] [assembly: AssemblyCompany("DaanDeReus")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0")] [assembly: AssemblyProduct("MoreHotbarSlots")] [assembly: AssemblyTitle("MoreHotbarSlots")] [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.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)] internal sealed class NullableAttribute : Attribute { public readonly byte[] NullableFlags; public NullableAttribute(byte P_0) { NullableFlags = new byte[1] { P_0 }; } public NullableAttribute(byte[] P_0) { NullableFlags = P_0; } } [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] internal sealed class NullableContextAttribute : Attribute { public readonly byte Flag; public NullableContextAttribute(byte P_0) { Flag = P_0; } } [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace MoreHotbarSlots { internal static class ExtraSlotMemory { private const float RestoreTimeout = 30f; private static readonly Dictionary<int, string> itemBySlot = new Dictionary<int, string>(); private static InventorySpot? restoredForSpot; internal static void Remember(int slotIndex, ItemEquippable item) { ItemAttributes component = ((Component)item).GetComponent<ItemAttributes>(); if ((Object)(object)component == (Object)null || string.IsNullOrEmpty(component.instanceName)) { return; } foreach (KeyValuePair<int, string> item2 in new List<KeyValuePair<int, string>>(itemBySlot)) { if (item2.Value == component.instanceName) { itemBySlot.Remove(item2.Key); } } itemBySlot[slotIndex] = component.instanceName; } internal static void Forget(int slotIndex) { itemBySlot.Remove(slotIndex); } internal static void Clear() { itemBySlot.Clear(); } internal static void OnSpotRegistered(Inventory inventory) { if (itemBySlot.Count == 0) { return; } int value = MoreHotbarSlotsConfig.SlotCount.Value; for (int i = 0; i < value; i++) { if ((Object)(object)InventoryPatch.GetSpot(inventory, i) == (Object)null) { return; } } InventorySpot spot = InventoryPatch.GetSpot(inventory, 0); if (!((Object)(object)spot == (Object)(object)restoredForSpot)) { restoredForSpot = spot; ((MonoBehaviour)MoreHotbarSlots.Instance).StartCoroutine(RestoreWhenReady()); } } private static IEnumerator RestoreWhenReady() { Dictionary<int, string> pending = new Dictionary<int, string>(itemBySlot); float deadline = Time.time + 30f; while (pending.Count > 0 && Time.time < deadline) { yield return (object)new WaitForSeconds(0.5f); Inventory instance = Inventory.instance; PlayerAvatar instance2 = PlayerAvatar.instance; if ((Object)(object)instance == (Object)null || (Object)(object)instance2 == (Object)null || (Object)(object)LevelGenerator.Instance == (Object)null || !LevelGenerator.Instance.Generated) { continue; } int num = (SemiFunc.IsMultiplayer() ? instance2.photonView.ViewID : (-1)); ItemAttributes[] array = Object.FindObjectsOfType<ItemAttributes>(); foreach (ItemAttributes val in array) { foreach (KeyValuePair<int, string> item in pending) { if (!(val.instanceName != item.Value)) { ItemEquippable component = ((Component)val).GetComponent<ItemEquippable>(); InventorySpot spot = InventoryPatch.GetSpot(instance, item.Key); if ((Object)(object)component != (Object)null && (Object)(object)spot != (Object)null && !spot.IsOccupied() && !component.IsEquipped()) { component.RequestEquip(item.Key, num); MoreHotbarSlots.Logger.LogInfo((object)$"Restored {item.Value} to slot {item.Key + 1}."); } pending.Remove(item.Key); break; } } } } foreach (KeyValuePair<int, string> item2 in pending) { MoreHotbarSlots.Logger.LogWarning((object)$"Could not find {item2.Value} to restore to slot {item2.Key + 1}."); } } } [HarmonyPatch] internal static class ExtraSlotPersistencePatch { private static ItemEquippable? destroyingItem; [HarmonyPostfix] [HarmonyPatch(typeof(InventorySpot), "EquipItem")] private static void EquipItem_Postfix(InventorySpot __instance, ItemEquippable item) { if (__instance.inventorySpotIndex < 3 || (Object)(object)item == (Object)null) { return; } try { ExtraSlotMemory.Remember(__instance.inventorySpotIndex, item); } catch (Exception ex) { MoreHotbarSlots.Logger.LogError((object)("EquipItem postfix failed: " + ex.Message)); } } [HarmonyPrefix] [HarmonyPatch(typeof(InventorySpot), "UnequipItem")] private static void UnequipItem_Prefix(InventorySpot __instance) { if (__instance.inventorySpotIndex >= 3) { ItemEquippable currentItem = __instance.CurrentItem; if (!((Object)(object)currentItem == (Object)null) && !((Object)(object)currentItem == (Object)(object)destroyingItem)) { ExtraSlotMemory.Forget(__instance.inventorySpotIndex); } } } [HarmonyPrefix] [HarmonyPatch(typeof(ItemEquippable), "OnDestroy")] private static void ItemOnDestroy_Prefix(ItemEquippable __instance) { destroyingItem = __instance; } [HarmonyFinalizer] [HarmonyPatch(typeof(ItemEquippable), "OnDestroy")] private static void ItemOnDestroy_Finalizer() { destroyingItem = null; } [HarmonyPostfix] [HarmonyPatch(typeof(RunManager), "ResetProgress")] private static void ResetProgress_Postfix() { ExtraSlotMemory.Clear(); } [HarmonyPostfix] [HarmonyPatch(typeof(RunManager), "LeaveToMainMenu")] private static void LeaveToMainMenu_Postfix() { ExtraSlotMemory.Clear(); } } [HarmonyPatch(typeof(Inventory))] internal static class InventoryPatch { [HarmonyPrefix] [HarmonyPatch("InventorySpotAddAtIndex")] private static void InventorySpotAddAtIndex_Prefix(Inventory __instance, int index) { EnsureCapacity(__instance, index + 1); } [HarmonyPostfix] [HarmonyPatch("InventorySpotAddAtIndex")] private static void InventorySpotAddAtIndex_Postfix(Inventory __instance) { ExtraSlotMemory.OnSpotRegistered(__instance); } private static void EnsureCapacity(Inventory inventory, int count) { List<InventorySpot> inventorySpots = inventory.inventorySpots; while (inventorySpots.Count < count) { inventorySpots.Add(null); } } internal static InventorySpot? GetSpot(Inventory inventory, int index) { List<InventorySpot> inventorySpots = inventory.inventorySpots; if (index < 0 || index >= inventorySpots.Count) { return null; } return inventorySpots[index]; } } [HarmonyPatch(typeof(InventoryUI))] internal static class InventoryUIPatch { [HarmonyPrefix] [HarmonyPatch("LayoutSetup")] private static void LayoutSetup_Prefix(InventoryUI __instance) { try { AddExtraSpots(__instance); } catch (Exception arg) { MoreHotbarSlots.Logger.LogError((object)$"Failed to add extra hotbar slots: {arg}"); } } private static void AddExtraSpots(InventoryUI ui) { //IL_0092: Unknown result type (might be due to invalid IL or missing references) //IL_009d: Unknown result type (might be due to invalid IL or missing references) //IL_00a2: Unknown result type (might be due to invalid IL or missing references) //IL_00a7: 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_0120: Unknown result type (might be due to invalid IL or missing references) //IL_0125: Unknown result type (might be due to invalid IL or missing references) //IL_0154: Unknown result type (might be due to invalid IL or missing references) //IL_0156: Unknown result type (might be due to invalid IL or missing references) //IL_0160: Unknown result type (might be due to invalid IL or missing references) //IL_016a: Unknown result type (might be due to invalid IL or missing references) //IL_016f: Unknown result type (might be due to invalid IL or missing references) //IL_018c: Unknown result type (might be due to invalid IL or missing references) //IL_0191: Unknown result type (might be due to invalid IL or missing references) //IL_0193: Unknown result type (might be due to invalid IL or missing references) int value = MoreHotbarSlotsConfig.SlotCount.Value; List<InventorySpot> list = (from s in ((Component)ui).GetComponentsInChildren<InventorySpot>(true) orderby s.inventorySpotIndex select s).ToList(); if (list.Count < 2) { MoreHotbarSlots.Logger.LogWarning((object)$"Expected the vanilla hotbar slots under InventoryUI, found {list.Count}. Skipping."); } else { if (list.Count >= value) { return; } InventorySpot val = list[0]; InventorySpot val2 = list[list.Count - 1]; Vector3 val3 = ((Component)list[1]).transform.localPosition - ((Component)val).transform.localPosition; int count = list.Count; for (int num = count; num < value; num++) { GameObject val4 = Object.Instantiate<GameObject>(((Component)val2).gameObject, ((Component)val2).transform.parent); ((Object)val4).name = $"{((Object)((Component)val2).gameObject).name} ({num + 1})"; InventorySpot component = val4.GetComponent<InventorySpot>(); component.inventorySpotIndex = num; val4.transform.localPosition = ((Component)val).transform.localPosition + val3 * (float)num; RelabelSpot(val4, val2.inventorySpotIndex, num); list.Add(component); } Vector3 val5 = -val3 * (float)(value - count) / 2f; foreach (InventorySpot item in list) { Transform transform = ((Component)item).transform; transform.localPosition += val5; } MoreHotbarSlots.Logger.LogInfo((object)$"Hotbar expanded to {value} slots."); } } private static void RelabelSpot(GameObject clone, int templateIndex, int index) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_000a: Unknown result type (might be due to invalid IL or missing references) KeyCode keyForSlot = MoreHotbarSlotsConfig.GetKeyForSlot(index); string newValue = (((int)keyForSlot == 0) ? "" : MoreHotbarSlotsConfig.GetKeyLabel(keyForSlot)); string text = $"[inventory{templateIndex + 1}]"; InputGlyphText[] componentsInChildren = clone.GetComponentsInChildren<InputGlyphText>(true); foreach (InputGlyphText val in componentsInChildren) { if (!string.IsNullOrEmpty(val.template) && val.template.Contains(text)) { val.SetTemplate(val.template.Replace(text, newValue)); } } } } [BepInPlugin("DaanDeReus.MoreHotbarSlots", "MoreHotbarSlots", "1.0.0")] public class MoreHotbarSlots : BaseUnityPlugin { internal static MoreHotbarSlots Instance { get; private set; } internal static ManualLogSource Logger => Instance._logger; private ManualLogSource _logger => ((BaseUnityPlugin)this).Logger; internal Harmony? Harmony { get; set; } private void Awake() { Instance = this; ((Component)this).gameObject.transform.parent = null; ((Object)((Component)this).gameObject).hideFlags = (HideFlags)61; MoreHotbarSlotsConfig.Bind(((BaseUnityPlugin)this).Config); Patch(); Logger.LogInfo((object)$"{((BaseUnityPlugin)this).Info.Metadata.GUID} v{((BaseUnityPlugin)this).Info.Metadata.Version} has loaded with {MoreHotbarSlotsConfig.SlotCount.Value} hotbar slots!"); } internal void Patch() { //IL_0019: 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) //IL_0020: Expected O, but got Unknown //IL_0025: Expected O, but got Unknown if (Harmony == null) { Harmony val = new Harmony(((BaseUnityPlugin)this).Info.Metadata.GUID); Harmony val2 = val; Harmony = val; } Harmony.PatchAll(); } internal void Unpatch() { Harmony? harmony = Harmony; if (harmony != null) { harmony.UnpatchSelf(); } } private void Update() { //IL_005f: Unknown result type (might be due to invalid IL or missing references) //IL_0064: 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) //IL_0068: Unknown result type (might be due to invalid IL or missing references) Inventory instance = Inventory.instance; if ((Object)(object)instance == (Object)null || MoreHotbarSlotsConfig.ExtraSlotCount <= 0 || !SemiFunc.NoTextInputsActive() || ((Object)(object)ChatManager.instance != (Object)null && ChatManager.instance.chatActive)) { return; } PlayerAvatar instance2 = PlayerAvatar.instance; if ((Object)(object)instance2 == (Object)null || instance2.isDisabled || instance2.deadSet) { return; } for (int i = 3; i < MoreHotbarSlotsConfig.SlotCount.Value; i++) { KeyCode keyForSlot = MoreHotbarSlotsConfig.GetKeyForSlot(i); if ((int)keyForSlot == 0 || !Input.GetKeyDown(keyForSlot)) { continue; } InventorySpot spot = InventoryPatch.GetSpot(instance, i); if (!((Object)(object)spot == (Object)null)) { try { spot.HandleInput(); } catch (Exception ex) { Logger.LogError((object)$"Slot {i + 1} input failed: {ex.Message}"); } } } } } internal static class MoreHotbarSlotsConfig { internal const int VanillaSlotCount = 3; internal const int MaxSlotCount = 10; internal static ConfigEntry<int> SlotCount { get; private set; } = null; internal static ConfigEntry<string> ExtraSlotKeys { get; private set; } = null; internal static List<KeyCode> ParsedExtraSlotKeys { get; } = new List<KeyCode>(); internal static int ExtraSlotCount => SlotCount.Value - 3; internal static void Bind(ConfigFile config) { //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Expected O, but got Unknown SlotCount = config.Bind<int>("General", "SlotCount", 6, new ConfigDescription("Total number of hotbar slots (vanilla is 3). Takes effect on the next level load.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(3, 10), Array.Empty<object>())); ExtraSlotKeys = config.Bind<string>("General", "ExtraSlotKeys", "4, 5, 6, 7, 8, 9, 0", "Comma-separated keys for slot 4 and up, in order. A single digit means the number row key; anything else is a Unity KeyCode name (e.g. F1, Keypad4, Mouse3). Slots 1-3 keep the game's own keybinds."); ExtraSlotKeys.SettingChanged += delegate { RefreshExtraSlotKeys(); }; RefreshExtraSlotKeys(); } private static void RefreshExtraSlotKeys() { //IL_006a: Unknown result type (might be due to invalid IL or missing references) ParsedExtraSlotKeys.Clear(); string[] array = ExtraSlotKeys.Value.Split(','); foreach (string text in array) { string text2 = text.Trim(); if (text2.Length != 0) { if (text2.Length == 1 && char.IsDigit(text2[0])) { text2 = "Alpha" + text2; } if (Enum.TryParse<KeyCode>(text2, ignoreCase: true, out KeyCode result)) { ParsedExtraSlotKeys.Add(result); continue; } MoreHotbarSlots.Logger.LogWarning((object)$"Invalid key '{text.Trim()}' in ExtraSlotKeys, slot {3 + ParsedExtraSlotKeys.Count + 1} has no key."); ParsedExtraSlotKeys.Add((KeyCode)0); } } } internal static KeyCode GetKeyForSlot(int slotIndex) { //IL_001d: Unknown result type (might be due to invalid IL or missing references) int num = slotIndex - 3; if (num < 0 || num >= ParsedExtraSlotKeys.Count) { return (KeyCode)0; } return ParsedExtraSlotKeys[num]; } internal unsafe static string GetKeyLabel(KeyCode key) { string text = ((object)(*(KeyCode*)(&key))/*cast due to .constrained prefix*/).ToString(); if (text.StartsWith("Alpha")) { return text.Substring("Alpha".Length); } if (text.StartsWith("Keypad") && text.Length == "Keypad".Length + 1) { return text.Substring("Keypad".Length); } return text; } } }