using System; using System.Collections.Generic; using System.Diagnostics; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using BepInEx; using BepInEx.Bootstrap; using BepInEx.Configuration; using BepInEx.Logging; using GameNetcodeStuff; using HarmonyLib; using HotbarPlus.Input; using Microsoft.CodeAnalysis; using ReservedItemSlotCore; using ReservedItemSlotCore.Config; using ReservedItemSlotCore.Data; using ReservedSlotPositionsForInventory.Cache; using ReservedSlotPositionsForInventory.Compatibility; using ReservedSlotPositionsForInventory.NetcodePatcher; using ReservedSlotPositionsForInventory.Networking; using ReservedSlotPositionsForInventory.Patches; using TooManyEmotes; using TooManyEmotes.Patches; using Unity.Collections; using Unity.Netcode; using UnityEngine; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: AssemblyCompany("ReservedSlotPositionsForInventory")] [assembly: AssemblyConfiguration("Debug")] [assembly: AssemblyFileVersion("1.0.6.0")] [assembly: AssemblyInformationalVersion("1.0.6")] [assembly: AssemblyProduct("ReservedSlotPositionsForInventory")] [assembly: AssemblyTitle("ReservedSlotPositionsForInventory")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.0.6.0")] [module: UnverifiableCode] [module: RefSafetyRules(11)] [module: NetcodePatchedAssembly] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Microsoft.CodeAnalysis.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 ReservedSlotPositionsForInventory { internal static class ConfigManager { private static readonly Dictionary> SlotToItems = new Dictionary>(StringComparer.Ordinal); private static readonly Dictionary> SlotToggles = new Dictionary>(StringComparer.Ordinal); private static readonly Dictionary> SlotItemLists = new Dictionary>(StringComparer.Ordinal); internal static ConfigEntry BoneVisibilityModeConfig { get; private set; } internal static void Initialise(ConfigFile config) { BoneVisibilityModeConfig = config.Bind("General", "Visibility Mode", BoneVisibilityMode.FirstPickedUpMode, "Controls which item stays visible when multiple items share the same bone."); } internal static bool IsSlotDisabled(string slotName) { ConfigEntry value; return SlotToggles.TryGetValue(slotName, out value) && value.Value; } internal static void EnsureSlotConfig(string slotName) { if (!SlotToggles.ContainsKey(slotName)) { SlotToggles[slotName] = ((BaseUnityPlugin)Plugin.Instance).Config.Bind("ReservedSlots", "Disable " + slotName + " reserved slot", false, "Disable the ReservedItemSlotCore reserved slot '" + slotName + "'. Will retain custom positions."); } if (!SlotItemLists.ContainsKey(slotName)) { SlotItemLists[slotName] = ((BaseUnityPlugin)Plugin.Instance).Config.Bind("ReservedSlots", "Items used by " + slotName + " slot", SlotToItems.TryGetValue(slotName, out var value) ? string.Join(", ", value.Values) : string.Empty, "Automatically generated list of items used by '" + slotName + "'. Does nothing if changed and is purely informative."); } } internal static void Register(string slotName, ReservedItemData itemData) { if (!SlotToItems.TryGetValue(slotName, out var value)) { value = new SortedDictionary(StringComparer.Ordinal); SlotToItems[slotName] = value; } string itemName = itemData.itemName; bool flag = HasBoneData(itemData); if (value.TryGetValue(itemName, out var value2) && !value2.EndsWith("[NO BONE DATA]", StringComparison.Ordinal) && !flag) { EnsureSlotConfig(slotName); return; } value[itemName] = (flag ? itemName : (itemName + " [NO BONE DATA]")); EnsureSlotConfig(slotName); SlotItemLists[slotName].Value = string.Join(", ", value.Values); } private static bool HasBoneData(ReservedItemData itemData) { //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Invalid comparison between Unknown and I4 return itemData.showOnPlayerWhileHolstered && (int)itemData.holsteredParentBone > 0; } } internal enum BoneVisibilityMode { FirstPickedUpMode, LastItemHeldMode } [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInPlugin("HQ_Team.ReservedSlotPositionsForInventory", "ReservedSlotPositionsForInventory", "1.0.6")] public sealed class Plugin : BaseUnityPlugin { internal const string ModGuid = "HQ_Team.ReservedSlotPositionsForInventory"; private const string ModName = "ReservedSlotPositionsForInventory"; private const string ModVersion = "1.0.6"; private const string HasTooManyEmotes = "FlipMods.TooManyEmotes"; private const string HasHotbarPlus = "FlipMods.HotbarPlus"; private Harmony _harmony; internal static bool hasTooManyEmotes { get; private set; } internal static Plugin Instance { get; private set; } internal static ManualLogSource Log { get; private set; } private void Awake() { //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_0045: Expected O, but got Unknown hasTooManyEmotes = Chainloader.PluginInfos.ContainsKey("FlipMods.TooManyEmotes"); Instance = this; Log = ((BaseUnityPlugin)this).Logger; ConfigManager.Initialise(((BaseUnityPlugin)this).Config); _harmony = new Harmony("HQ_Team.ReservedSlotPositionsForInventory"); _harmony.PatchAll(typeof(NetworkManagerPatches)); _harmony.PatchAll(typeof(SessionManagerPatches)); _harmony.PatchAll(typeof(ReservedItemSlotDataPatches)); _harmony.PatchAll(typeof(ReservedItemDataPatches)); _harmony.PatchAll(typeof(GrabbableObjectPatches)); _harmony.PatchAll(typeof(StartOfRoundPatches)); _harmony.PatchAll(typeof(FlashlightItemPatches)); _harmony.PatchAll(typeof(ReservedPlayerDataPatches)); _harmony.PatchAll(typeof(PlayerControllerBPatches)); if (Chainloader.PluginInfos.ContainsKey("FlipMods.TooManyEmotes")) { _harmony.PatchAll(typeof(TooManyEmotesCompat)); Log.LogInfo((object)"TooManyEmotes compatibility patch ran"); if (Chainloader.PluginInfos.ContainsKey("FlipMods.HotbarPlus")) { _harmony.PatchAll(typeof(HotbarPlusCompat)); Log.LogInfo((object)"HotbarPlus compatibility patch ran"); } } } } public static class PluginInfo { public const string PLUGIN_GUID = "ReservedSlotPositionsForInventory"; public const string PLUGIN_NAME = "ReservedSlotPositionsForInventory"; public const string PLUGIN_VERSION = "1.0.6"; } } namespace ReservedSlotPositionsForInventory.Patches { internal static class FlashlightItemPatches { [HarmonyPatch(typeof(FlashlightItem), "SwitchFlashlight")] [HarmonyPostfix] private static void SwitchFlashlightPostfix(FlashlightItem __instance, bool on) { if (on) { FlashlightPriorityCache.MarkToggledOn(__instance); } else { FlashlightPriorityCache.MarkToggledOff(__instance); } HolsterVisibilityCache.RefreshItem((GrabbableObject)(object)__instance); if (Plugin.hasTooManyEmotes) { TooManyEmotesCompat.RefreshItemDuringLocalEmote((GrabbableObject)(object)__instance); } } [HarmonyPatch(typeof(FlashlightItem), "PocketFlashlightClientRpc")] [HarmonyPostfix] private static void PocketFlashlightClientRpcPostfix(FlashlightItem __instance, bool stillUsingFlashlight) { if (stillUsingFlashlight) { FlashlightPriorityCache.MarkToggledOn(__instance); } else { FlashlightPriorityCache.MarkToggledOff(__instance); } HolsterVisibilityCache.RefreshItem((GrabbableObject)(object)__instance); if (Plugin.hasTooManyEmotes) { TooManyEmotesCompat.RefreshItemDuringLocalEmote((GrabbableObject)(object)__instance); } } [HarmonyPatch(typeof(FlashlightItem), "DiscardItem")] [HarmonyPostfix] private static void DiscardItemPostfix(FlashlightItem __instance) { FlashlightPriorityCache.MarkToggledOff(__instance); } [HarmonyPatch(typeof(FlashlightItem), "PocketItem")] [HarmonyPostfix] private static void PocketItemPostfix(FlashlightItem __instance) { if (((GrabbableObject)__instance).isPocketed && ((GrabbableObject)__instance).isBeingUsed && __instance.usingPlayerHelmetLight) { FlashlightPriorityCache.MarkToggledOn(__instance); } else { FlashlightPriorityCache.MarkToggledOff(__instance); } HolsterVisibilityCache.RefreshItem((GrabbableObject)(object)__instance); if (Plugin.hasTooManyEmotes) { TooManyEmotesCompat.RefreshItemDuringLocalEmote((GrabbableObject)(object)__instance); } } } internal static class GrabbableObjectPatches { internal const int HiddenFromLocalPlayerLayer = 23; private const int VisibleOnRemotePlayersLayer = 6; private static readonly HashSet LoggedMissingParentItems = new HashSet(); private static readonly HashSet LoggedMissingBones = new HashSet(); internal static bool IsLayerInLocalCameraMask(int layer) { Camera gameplayCamera = StartOfRound.Instance.localPlayerController.gameplayCamera; if ((Object)(object)gameplayCamera == (Object)null) { return false; } return (gameplayCamera.cullingMask & (1 << layer)) != 0; } internal static bool TryGetHolsterData(GrabbableObject item, PlayerControllerB playerController, out ReservedPlayerData playerData, out ReservedItemData itemData) { //IL_007e: Unknown result type (might be due to invalid IL or missing references) //IL_0084: Invalid comparison between Unknown and I4 playerData = null; itemData = null; if ((Object)(object)item == (Object)null || (Object)(object)playerController == (Object)null) { return false; } if (!ReservedPlayerData.allPlayerData.TryGetValue(playerController, out playerData)) { return false; } if (!IsVanillaInventoryOrUtilityItem(item, playerController, playerData)) { return false; } if (playerData.IsItemInReservedItemSlot(item)) { return false; } if (!BoneSlotData.TryGet(item, out itemData)) { return false; } return itemData.showOnPlayerWhileHolstered && (int)itemData.holsteredParentBone > 0; } internal static bool TryGetVisibilityHolsterData(GrabbableObject item, PlayerControllerB playerController, out ReservedItemData itemData) { itemData = null; if ((Object)(object)item == (Object)null || (Object)(object)playerController == (Object)null) { return false; } if (SessionManager.TryGetUnlockedItemData(item, ref itemData) && BoneSlotData.HasBoneData(itemData)) { return true; } return false; } private static void RestoreLayers(GrabbableObject item) { MeshRenderer[] renderers = RendererCache.GetRenderers(item); foreach (MeshRenderer val in renderers) { if (RendererCache.TryGetOriginalLayer(((Component)val).gameObject, out var layer)) { ((Component)val).gameObject.layer = layer; RendererCache.ForgetLayer(((Component)val).gameObject); } } } private static void SetItemVisible(GrabbableObject item, bool visible) { if ((Object)(object)item == (Object)null) { return; } item.EnableItemMeshes(visible); MeshRenderer[] renderers = RendererCache.GetRenderers(item); foreach (MeshRenderer val in renderers) { if ((Object)(object)val != (Object)null) { ((Renderer)val).enabled = visible; } } } internal static GrabbableObject GetEquippedItem(PlayerControllerB playerController) { if ((Object)(object)playerController == (Object)null) { return null; } if (playerController.currentItemSlot == 50) { return playerController.ItemOnlySlot; } int currentItemSlot = playerController.currentItemSlot; if (currentItemSlot < 0 || currentItemSlot >= playerController.ItemSlots.Length) { return null; } return playerController.ItemSlots[currentItemSlot]; } internal static bool IsVanillaInventoryOrUtilityItem(GrabbableObject item, PlayerControllerB playerController, ReservedPlayerData playerData) { if ((Object)(object)item == (Object)null || (Object)(object)playerController == (Object)null || playerData == null) { return false; } if ((Object)(object)playerController.ItemOnlySlot == (Object)(object)item) { return true; } int num = Mathf.Min(playerData.reservedHotbarStartIndex, playerController.ItemSlots.Length); for (int i = 0; i < num; i++) { if ((Object)(object)playerController.ItemSlots[i] == (Object)(object)item) { return true; } } return false; } internal static void Clear() { LoggedMissingParentItems.Clear(); LoggedMissingBones.Clear(); } [HarmonyPatch(typeof(GrabbableObject), "PocketItem")] [HarmonyPostfix] private static void PocketItemPostfix(GrabbableObject __instance) { //IL_01c6: Unknown result type (might be due to invalid IL or missing references) //IL_00f8: Unknown result type (might be due to invalid IL or missing references) //IL_0124: Unknown result type (might be due to invalid IL or missing references) //IL_0152: Unknown result type (might be due to invalid IL or missing references) PlayerControllerB playerHeldBy = __instance.playerHeldBy; if ((Object)(object)playerHeldBy == (Object)null) { return; } if (TryGetHolsterData(__instance, playerHeldBy, out var playerData, out var itemData)) { MeshRenderer[] renderers = RendererCache.GetRenderers(__instance); foreach (MeshRenderer val in renderers) { RendererCache.RememberLayer(((Component)val).gameObject); if (playerData.isLocalPlayer) { if (IsLayerInLocalCameraMask(((Component)val).gameObject.layer)) { ((Component)val).gameObject.layer = 23; } } else if (!IsLayerInLocalCameraMask(((Component)val).gameObject.layer)) { ((Component)val).gameObject.layer = 6; } } if (__instance.isPocketed) { playerData.boneMap.CreateBoneMap(((Component)playerData.playerController).transform, (List)null); Transform bone = playerData.boneMap.GetBone(itemData.holsteredParentBone); if ((Object)(object)bone == (Object)null) { string item = $"{__instance.itemProperties.itemName}:{itemData.holsteredParentBone}"; if (LoggedMissingBones.Add(item)) { Plugin.Log.LogWarning((object)$"Failed to find bone '{itemData.holsteredParentBone}' for item '{__instance.itemProperties.itemName}'."); } } else { __instance.parentObject = bone; ((Component)__instance).transform.SetParent(bone, false); __instance.EnableItemMeshes(true); } } } if (__instance.isPocketed && TryGetVisibilityHolsterData(__instance, playerHeldBy, out var itemData2)) { HolsterOrderNetwork.EnsureFirstPickupOrder(__instance); HolsterVisibilityCache.RegisterPocketedItem(playerHeldBy, itemData2.holsteredParentBone, __instance); } } [HarmonyPatch(typeof(GrabbableObject), "EquipItem")] [HarmonyPatch(typeof(StunGrenadeItem), "EquipItem")] [HarmonyPostfix] private static void EquipItemPostfix(GrabbableObject __instance) { HolsterVisibilityCache.RemoveItem(__instance); if (!TryGetHolsterData(__instance, __instance.playerHeldBy, out var playerData, out var _)) { SetItemVisible(__instance, visible: true); return; } RestoreLayers(__instance); Transform val = (__instance.parentObject = (playerData.isLocalPlayer ? __instance.playerHeldBy.localItemHolder : __instance.playerHeldBy.serverItemHolder)); if ((Object)(object)val != (Object)null) { ((Component)__instance).transform.SetParent(val, false); } SetItemVisible(__instance, visible: true); } [HarmonyPatch(typeof(GrabbableObject), "DiscardItem")] [HarmonyPostfix] private static void DiscardItemPostfix(GrabbableObject __instance) { if (!((Object)(object)__instance == (Object)null)) { RestoreLayers(__instance); HolsterOrderNetwork.NotifyDroppedItem(__instance); HolsterVisibilityCache.RemoveItemAndForgetPriority(__instance); } } [HarmonyPatch(typeof(GrabbableObject), "LateUpdate")] [HarmonyPostfix] private static void LateUpdatePostfix(GrabbableObject __instance) { //IL_00f3: Unknown result type (might be due to invalid IL or missing references) //IL_00f9: Unknown result type (might be due to invalid IL or missing references) //IL_00fe: Unknown result type (might be due to invalid IL or missing references) //IL_0103: Unknown result type (might be due to invalid IL or missing references) //IL_0115: 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_0121: Unknown result type (might be due to invalid IL or missing references) //IL_0126: Unknown result type (might be due to invalid IL or missing references) //IL_012b: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)__instance == (Object)null || (Object)(object)__instance.playerHeldBy == (Object)null || !__instance.isHeld || !TryGetHolsterData(__instance, __instance.playerHeldBy, out var playerData, out var itemData) || (Object)(object)__instance == (Object)(object)GetEquippedItem(playerData.playerController)) { return; } if ((Object)(object)__instance.parentObject == (Object)null) { int instanceID = ((Object)__instance).GetInstanceID(); if (LoggedMissingParentItems.Add(instanceID)) { Plugin.Log.LogDebug((object)("parentObject is null for '" + __instance.itemProperties.itemName + "' on player '" + __instance.playerHeldBy.playerUsername + "'.")); } } else { Transform transform = ((Component)__instance.parentObject).transform; ((Component)__instance).transform.rotation = transform.rotation * Quaternion.Euler(itemData.holsteredRotationOffset); ((Component)__instance).transform.position = transform.position + transform.rotation * itemData.holsteredPositionOffset; } } } [HarmonyPatch] internal static class NetworkManagerPatches { [HarmonyPatch(typeof(NetworkManager), "Initialize")] [HarmonyPostfix] private static void InitializePostfix() { HolsterOrderNetwork.RegisterMessages(); } [HarmonyPatch(typeof(GameNetworkManager), "SetInstanceValuesBackToDefault")] [HarmonyPostfix] private static void ResetPostfix() { HolsterOrderNetwork.UnregisterMessages(); } } internal class PlayerControllerBPatches { [HarmonyPatch(typeof(PlayerControllerB), "BeginGrabObject")] [HarmonyPrefix] [HarmonyAfter(new string[] { "ReservedItemSlotCore" })] private static void BeginGrabObjectPrefix(PlayerControllerB __instance) { if (!((Object)(object)__instance == (Object)null) && __instance.currentItemSlot == 50 && ReservedPlayerData.allPlayerData.TryGetValue(__instance, out var value) && value.isGrabbingReservedItem) { value.previousHotbarIndex = 50; } } [HarmonyPatch(typeof(PlayerControllerB), "GrabObjectClientRpc")] [HarmonyPrefix] [HarmonyAfter(new string[] { "ReservedItemSlotCore" })] private static void GrabObjectClientRpcPrefix(bool grabValidated, PlayerControllerB __instance) { if (grabValidated && !((Object)(object)__instance == (Object)null) && __instance.currentItemSlot == 50 && ReservedPlayerData.allPlayerData.TryGetValue(__instance, out var value) && value.isGrabbingReservedItem) { value.previousHotbarIndex = 50; } } } internal static class BoneSlotData { private static readonly Dictionary CopiedData = new Dictionary(StringComparer.Ordinal); internal static bool TryGet(GrabbableObject item, out ReservedItemData itemData) { itemData = null; string text = item?.itemProperties?.itemName; return text != null && CopiedData.TryGetValue(text, out itemData); } internal static bool TryGet(string itemName, out ReservedItemData itemData) { itemData = null; return !string.IsNullOrEmpty(itemName) && CopiedData.TryGetValue(itemName, out itemData); } internal static void Set(string itemName, ReservedItemData itemData) { if (string.IsNullOrEmpty(itemName) || itemData == null) { return; } bool flag = HasBoneData(itemData); if (!CopiedData.TryGetValue(itemName, out var value)) { CopiedData[itemName] = itemData; return; } bool flag2 = HasBoneData(value); if (!flag2 || flag) { if (!flag2 && flag) { CopiedData[itemName] = itemData; } else if (!(flag2 && flag)) { } } } internal static bool HasBoneData(ReservedItemData itemData) { //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Invalid comparison between Unknown and I4 return itemData != null && itemData.showOnPlayerWhileHolstered && (int)itemData.holsteredParentBone > 0; } } [HarmonyPatch(typeof(ReservedItemData))] [HarmonyPatch(/*Could not decode attribute arguments.*/)] [HarmonyPatch(new Type[] { typeof(string), typeof(PlayerBone), typeof(Vector3), typeof(Vector3) })] internal static class ReservedItemDataPatches { [HarmonyPostfix] private static void Postfix(ReservedItemData __instance, string itemName) { BoneSlotData.Set(itemName, __instance); } } internal static class ReservedItemSlotDataPatches { [HarmonyPatch(typeof(ReservedItemSlotData), "AddItemToReservedItemSlot", new Type[] { typeof(ReservedItemData) })] [HarmonyPrefix] private static void Prefix(ReservedItemSlotData __instance, ReservedItemData itemData) { if (itemData != null && !string.IsNullOrEmpty(itemData.itemName)) { ConfigManager.Register(__instance.slotName, itemData); } } [HarmonyPatch(typeof(ReservedItemSlotData), "CreateReservedItemSlotData")] [HarmonyPostfix] private static void Postfix(ReservedItemSlotData __result) { if (__result != null) { ConfigManager.EnsureSlotConfig(__result.slotName); } } } internal static class ReservedPlayerDataPatches { [HarmonyPatch(/*Could not decode attribute arguments.*/)] [HarmonyPostfix] private static void CurrentlySelectedItemGetterPostfix(ReservedPlayerData __instance, ref GrabbableObject __result) { if (__instance != null && !((Object)(object)__instance.playerController == (Object)null) && __instance.currentItemSlot == 50) { __result = __instance.playerController.ItemOnlySlot; } } [HarmonyPatch(/*Could not decode attribute arguments.*/)] [HarmonyPostfix] private static void PreviouslyHeldItemGetterPostfix(ReservedPlayerData __instance, ref GrabbableObject __result) { if (__instance != null && !((Object)(object)__instance.playerController == (Object)null) && __instance.previousHotbarIndex == 50) { __result = __instance.playerController.ItemOnlySlot; } } } internal static class SessionManagerPatches { [HarmonyPatch(typeof(SessionManager), "UnlockReservedItemSlot")] [HarmonyPrefix] private static bool Prefix(ReservedItemSlotData itemSlotData) { if (ConfigSettings.enablePurchasingItemSlots.Value || itemSlotData == null) { return true; } return !ConfigManager.IsSlotDisabled(itemSlotData.slotName); } [HarmonyPatch(/*Could not decode attribute arguments.*/)] [HarmonyPostfix] private static void TryGetUnlockedItemDataPostfix(GrabbableObject item, ref ReservedItemData itemData, ref bool __result) { if ((!__result || !BoneSlotData.HasBoneData(itemData)) && BoneSlotData.TryGet(item, out var itemData2) && BoneSlotData.HasBoneData(itemData2)) { itemData = itemData2; __result = true; } } [HarmonyPatch(/*Could not decode attribute arguments.*/)] [HarmonyPostfix] private static void TryGetUnlockedItemDataPostfix(string itemName, ref ReservedItemData itemData, ref bool __result) { if ((!__result || !BoneSlotData.HasBoneData(itemData)) && BoneSlotData.TryGet(itemName, out var itemData2) && BoneSlotData.HasBoneData(itemData2)) { itemData = itemData2; __result = true; } } } internal static class StartOfRoundPatches { [HarmonyPatch(typeof(StartOfRound), "OnDestroy")] [HarmonyPostfix] private static void Postfix() { Stopwatch stopwatch = Stopwatch.StartNew(); Plugin.Log.LogInfo((object)"Starting cleanup."); GrabbableObjectPatches.Clear(); Plugin.Log.LogDebug((object)"GrabbableObjectPatches caches cleared"); RendererCache.Clear(); Plugin.Log.LogDebug((object)"Renderer cache cleared"); HolsterVisibilityCache.Clear(); Plugin.Log.LogDebug((object)"HolsterVisibility cache cleared"); HolsterOrderNetwork.UnregisterMessages(); Plugin.Log.LogDebug((object)"HolsterOrderNetwork cache cleared"); FlashlightPriorityCache.Clear(); Plugin.Log.LogDebug((object)"FlashlightPriority cache cleared"); stopwatch.Stop(); Plugin.Log.LogInfo((object)$"Cleanup complete in {stopwatch.Elapsed.TotalMilliseconds:F3} ms"); } } } namespace ReservedSlotPositionsForInventory.Networking { internal static class HolsterOrderNetwork { [CompilerGenerated] private static class <>O { public static HandleNamedMessageDelegate <0>__OnSetFirstPickupOrderServerRpc; public static HandleNamedMessageDelegate <1>__OnSetFirstPickupOrderClientRpc; public static HandleNamedMessageDelegate <2>__OnForgetFirstPickupOrderServerRpc; public static HandleNamedMessageDelegate <3>__OnForgetFirstPickupOrderClientRpc; } private static readonly string SetFirstPickupOrderServerRpcMessage = "HQ_Team.ReservedSlotPositionsForInventory.SetFirstPickupOrderServerRpc"; private static readonly string SetFirstPickupOrderClientRpcMessage = "HQ_Team.ReservedSlotPositionsForInventory.SetFirstPickupOrderClientRpc"; private static readonly string ForgetFirstPickupOrderServerRpcMessage = "HQ_Team.ReservedSlotPositionsForInventory.ForgetFirstPickupOrderServerRpc"; private static readonly string ForgetFirstPickupOrderClientRpcMessage = "HQ_Team.ReservedSlotPositionsForInventory.ForgetFirstPickupOrderClientRpc"; private static long _nextLocalOrder; private static bool _registered; internal static void RegisterMessages() { //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Expected O, but got Unknown //IL_0069: Unknown result type (might be due to invalid IL or missing references) //IL_006e: Unknown result type (might be due to invalid IL or missing references) //IL_0074: Expected O, but got Unknown //IL_0090: Unknown result type (might be due to invalid IL or missing references) //IL_0095: Unknown result type (might be due to invalid IL or missing references) //IL_009b: Expected O, but got Unknown //IL_00b7: Unknown result type (might be due to invalid IL or missing references) //IL_00bc: Unknown result type (might be due to invalid IL or missing references) //IL_00c2: Expected O, but got Unknown if (!_registered && NetworkManager.Singleton.CustomMessagingManager != null) { CustomMessagingManager customMessagingManager = NetworkManager.Singleton.CustomMessagingManager; string setFirstPickupOrderServerRpcMessage = SetFirstPickupOrderServerRpcMessage; object obj = <>O.<0>__OnSetFirstPickupOrderServerRpc; if (obj == null) { HandleNamedMessageDelegate val = OnSetFirstPickupOrderServerRpc; <>O.<0>__OnSetFirstPickupOrderServerRpc = val; obj = (object)val; } customMessagingManager.RegisterNamedMessageHandler(setFirstPickupOrderServerRpcMessage, (HandleNamedMessageDelegate)obj); string setFirstPickupOrderClientRpcMessage = SetFirstPickupOrderClientRpcMessage; object obj2 = <>O.<1>__OnSetFirstPickupOrderClientRpc; if (obj2 == null) { HandleNamedMessageDelegate val2 = OnSetFirstPickupOrderClientRpc; <>O.<1>__OnSetFirstPickupOrderClientRpc = val2; obj2 = (object)val2; } customMessagingManager.RegisterNamedMessageHandler(setFirstPickupOrderClientRpcMessage, (HandleNamedMessageDelegate)obj2); string forgetFirstPickupOrderServerRpcMessage = ForgetFirstPickupOrderServerRpcMessage; object obj3 = <>O.<2>__OnForgetFirstPickupOrderServerRpc; if (obj3 == null) { HandleNamedMessageDelegate val3 = OnForgetFirstPickupOrderServerRpc; <>O.<2>__OnForgetFirstPickupOrderServerRpc = val3; obj3 = (object)val3; } customMessagingManager.RegisterNamedMessageHandler(forgetFirstPickupOrderServerRpcMessage, (HandleNamedMessageDelegate)obj3); string forgetFirstPickupOrderClientRpcMessage = ForgetFirstPickupOrderClientRpcMessage; object obj4 = <>O.<3>__OnForgetFirstPickupOrderClientRpc; if (obj4 == null) { HandleNamedMessageDelegate val4 = OnForgetFirstPickupOrderClientRpc; <>O.<3>__OnForgetFirstPickupOrderClientRpc = val4; obj4 = (object)val4; } customMessagingManager.RegisterNamedMessageHandler(forgetFirstPickupOrderClientRpcMessage, (HandleNamedMessageDelegate)obj4); _registered = true; _nextLocalOrder = 0L; } } internal static void UnregisterMessages() { if (_registered && NetworkManager.Singleton.CustomMessagingManager != null) { CustomMessagingManager customMessagingManager = NetworkManager.Singleton.CustomMessagingManager; customMessagingManager.UnregisterNamedMessageHandler(SetFirstPickupOrderServerRpcMessage); customMessagingManager.UnregisterNamedMessageHandler(SetFirstPickupOrderClientRpcMessage); customMessagingManager.UnregisterNamedMessageHandler(ForgetFirstPickupOrderServerRpcMessage); customMessagingManager.UnregisterNamedMessageHandler(ForgetFirstPickupOrderClientRpcMessage); _registered = false; _nextLocalOrder = 0L; } } internal static void EnsureFirstPickupOrder(GrabbableObject item) { //IL_0082: Unknown result type (might be due to invalid IL or missing references) //IL_0078: Unknown result type (might be due to invalid IL or missing references) if (HolsterVisibilityCache.UsesSyncedFirstPickupOrdering && TryGetNetworkObjectReference(item, out var itemReference) && (ConfigManager.BoneVisibilityModeConfig.Value == BoneVisibilityMode.LastItemHeldMode || !HolsterVisibilityCache.HasSyncedFirstPickupOrder(((NetworkObjectReference)(ref itemReference)).NetworkObjectId))) { long order = _nextLocalOrder++; HolsterVisibilityCache.ApplySyncedFirstPickupOrder(((NetworkObjectReference)(ref itemReference)).NetworkObjectId, order); if (NetworkManager.Singleton.IsServer) { SendSetFirstPickupOrderClientRpc(itemReference, order); } else { SendSetFirstPickupOrderServerRpc(itemReference, order); } } } internal static void NotifyDroppedItem(GrabbableObject item) { //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Unknown result type (might be due to invalid IL or missing references) if (TryGetNetworkObjectReference(item, out var itemReference)) { if (NetworkManager.Singleton.IsServer) { HolsterVisibilityCache.RemoveSyncedFirstPickupOrder(((NetworkObjectReference)(ref itemReference)).NetworkObjectId); SendForgetFirstPickupOrderClientRpc(itemReference); } else { SendForgetFirstPickupOrderServerRpc(itemReference); } } } private static void SendSetFirstPickupOrderServerRpc(NetworkObjectReference itemReference, long order) { //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Unknown result type (might be due to invalid IL or missing references) FastBufferWriter val = default(FastBufferWriter); ((FastBufferWriter)(ref val))..ctor(256, (Allocator)2, -1); try { ((FastBufferWriter)(ref val)).WriteNetworkSerializable(ref itemReference); ((FastBufferWriter)(ref val)).WriteValueSafe(ref order, default(ForPrimitives)); NetworkManager.Singleton.CustomMessagingManager.SendNamedMessage(SetFirstPickupOrderServerRpcMessage, 0uL, val, (NetworkDelivery)2); } finally { ((IDisposable)(FastBufferWriter)(ref val)).Dispose(); } } private static void SendSetFirstPickupOrderClientRpc(NetworkObjectReference itemReference, long order) { //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Unknown result type (might be due to invalid IL or missing references) FastBufferWriter val = default(FastBufferWriter); ((FastBufferWriter)(ref val))..ctor(256, (Allocator)2, -1); try { ((FastBufferWriter)(ref val)).WriteNetworkSerializable(ref itemReference); ((FastBufferWriter)(ref val)).WriteValueSafe(ref order, default(ForPrimitives)); NetworkManager.Singleton.CustomMessagingManager.SendNamedMessageToAll(SetFirstPickupOrderClientRpcMessage, val, (NetworkDelivery)2); } finally { ((IDisposable)(FastBufferWriter)(ref val)).Dispose(); } } private static void SendForgetFirstPickupOrderServerRpc(NetworkObjectReference itemReference) { //IL_002a: Unknown result type (might be due to invalid IL or missing references) FastBufferWriter val = default(FastBufferWriter); ((FastBufferWriter)(ref val))..ctor(128, (Allocator)2, -1); try { ((FastBufferWriter)(ref val)).WriteNetworkSerializable(ref itemReference); NetworkManager.Singleton.CustomMessagingManager.SendNamedMessage(ForgetFirstPickupOrderServerRpcMessage, 0uL, val, (NetworkDelivery)2); } finally { ((IDisposable)(FastBufferWriter)(ref val)).Dispose(); } } private static void SendForgetFirstPickupOrderClientRpc(NetworkObjectReference itemReference) { //IL_0028: Unknown result type (might be due to invalid IL or missing references) FastBufferWriter val = default(FastBufferWriter); ((FastBufferWriter)(ref val))..ctor(128, (Allocator)2, -1); try { ((FastBufferWriter)(ref val)).WriteNetworkSerializable(ref itemReference); NetworkManager.Singleton.CustomMessagingManager.SendNamedMessageToAll(ForgetFirstPickupOrderClientRpcMessage, val, (NetworkDelivery)2); } finally { ((IDisposable)(FastBufferWriter)(ref val)).Dispose(); } } private static void OnSetFirstPickupOrderServerRpc(ulong senderId, FastBufferReader reader) { //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_0041: Unknown result type (might be due to invalid IL or missing references) if (!NetworkManager.Singleton.IsServer) { return; } try { NetworkObjectReference itemReference = default(NetworkObjectReference); ((FastBufferReader)(ref reader)).ReadNetworkSerializable(ref itemReference); long order = default(long); ((FastBufferReader)(ref reader)).ReadValueSafe(ref order, default(ForPrimitives)); HolsterVisibilityCache.ApplySyncedFirstPickupOrder(((NetworkObjectReference)(ref itemReference)).NetworkObjectId, order); SendSetFirstPickupOrderClientRpc(itemReference, order); } catch (Exception arg) { Plugin.Log.LogError((object)$"SetFirstPickupOrderServerRpc: {arg}"); } } private static void OnSetFirstPickupOrderClientRpc(ulong senderId, FastBufferReader reader) { //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Unknown result type (might be due to invalid IL or missing references) if (senderId != 0) { return; } try { NetworkObjectReference val = default(NetworkObjectReference); ((FastBufferReader)(ref reader)).ReadNetworkSerializable(ref val); long order = default(long); ((FastBufferReader)(ref reader)).ReadValueSafe(ref order, default(ForPrimitives)); HolsterVisibilityCache.ApplySyncedFirstPickupOrder(((NetworkObjectReference)(ref val)).NetworkObjectId, order); } catch (Exception arg) { Plugin.Log.LogError((object)$"SetFirstPickupOrderClientRpc: {arg}"); } } private static void OnForgetFirstPickupOrderServerRpc(ulong senderId, FastBufferReader reader) { //IL_002d: Unknown result type (might be due to invalid IL or missing references) if (!NetworkManager.Singleton.IsServer) { return; } try { NetworkObjectReference itemReference = default(NetworkObjectReference); ((FastBufferReader)(ref reader)).ReadNetworkSerializable(ref itemReference); HolsterVisibilityCache.RemoveSyncedFirstPickupOrder(((NetworkObjectReference)(ref itemReference)).NetworkObjectId); SendForgetFirstPickupOrderClientRpc(itemReference); } catch (Exception arg) { Plugin.Log.LogError((object)$"ForgetFirstPickupOrderServerRpc: {arg}"); } } private static void OnForgetFirstPickupOrderClientRpc(ulong senderId, FastBufferReader reader) { if (senderId != 0) { return; } try { NetworkObjectReference val = default(NetworkObjectReference); ((FastBufferReader)(ref reader)).ReadNetworkSerializable(ref val); HolsterVisibilityCache.RemoveSyncedFirstPickupOrder(((NetworkObjectReference)(ref val)).NetworkObjectId); } catch (Exception arg) { Plugin.Log.LogError((object)$"ForgetFirstPickupOrderClientRpc: {arg}"); } } private static bool TryGetNetworkObjectReference(GrabbableObject item, out NetworkObjectReference itemReference) { //IL_0002: 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_0044: Unknown result type (might be due to invalid IL or missing references) itemReference = default(NetworkObjectReference); if ((Object)(object)item == (Object)null || (Object)(object)((NetworkBehaviour)item).NetworkObject == (Object)null || !((NetworkBehaviour)item).NetworkObject.IsSpawned) { return false; } itemReference = NetworkObjectReference.op_Implicit(((NetworkBehaviour)item).NetworkObject); return true; } } } namespace ReservedSlotPositionsForInventory.Compatibility { [HarmonyPatch(typeof(Keybinds), "OnPressItemSlotHotkeyAction")] internal static class HotbarPlusCompat { [HarmonyPrefix] private static bool Prefix() { EmoteControllerPlayer emoteControllerLocal = EmoteControllerPlayer.emoteControllerLocal; return (Object)(object)emoteControllerLocal == (Object)null || !((EmoteController)emoteControllerLocal).IsPerformingCustomEmote(); } } internal static class TooManyEmotesCompat { internal static bool IsLocalCustomEmoteActive { get; private set; } internal static void RefreshItemDuringLocalEmote(GrabbableObject item) { if (!IsLocalCustomEmoteActive || (Object)(object)item == (Object)null) { return; } ReservedPlayerData localPlayerData = ReservedPlayerData.localPlayerData; if (localPlayerData == null) { return; } PlayerControllerB playerController = localPlayerData.playerController; if ((Object)(object)playerController == (Object)null || (Object)(object)item.playerHeldBy != (Object)(object)playerController) { return; } int num = Mathf.Min(localPlayerData.reservedHotbarStartIndex, playerController.ItemSlots.Length); bool flag = false; for (int i = 0; i < num; i++) { if (!((Object)(object)playerController.ItemSlots[i] != (Object)(object)item)) { if (i == playerController.currentItemSlot) { return; } flag = true; break; } } if (!flag && (Object)(object)playerController.ItemOnlySlot == (Object)(object)item) { if (playerController.currentItemSlot == 50) { return; } flag = true; } if (!flag || !GrabbableObjectPatches.TryGetHolsterData(item, playerController, out var _, out var _)) { return; } MeshRenderer[] renderers = RendererCache.GetRenderers(item); foreach (MeshRenderer val in renderers) { ((Renderer)val).enabled = true; if (RendererCache.TryGetOriginalLayer(((Component)val).gameObject, out var layer) && !GrabbableObjectPatches.IsLayerInLocalCameraMask(((Component)val).gameObject.layer)) { ((Component)val).gameObject.layer = layer; } } } [HarmonyPatch(typeof(ThirdPersonEmoteController), "OnStartCustomEmoteLocal")] [HarmonyPostfix] private static void OnStartCustomEmoteLocalPostfix() { IsLocalCustomEmoteActive = true; ReservedPlayerData localPlayerData = ReservedPlayerData.localPlayerData; if (localPlayerData == null) { return; } PlayerControllerB playerController = localPlayerData.playerController; if ((Object)(object)playerController == (Object)null) { return; } int num = Mathf.Min(localPlayerData.reservedHotbarStartIndex, playerController.ItemSlots.Length); ReservedPlayerData playerData; ReservedItemData itemData; for (int i = 0; i < num; i++) { if (i == playerController.currentItemSlot) { continue; } GrabbableObject val = playerController.ItemSlots[i]; if ((Object)(object)val == (Object)null || !GrabbableObjectPatches.TryGetHolsterData(val, playerController, out playerData, out itemData)) { continue; } MeshRenderer[] renderers = RendererCache.GetRenderers(val); foreach (MeshRenderer val2 in renderers) { ((Renderer)val2).enabled = true; if (RendererCache.TryGetOriginalLayer(((Component)val2).gameObject, out var layer) && !GrabbableObjectPatches.IsLayerInLocalCameraMask(((Component)val2).gameObject.layer)) { ((Component)val2).gameObject.layer = layer; } } } if (playerController.currentItemSlot == 50) { return; } GrabbableObject itemOnlySlot = playerController.ItemOnlySlot; if ((Object)(object)itemOnlySlot == (Object)null || !GrabbableObjectPatches.TryGetHolsterData(itemOnlySlot, playerController, out playerData, out itemData)) { return; } MeshRenderer[] renderers2 = RendererCache.GetRenderers(itemOnlySlot); foreach (MeshRenderer val3 in renderers2) { ((Renderer)val3).enabled = true; if (RendererCache.TryGetOriginalLayer(((Component)val3).gameObject, out var layer2) && !GrabbableObjectPatches.IsLayerInLocalCameraMask(((Component)val3).gameObject.layer)) { ((Component)val3).gameObject.layer = layer2; } } } [HarmonyPatch(typeof(ThirdPersonEmoteController), "OnStopCustomEmoteLocal")] [HarmonyPostfix] private static void OnStopCustomEmoteLocalPostfix() { IsLocalCustomEmoteActive = false; ReservedPlayerData localPlayerData = ReservedPlayerData.localPlayerData; if (localPlayerData == null) { return; } PlayerControllerB playerController = localPlayerData.playerController; if ((Object)(object)playerController == (Object)null) { return; } int num = Mathf.Min(localPlayerData.reservedHotbarStartIndex, playerController.ItemSlots.Length); ReservedPlayerData playerData; ReservedItemData itemData; int layer; for (int i = 0; i < num; i++) { if (i == playerController.currentItemSlot) { continue; } GrabbableObject val = playerController.ItemSlots[i]; if ((Object)(object)val == (Object)null || !GrabbableObjectPatches.TryGetHolsterData(val, playerController, out playerData, out itemData)) { continue; } MeshRenderer[] renderers = RendererCache.GetRenderers(val); foreach (MeshRenderer val2 in renderers) { if (RendererCache.TryGetOriginalLayer(((Component)val2).gameObject, out layer) && GrabbableObjectPatches.IsLayerInLocalCameraMask(((Component)val2).gameObject.layer)) { ((Component)val2).gameObject.layer = 23; } } HolsterVisibilityCache.RefreshItem(val); } if (playerController.currentItemSlot == 50) { return; } GrabbableObject itemOnlySlot = playerController.ItemOnlySlot; if ((Object)(object)itemOnlySlot == (Object)null || !GrabbableObjectPatches.TryGetHolsterData(itemOnlySlot, playerController, out playerData, out itemData)) { return; } MeshRenderer[] renderers2 = RendererCache.GetRenderers(itemOnlySlot); foreach (MeshRenderer val3 in renderers2) { if (RendererCache.TryGetOriginalLayer(((Component)val3).gameObject, out layer) && GrabbableObjectPatches.IsLayerInLocalCameraMask(((Component)val3).gameObject.layer)) { ((Component)val3).gameObject.layer = 23; } } HolsterVisibilityCache.RefreshItem(itemOnlySlot); } [HarmonyPatch(typeof(PlayerControllerB), "UseUtilitySlot_performed")] [HarmonyPrefix] private static bool UseUtilitySlot_performedPrefix(PlayerControllerB __instance) { if (!IsLocalCustomEmoteActive) { return true; } PlayerControllerB val = StartOfRound.Instance?.localPlayerController; if ((Object)(object)__instance != (Object)(object)val) { return true; } return false; } } } namespace ReservedSlotPositionsForInventory.Cache { internal static class FlashlightPriorityCache { private static readonly Dictionary ToggleOrderByItemId = new Dictionary(); private static long NextToggleOrder; internal static void MarkToggledOn(FlashlightItem flashlight) { if (!((Object)(object)flashlight == (Object)null)) { ToggleOrderByItemId[((Object)flashlight).GetInstanceID()] = NextToggleOrder; NextToggleOrder++; } } internal static void MarkToggledOff(FlashlightItem flashlight) { if (!((Object)(object)flashlight == (Object)null)) { ToggleOrderByItemId.Remove(((Object)flashlight).GetInstanceID()); } } internal static bool TryGetToggleOrder(FlashlightItem flashlight, out long order) { order = 0L; return (Object)(object)flashlight != (Object)null && ToggleOrderByItemId.TryGetValue(((Object)flashlight).GetInstanceID(), out order); } internal static void Clear() { ToggleOrderByItemId.Clear(); NextToggleOrder = 0L; } } internal readonly struct HolsterBoneKey : IEquatable { private readonly int _playerId; private readonly PlayerBone _bone; internal HolsterBoneKey(PlayerControllerB playerController, PlayerBone bone) { //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Unknown result type (might be due to invalid IL or missing references) _playerId = ((Object)playerController).GetInstanceID(); _bone = bone; } public bool Equals(HolsterBoneKey other) { //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Unknown result type (might be due to invalid IL or missing references) return _playerId == other._playerId && _bone == other._bone; } public override bool Equals(object obj) { return obj is HolsterBoneKey other && Equals(other); } public override int GetHashCode() { //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Expected I4, but got Unknown return HashCode.Combine(_playerId, (int)_bone); } } internal static class HolsterVisibilityCache { internal static readonly Dictionary> ItemsByBone = new Dictionary>(); internal static readonly Dictionary KeyByItemId = new Dictionary(); internal static readonly Dictionary SyncedFirstPickupOrderByNetworkObjectId = new Dictionary(); internal static bool UsesSyncedFirstPickupOrdering => ConfigManager.BoneVisibilityModeConfig.Value == BoneVisibilityMode.FirstPickedUpMode || ConfigManager.BoneVisibilityModeConfig.Value == BoneVisibilityMode.LastItemHeldMode; internal static void RegisterPocketedItem(PlayerControllerB playerController, PlayerBone bone, GrabbableObject item) { //IL_000b: Unknown result type (might be due to invalid IL or missing references) int instanceID = ((Object)item).GetInstanceID(); HolsterBoneKey holsterBoneKey = new HolsterBoneKey(playerController, bone); if (KeyByItemId.TryGetValue(instanceID, out var value) && !value.Equals(holsterBoneKey) && ItemsByBone.TryGetValue(value, out var value2)) { RemoveDeadAndItem(value2, item); if (value2.Count == 0) { ItemsByBone.Remove(value); } else { RefreshVisibleItem(value2); } } if (!ItemsByBone.TryGetValue(holsterBoneKey, out var value3)) { value3 = new List(); ItemsByBone[holsterBoneKey] = value3; } RemoveDeadAndItem(value3, item); value3.Add(item); KeyByItemId[instanceID] = holsterBoneKey; RefreshVisibleItem(value3); } internal static void RemoveItem(GrabbableObject item) { if ((Object)(object)item == (Object)null) { return; } int instanceID = ((Object)item).GetInstanceID(); if (!KeyByItemId.TryGetValue(instanceID, out var value)) { SetItemVisible(item, visible: true); return; } KeyByItemId.Remove(instanceID); if (!ItemsByBone.TryGetValue(value, out var value2)) { SetItemVisible(item, visible: true); return; } RemoveDeadAndItem(value2, item); SetItemVisible(item, visible: true); if (value2.Count == 0) { ItemsByBone.Remove(value); } else { RefreshVisibleItem(value2); } } internal static void RemoveItemAndForgetPriority(GrabbableObject item) { RemoveItem(item); if (TryGetNetworkObjectId(item, out var networkObjectId)) { RemoveSyncedFirstPickupOrder(networkObjectId); } } internal static bool HasSyncedFirstPickupOrder(ulong networkObjectId) { return SyncedFirstPickupOrderByNetworkObjectId.ContainsKey(networkObjectId); } internal static void ApplySyncedFirstPickupOrder(ulong networkObjectId, long order) { SyncedFirstPickupOrderByNetworkObjectId[networkObjectId] = order; GrabbableObject grabbableObjectByNetworkId = GetGrabbableObjectByNetworkId(networkObjectId); if ((Object)(object)grabbableObjectByNetworkId != (Object)null) { RefreshItem(grabbableObjectByNetworkId); } } internal static void RemoveSyncedFirstPickupOrder(ulong networkObjectId) { if (SyncedFirstPickupOrderByNetworkObjectId.Remove(networkObjectId)) { GrabbableObject grabbableObjectByNetworkId = GetGrabbableObjectByNetworkId(networkObjectId); if ((Object)(object)grabbableObjectByNetworkId != (Object)null) { RefreshItem(grabbableObjectByNetworkId); } } } internal static void RefreshItem(GrabbableObject item) { if (!((Object)(object)item == (Object)null)) { int instanceID = ((Object)item).GetInstanceID(); if (KeyByItemId.TryGetValue(instanceID, out var value) && ItemsByBone.TryGetValue(value, out var value2)) { RefreshVisibleItem(value2); } } } internal static void Clear() { ItemsByBone.Clear(); KeyByItemId.Clear(); SyncedFirstPickupOrderByNetworkObjectId.Clear(); } private static void RefreshVisibleItem(List items) { RemoveDead(items); if (items.Count != 0) { GrabbableObject preferredVisibleItem = GetPreferredVisibleItem(items); for (int i = 0; i < items.Count; i++) { SetItemVisible(items[i], (Object)(object)items[i] == (Object)(object)preferredVisibleItem); } } } private static GrabbableObject GetPreferredVisibleItem(List items) { if (TryGetPriorityFlashlight(items, out var priorityFlashlight)) { return priorityFlashlight; } BoneVisibilityMode value = ConfigManager.BoneVisibilityModeConfig.Value; if (1 == 0) { } GrabbableObject result = (GrabbableObject)(value switch { BoneVisibilityMode.FirstPickedUpMode => GetFirstPickedUpItem(items), BoneVisibilityMode.LastItemHeldMode => GetLastItemHeldItem(items), _ => GetFirstPickedUpItem(items), }); if (1 == 0) { } return result; } private static bool TryGetPriorityFlashlight(List items, out GrabbableObject priorityFlashlight) { priorityFlashlight = null; FlashlightItem val = null; long num = long.MinValue; bool flag = false; for (int i = 0; i < items.Count; i++) { GrabbableObject obj = items[i]; FlashlightItem val2 = (FlashlightItem)(object)((obj is FlashlightItem) ? obj : null); if (val2 == null || !IsPriorityFlashlight(val2)) { continue; } if (FlashlightPriorityCache.TryGetToggleOrder(val2, out var order)) { if (!flag || order > num) { val = val2; num = order; flag = true; } } else if ((Object)(object)val == (Object)null) { val = val2; } } priorityFlashlight = (GrabbableObject)(object)val; return (Object)(object)priorityFlashlight != (Object)null; } private static bool IsPriorityFlashlight(FlashlightItem flashlight) { if (!((GrabbableObject)flashlight).isBeingUsed) { return false; } if (flashlight.usingPlayerHelmetLight) { return true; } PlayerControllerB playerHeldBy = ((GrabbableObject)flashlight).playerHeldBy; return (Object)(object)playerHeldBy != (Object)null && (Object)(object)playerHeldBy.pocketedFlashlight == (Object)(object)flashlight; } private static GrabbableObject GetFirstPickedUpItem(List items) { GrabbableObject val = items[0]; long num = GetSyncedFirstPickupOrder(val); for (int i = 1; i < items.Count; i++) { GrabbableObject val2 = items[i]; long syncedFirstPickupOrder = GetSyncedFirstPickupOrder(val2); if (syncedFirstPickupOrder < num) { val = val2; num = syncedFirstPickupOrder; } } return val; } private static GrabbableObject GetLastItemHeldItem(List items) { GrabbableObject val = items[0]; long num = GetSyncedFirstPickupOrder(val); for (int i = 1; i < items.Count; i++) { GrabbableObject val2 = items[i]; long syncedFirstPickupOrder = GetSyncedFirstPickupOrder(val2); if (syncedFirstPickupOrder > num) { val = val2; num = syncedFirstPickupOrder; } } return val; } private static long GetSyncedFirstPickupOrder(GrabbableObject item) { if (!TryGetNetworkObjectId(item, out var networkObjectId)) { return long.MaxValue; } long value; return SyncedFirstPickupOrderByNetworkObjectId.TryGetValue(networkObjectId, out value) ? value : long.MaxValue; } private static void RemoveDead(List items) { for (int num = items.Count - 1; num >= 0; num--) { if (!((Object)(object)items[num] != (Object)null)) { items.RemoveAt(num); } } } private static void RemoveDeadAndItem(List items, GrabbableObject item) { for (int num = items.Count - 1; num >= 0; num--) { GrabbableObject val = items[num]; if (!((Object)(object)val != (Object)null) || !((Object)(object)val != (Object)(object)item)) { items.RemoveAt(num); } } } private static bool TryGetNetworkObjectId(GrabbableObject item, out ulong networkObjectId) { networkObjectId = 0uL; if ((Object)(object)item == (Object)null || (Object)(object)((NetworkBehaviour)item).NetworkObject == (Object)null || !((NetworkBehaviour)item).NetworkObject.IsSpawned) { return false; } networkObjectId = ((NetworkBehaviour)item).NetworkObject.NetworkObjectId; return true; } private static GrabbableObject GetGrabbableObjectByNetworkId(ulong networkObjectId) { NetworkManager singleton = NetworkManager.Singleton; if (((singleton != null) ? singleton.SpawnManager : null) == null) { return null; } if (!singleton.SpawnManager.SpawnedObjects.TryGetValue(networkObjectId, out var value)) { return null; } return ((Component)value).GetComponent(); } private static void SetItemVisible(GrabbableObject item, bool visible) { if ((Object)(object)item == (Object)null) { return; } item.EnableItemMeshes(visible); MeshRenderer[] renderers = RendererCache.GetRenderers(item); foreach (MeshRenderer val in renderers) { if ((Object)(object)val != (Object)null) { ((Renderer)val).enabled = visible; } } } } internal static class RendererCache { private static readonly Dictionary RenderersByItem = new Dictionary(); private static readonly Dictionary OriginalLayers = new Dictionary(); internal static MeshRenderer[] GetRenderers(GrabbableObject item) { int instanceID = ((Object)item).GetInstanceID(); if (RenderersByItem.TryGetValue(instanceID, out var value) && IsValid(value)) { return value; } MeshRenderer[] componentsInChildren = ((Component)item).GetComponentsInChildren(true); List list = new List(componentsInChildren.Length); foreach (MeshRenderer val in componentsInChildren) { if (!((Object)(object)val == (Object)null) && ((Object)val).name.IndexOf("ScanNode", StringComparison.Ordinal) < 0 && !((Component)val).gameObject.CompareTag("DoNotSet") && !((Component)val).gameObject.CompareTag("InteractTrigger") && ((Component)val).gameObject.layer != LayerMask.NameToLayer("Enemies")) { list.Add(val); } } MeshRenderer[] array = list.ToArray(); RenderersByItem[instanceID] = array; return array; } internal static void RememberLayer(GameObject gameObject) { if (!OriginalLayers.ContainsKey(gameObject)) { OriginalLayers[gameObject] = gameObject.layer; } } internal static bool TryGetOriginalLayer(GameObject gameObject, out int layer) { return OriginalLayers.TryGetValue(gameObject, out layer); } internal static void ForgetLayer(GameObject gameObject) { OriginalLayers.Remove(gameObject); } internal static void Clear() { RenderersByItem.Clear(); OriginalLayers.Clear(); } private static bool IsValid(MeshRenderer[] renderers) { for (int i = 0; i < renderers.Length; i++) { if ((Object)(object)renderers[i] == (Object)null) { return false; } } return true; } } } namespace __GEN { internal class NetworkVariableSerializationHelper { [RuntimeInitializeOnLoadMethod] internal static void InitializeSerialization() { } } } namespace ReservedSlotPositionsForInventory.NetcodePatcher { [AttributeUsage(AttributeTargets.Module)] internal class NetcodePatchedAssemblyAttribute : Attribute { } }