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 ImprovedTABSlot v2.0.0
plugins/Iron.ImprovedTABSlot.dll
Decompiled 18 hours agousing System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using GameNetcodeStuff; using HarmonyLib; using ImprovedTabSlot.Networking; using Microsoft.CodeAnalysis; using Unity.Collections; using Unity.Netcode; 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: AssemblyCompany("Iron.ImprovedTABSlot")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("2.0.0.0")] [assembly: AssemblyInformationalVersion("2.0.0+a1a0ae3f460207ca065f3f4b61d85da3d504388e")] [assembly: AssemblyProduct("ImprovedTABSlot")] [assembly: AssemblyTitle("Iron.ImprovedTABSlot")] [assembly: AssemblyVersion("2.0.0.0")] [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; } } } namespace ImprovedTabSlot { internal static class ItemIdentity { internal const int ManeaterItemIdA = 123984; internal const int ManeaterItemIdB = 819501; public static bool IsManeater(GrabbableObject o) { Item val = o?.itemProperties; if ((Object)(object)val != (Object)null) { if (val.itemId != 123984) { return val.itemId == 819501; } return true; } return false; } public static string Name(GrabbableObject o) { if ((Object)(object)o == (Object)null) { return "<null>"; } if ((Object)(object)o.itemProperties != (Object)null && !string.IsNullOrEmpty(o.itemProperties.itemName)) { return o.itemProperties.itemName; } return ((object)o).GetType().Name; } public static bool IsAllowed(GrabbableObject o) { if ((Object)(object)o == (Object)null) { return false; } PluginConfig cfg = Plugin.Cfg; string text = (((Object)(object)o.itemProperties != (Object)null && o.itemProperties.itemName != null) ? o.itemProperties.itemName.Trim().ToLowerInvariant() : ""); if (cfg.AllowShovel.Value) { if (!HasClass(o, "Shovel")) { switch (text) { case "shovel": case "stop sign": case "yield sign": break; default: goto IL_008c; } } return true; } goto IL_008c; IL_008c: if (cfg.AllowShotgun.Value && (HasClass(o, "ShotgunItem") || text == "shotgun")) { return true; } if (cfg.AllowKnife.Value && (HasClass(o, "KnifeItem") || text.Contains("knife"))) { return true; } if (cfg.AllowKey.Value && (HasClass(o, "KeyItem") || text == "key")) { return true; } if (cfg.AllowClipboard.Value && text == "clipboard") { return true; } if (cfg.AllowStickyNote.Value && text == "sticky note") { return true; } if (cfg.AllowAmmo.Value && (text == "ammo" || text.Contains("shell"))) { return true; } if (cfg.AllowManeater.Value && IsManeater(o)) { return true; } return false; } private static bool HasClass(GrabbableObject o, string simpleName) { Type type = ((object)o).GetType(); while (type != null && type != typeof(GrabbableObject)) { if (type.Name == simpleName) { return true; } type = type.BaseType; } return false; } } [HarmonyPatch(typeof(PlayerControllerB))] internal static class UtilitySlotPatch { internal const int UtilitySlotIndex = 50; [HarmonyPrefix] [HarmonyPatch("FirstEmptyItemSlot", new Type[] { typeof(GrabbableObject) })] private static bool FirstEmptyItemSlot_Prefix(PlayerControllerB __instance, GrabbableObject attemptingGrab, ref int __result) { try { if (!HostSync.Enabled) { return true; } if (!Plugin.Cfg.Enabled.Value) { return true; } if ((Object)(object)attemptingGrab == (Object)null) { return true; } if ((Object)(object)__instance.ItemOnlySlot != (Object)null) { return true; } if (!ItemIdentity.IsAllowed(attemptingGrab)) { return true; } __result = 50; if (Plugin.Cfg.VerboseLogging.Value) { Plugin.Log.LogInfo((object)("Routing '" + ItemIdentity.Name(attemptingGrab) + "' to the utility slot.")); } return false; } catch (Exception arg) { Plugin.Log.LogError((object)$"FirstEmptyItemSlot_Prefix error: {arg}"); return true; } } } [BepInPlugin("Iron.ImprovedTABSlot", "ImprovedTABSlot", "2.0.0")] public class Plugin : BaseUnityPlugin { public const string PLUGIN_GUID = "Iron.ImprovedTABSlot"; public const string PLUGIN_NAME = "ImprovedTABSlot"; public const string PLUGIN_VERSION = "2.0.0"; private Harmony _harmony; internal static Plugin Instance { get; private set; } internal static ManualLogSource Log { get; private set; } internal static PluginConfig Cfg { get; private set; } private void Awake() { //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Expected O, but got Unknown Instance = this; Log = ((BaseUnityPlugin)this).Logger; Cfg = new PluginConfig(((BaseUnityPlugin)this).Config); _harmony = new Harmony("Iron.ImprovedTABSlot"); try { _harmony.PatchAll(typeof(Plugin).Assembly); VerifyPatched(); } catch (Exception arg) { Log.LogError((object)$"Harmony patching failed; the mod is inactive: {arg}"); } Log.LogInfo((object)"ImprovedTABSlot v2.0.0 loaded."); } private void VerifyPatched() { MethodInfo methodInfo = AccessTools.Method(typeof(PlayerControllerB), "FirstEmptyItemSlot", new Type[1] { typeof(GrabbableObject) }, (Type[])null); if (methodInfo == null) { Log.LogError((object)"PlayerControllerB.FirstEmptyItemSlot(GrabbableObject) was not found. The game version may have changed it; the utility-slot patch is INACTIVE."); return; } Patches patchInfo = Harmony.GetPatchInfo((MethodBase)methodInfo); bool flag = patchInfo?.Prefixes != null && patchInfo.Prefixes.Any((Patch p) => p.owner == "Iron.ImprovedTABSlot"); Log.LogInfo((object)(flag ? "Utility-slot patch active on PlayerControllerB.FirstEmptyItemSlot." : "WARNING: utility-slot Prefix did not attach — mod is loaded but inactive.")); } } public class PluginConfig { public readonly ConfigEntry<bool> Enabled; public readonly ConfigEntry<bool> AllowShovel; public readonly ConfigEntry<bool> AllowAmmo; public readonly ConfigEntry<bool> AllowClipboard; public readonly ConfigEntry<bool> AllowStickyNote; public readonly ConfigEntry<bool> AllowKey; public readonly ConfigEntry<bool> AllowShotgun; public readonly ConfigEntry<bool> AllowKnife; public readonly ConfigEntry<bool> AllowManeater; public readonly ConfigEntry<bool> VerboseLogging; public PluginConfig(ConfigFile file) { Enabled = file.Bind<bool>("General", "Enabled", true, "Master switch. When false the mod does nothing and the vanilla utility-slot blacklist is left untouched."); AllowShovel = file.Bind<bool>("Items", "Shovel", true, "Allow the Shovel into the utility slot. (Stop sign / Yield sign reuse the Shovel class and are included.)"); AllowAmmo = file.Bind<bool>("Items", "Ammo", true, "Allow Ammo (shotgun shells) into the utility slot."); AllowClipboard = file.Bind<bool>("Items", "Clipboard", true, "Allow the Clipboard into the utility slot."); AllowStickyNote = file.Bind<bool>("Items", "StickyNote", true, "Allow the Sticky note into the utility slot."); AllowKey = file.Bind<bool>("Items", "Key", true, "Allow Keys into the utility slot."); AllowShotgun = file.Bind<bool>("Items", "Shotgun", true, "Allow the Shotgun into the utility slot. NOTE: the Shotgun is two-handed, so vanilla's two-handed switching lock still applies once it is in your hands (see README)."); AllowKnife = file.Bind<bool>("Items", "Knife", true, "Allow the Kitchen knife into the utility slot."); AllowManeater = file.Bind<bool>("Items", "Maneater", false, "Allow the Maneater (baby cave dweller) into the utility (Tab) slot. The utility slot uses the real grab path (EquipItem) which freezes the creature correctly. WARNING: off by design — it's a balance cheese. Set true only if you specifically want it."); VerboseLogging = file.Bind<bool>("Debug", "VerboseLogging", false, "Log each time an item is routed to the utility slot, and networking state changes."); } } } namespace ImprovedTabSlot.Patches { [HarmonyPatch] internal static class NetworkPatches { [HarmonyPostfix] [HarmonyPatch(typeof(NetworkManager), "Initialize")] private static void AfterNetworkInitialize() { HostSync.Register(); } [HarmonyPostfix] [HarmonyPatch(typeof(GameNetworkManager), "SetInstanceValuesBackToDefault")] private static void OnNetworkTearDown() { HostSync.Unregister(); } [HarmonyPrefix] [HarmonyPatch(typeof(StartOfRound), "Start")] private static void OnLobbyStart(StartOfRound __instance) { if (((NetworkBehaviour)__instance).IsServer) { HostSync.EnableAsHost(); } } [HarmonyPostfix] [HarmonyPatch(typeof(StartOfRound), "OnClientConnect")] private static void OnClientConnected(StartOfRound __instance, ulong __0) { if (((NetworkBehaviour)__instance).IsServer) { HostSync.SendHostPresent(new ulong[1] { __0 }); } } [HarmonyPrefix] [HarmonyPatch(typeof(MenuManager), "Start")] private static void OnMainMenu() { HostSync.Reset(); } } } namespace ImprovedTabSlot.Networking { internal static class HostSync { [CompilerGenerated] private static class <>O { public static HandleNamedMessageDelegate <0>__OnHostPresent; } internal static bool Enabled; private static readonly string HostPresentMessage = "Iron.ImprovedTABSlot|HostPresent"; internal static void Register() { //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Expected O, but got Unknown NetworkManager singleton = NetworkManager.Singleton; if (((singleton != null) ? singleton.CustomMessagingManager : null) != null) { CustomMessagingManager customMessagingManager = singleton.CustomMessagingManager; string hostPresentMessage = HostPresentMessage; object obj = <>O.<0>__OnHostPresent; if (obj == null) { HandleNamedMessageDelegate val = OnHostPresent; <>O.<0>__OnHostPresent = val; obj = (object)val; } customMessagingManager.RegisterNamedMessageHandler(hostPresentMessage, (HandleNamedMessageDelegate)obj); } } internal static void Unregister() { NetworkManager singleton = NetworkManager.Singleton; if (((singleton != null) ? singleton.CustomMessagingManager : null) != null) { singleton.CustomMessagingManager.UnregisterNamedMessageHandler(HostPresentMessage); } } internal static void EnableAsHost() { Enabled = true; if (Plugin.Cfg.VerboseLogging.Value) { Plugin.Log.LogInfo((object)"Host has the mod — utility-slot feature enabled (host)."); } } internal static void Reset() { Enabled = false; } internal static void SendHostPresent(IReadOnlyList<ulong> targets = null) { //IL_004c: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Unknown result type (might be due to invalid IL or missing references) NetworkManager singleton = NetworkManager.Singleton; if (!((Object)(object)singleton == (Object)null) && singleton.IsServer && singleton.CustomMessagingManager != null) { FastBufferWriter val = default(FastBufferWriter); ((FastBufferWriter)(ref val))..ctor(0, (Allocator)2, -1); if (targets == null) { singleton.CustomMessagingManager.SendNamedMessageToAll(HostPresentMessage, val, (NetworkDelivery)3); } else { singleton.CustomMessagingManager.SendNamedMessage(HostPresentMessage, targets, val, (NetworkDelivery)3); } } } private static void OnHostPresent(ulong senderId, FastBufferReader reader) { if (senderId == 0L) { Enabled = true; if (Plugin.Cfg.VerboseLogging.Value) { Plugin.Log.LogInfo((object)"Host has the mod — utility-slot feature enabled (client)."); } } } } }