Decompiled source of ReservedSlotPositionsForInventory v1.0.6

ReservedSlotPositionsForInventory.dll

Decompiled a month ago
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<string, SortedDictionary<string, string>> SlotToItems = new Dictionary<string, SortedDictionary<string, string>>(StringComparer.Ordinal);

		private static readonly Dictionary<string, ConfigEntry<bool>> SlotToggles = new Dictionary<string, ConfigEntry<bool>>(StringComparer.Ordinal);

		private static readonly Dictionary<string, ConfigEntry<string>> SlotItemLists = new Dictionary<string, ConfigEntry<string>>(StringComparer.Ordinal);

		internal static ConfigEntry<BoneVisibilityMode> BoneVisibilityModeConfig { get; private set; }

		internal static void Initialise(ConfigFile config)
		{
			BoneVisibilityModeConfig = config.Bind<BoneVisibilityMode>("General", "Visibility Mode", BoneVisibilityMode.FirstPickedUpMode, "Controls which item stays visible when multiple items share the same bone.");
		}

		internal static bool IsSlotDisabled(string slotName)
		{
			ConfigEntry<bool> 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<bool>("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<string>("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<string, string>(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<int> LoggedMissingParentItems = new HashSet<int>();

		private static readonly HashSet<string> LoggedMissingBones = new HashSet<string>();

		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<string>)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<string, ReservedItemData> CopiedData = new Dictionary<string, ReservedItemData>(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<NetworkObjectReference>(ref itemReference);
				((FastBufferWriter)(ref val)).WriteValueSafe<long>(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<NetworkObjectReference>(ref itemReference);
				((FastBufferWriter)(ref val)).WriteValueSafe<long>(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<NetworkObjectReference>(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<NetworkObjectReference>(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<NetworkObjectReference>(ref itemReference);
				long order = default(long);
				((FastBufferReader)(ref reader)).ReadValueSafe<long>(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<NetworkObjectReference>(ref val);
				long order = default(long);
				((FastBufferReader)(ref reader)).ReadValueSafe<long>(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<NetworkObjectReference>(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<NetworkObjectReference>(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<int, long> ToggleOrderByItemId = new Dictionary<int, long>();

		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<HolsterBoneKey>
	{
		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<HolsterBoneKey, List<GrabbableObject>> ItemsByBone = new Dictionary<HolsterBoneKey, List<GrabbableObject>>();

		internal static readonly Dictionary<int, HolsterBoneKey> KeyByItemId = new Dictionary<int, HolsterBoneKey>();

		internal static readonly Dictionary<ulong, long> SyncedFirstPickupOrderByNetworkObjectId = new Dictionary<ulong, long>();

		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<GrabbableObject>();
				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<GrabbableObject> 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<GrabbableObject> 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<GrabbableObject> 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<GrabbableObject> 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<GrabbableObject> 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<GrabbableObject> 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<GrabbableObject> 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<GrabbableObject>();
		}

		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<int, MeshRenderer[]> RenderersByItem = new Dictionary<int, MeshRenderer[]>();

		private static readonly Dictionary<GameObject, int> OriginalLayers = new Dictionary<GameObject, int>();

		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<MeshRenderer>(true);
			List<MeshRenderer> list = new List<MeshRenderer>(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
	{
	}
}