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
{
}
}