Decompiled source of Coilhead mod v1.2.4

Mods/MannequinMod.dll

Decompiled 8 hours ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BoneLib;
using BoneLib.BoneMenu;
using CoilHead;
using HarmonyLib;
using Il2CppInterop.Runtime;
using Il2CppInterop.Runtime.InteropTypes;
using Il2CppInterop.Runtime.InteropTypes.Arrays;
using Il2CppSLZ.Marrow;
using Il2CppSLZ.Marrow.AI;
using Il2CppSLZ.Marrow.Input;
using Il2CppSLZ.Marrow.Utilities;
using Il2CppSLZ.VRMK;
using Il2CppSystem;
using Il2CppSystem.Collections.Generic;
using LabFusion.Data;
using LabFusion.Entities;
using LabFusion.Network;
using LabFusion.Player;
using LabFusion.SDK.Metadata;
using MelonLoader;
using MelonLoader.Preferences;
using Microsoft.CodeAnalysis;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.Rendering;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: MelonInfo(typeof(CoilHeadMod), "Coilhead mod", "1.2.4", "MannequinMod", null)]
[assembly: MelonGame("Stress Level Zero", "BONELAB")]
[assembly: TargetFramework(".NETCoreApp,Version=v6.0", FrameworkDisplayName = ".NET 6.0")]
[assembly: AssemblyCompany("MannequinMod")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.2.4.0")]
[assembly: AssemblyInformationalVersion("1.2.4")]
[assembly: AssemblyProduct("MannequinMod")]
[assembly: AssemblyTitle("MannequinMod")]
[assembly: AssemblyVersion("1.2.4.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableAttribute : Attribute
	{
		public readonly byte[] NullableFlags;

		public NullableAttribute(byte P_0)
		{
			NullableFlags = new byte[1] { P_0 };
		}

		public NullableAttribute(byte[] P_0)
		{
			NullableFlags = P_0;
		}
	}
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableContextAttribute : Attribute
	{
		public readonly byte Flag;

		public NullableContextAttribute(byte P_0)
		{
			Flag = P_0;
		}
	}
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace CoilHead
{
	public sealed class CoilHeadMod : MelonMod
	{
		private readonly WatchTimer _timer = new WatchTimer();

		private readonly ModSettings _settings = new ModSettings();

		private readonly PoseLock _pose = new PoseLock(null, delegate(string message)
		{
			MelonLogger.Warning(message);
		});

		private readonly List<NetworkPlayer> _watchers = new List<NetworkPlayer>();

		private readonly List<AIBrain> _npcWatchers = new List<AIBrain>();

		private readonly NpcWatcherScanner _npcScanner = new NpcWatcherScanner();

		private ObserverMode _mode;

		private readonly WatcherOutline _outline = new WatcherOutline();

		private readonly WatcherScanner _scanner = new WatcherScanner();

		private readonly DisableGesture _gesture = new DisableGesture();

		private readonly CountdownHud _hud = new CountdownHud();

		private readonly RemoteFreeze _remote = new RemoteFreeze();

		private bool _showHud = true;

		private bool _showHighlights = true;

		private float _nextVisualRetry;

		private float _nextHudRetry;

		private static readonly Color Gold = new Color(1f, 0.9f, 0.08f);

		private static readonly Color Mint = new Color(0.2f, 1f, 0.72f);

		private Page? _menuRoot;

		private BoolElement? _toggle;

		private FunctionElement? _status;

		private RigManager? _rig;

		private Transform? _avatar;

		private bool _enabled;

		private bool _poseHookReady;

		private float _nextStatus;

		private int _freezeSegmentSeconds = 20;

		public override void OnInitializeMelon()
		{
			_settings.Load();
			_timer.Configure(_settings.FreezeSeconds, _settings.CooldownSeconds, _settings.LookSeconds);
			SightQuery.ViewAngle = _settings.ViewAngle;
			((MelonBase)this).LoggerInstance.Msg("Coilhead mod 1.2.4 loaded. Live gaze, saved settings, pose-only freezing; no native rig detours.");
		}

		private void Menu()
		{
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0033: 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)
			//IL_00af: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f4: Unknown result type (might be due to invalid IL or missing references)
			//IL_0106: Unknown result type (might be due to invalid IL or missing references)
			//IL_0146: Unknown result type (might be due to invalid IL or missing references)
			//IL_0172: Unknown result type (might be due to invalid IL or missing references)
			//IL_019e: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d9: Unknown result type (might be due to invalid IL or missing references)
			//IL_0206: Unknown result type (might be due to invalid IL or missing references)
			//IL_0218: Unknown result type (might be due to invalid IL or missing references)
			//IL_023a: Unknown result type (might be due to invalid IL or missing references)
			if (Page.Root == null || _menuRoot == Page.Root)
			{
				return;
			}
			Page val = Page.Root.CreatePage("Coilhead mod", Gold, 0, true);
			_status = val.CreateFunction("OFF  /  COILHEAD", Color.gray, (Action)delegate
			{
			});
			((Element)_status).SetTooltip("Gold: frozen. Mint: cooldown, free to move. White: ready.");
			_toggle = val.CreateBool("Enable Coilhead", Gold, _enabled, (Action<bool>)SetEnabled);
			((Element)_toggle).SetTooltip("Combined look time qualifies each freeze. Looking away releases immediately; the countdown continues. No new freeze in its final 5 seconds.");
			val.CreateEnum("Who can freeze you", Gold, (Enum)_mode, (Action<Enum>)delegate(Enum value)
			{
				Reset();
				_mode = (ObserverMode)(object)value;
			});
			val.CreateFunction("Emergency release / disable", Color.red, (Action)delegate
			{
				SetEnabled(value: false);
			});
			Page obj = val.CreatePage("Settings", Mint, 0, true);
			((Element)obj.CreateFloat("Look time before freezing", Color.white, _settings.LookSeconds, 0.25f, 0f, 10f, (Action<float>)delegate(float value)
			{
				Reset();
				_settings.LookSeconds = value;
				_timer.Configure(_settings.FreezeSeconds, _settings.CooldownSeconds, _settings.LookSeconds);
			})).SetTooltip("Seconds of combined looks needed before each freeze. Pauses while unseen. Default 2.5s; 0 freezes instantly.");
			obj.CreateInt("Freeze duration (seconds)", Color.white, _settings.FreezeSeconds, 1, 1, 120, (Action<int>)delegate(int value)
			{
				Reset();
				_settings.FreezeSeconds = value;
				_timer.Configure(_settings.FreezeSeconds, _settings.CooldownSeconds, _settings.LookSeconds);
			});
			obj.CreateInt("Cooldown (seconds)", Color.white, _settings.CooldownSeconds, 1, 0, 120, (Action<int>)delegate(int value)
			{
				Reset();
				_settings.CooldownSeconds = value;
				_timer.Configure(_settings.FreezeSeconds, _settings.CooldownSeconds, _settings.LookSeconds);
			});
			((Element)obj.CreateInt("View cone (degrees)", Color.white, _settings.ViewAngle, 5, 20, 100, (Action<int>)delegate(int value)
			{
				Reset();
				_settings.ViewAngle = value;
				SightQuery.ViewAngle = _settings.ViewAngle;
			})).SetTooltip("Full cone around headset forward. Lower values require a more direct look. Default: 60 degrees.");
			obj.CreateEnum("Outline color", _settings.Color, (Enum)_settings.ColorChoice, (Action<Enum>)delegate(Enum value)
			{
				_settings.ColorChoice = (OutlineColor)(object)value;
			});
			Page obj2 = val.CreatePage("Display & highlights", Mint, 0, true);
			obj2.CreateBool("VR countdown", Color.white, _showHud, (Action<bool>)delegate(bool value)
			{
				_showHud = value;
				if (!value)
				{
					_hud.Hide();
				}
			});
			obj2.CreateBool("Watcher outlines", Gold, _showHighlights, (Action<bool>)delegate(bool value)
			{
				_showHighlights = value;
				if (!value)
				{
					_outline.Clear();
				}
			});
			_menuRoot = Page.Root;
		}

		private void SetEnabled(bool value)
		{
			_enabled = false;
			Reset();
			_enabled = value;
			if (_toggle != null)
			{
				_toggle.Value = value;
			}
			((MelonBase)this).LoggerInstance.Msg(value ? $"Coilhead enabled. Look time {_settings.LookSeconds}s; freeze {_settings.FreezeSeconds}s; cooldown {_settings.CooldownSeconds}s." : "Coilhead disabled; released.");
		}

		public override void OnUpdate()
		{
			//IL_0221: Unknown result type (might be due to invalid IL or missing references)
			//IL_022e: Expected O, but got Unknown
			//IL_0262: Unknown result type (might be due to invalid IL or missing references)
			//IL_026f: Expected O, but got Unknown
			//IL_06de: Unknown result type (might be due to invalid IL or missing references)
			//IL_06d7: Unknown result type (might be due to invalid IL or missing references)
			//IL_06d0: Unknown result type (might be due to invalid IL or missing references)
			//IL_06c9: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				if (_enabled)
				{
					XRApi xr = MarrowGame.xr;
					XRController val = ((xr != null) ? xr.LeftController : null);
					XRController val2 = ((xr != null) ? xr.RightController : null);
					bool flag = val != null && val2 != null && (Object)(object)Player.LeftController != (Object)null && (Object)(object)Player.RightController != (Object)null && ((Behaviour)Player.LeftController).isActiveAndEnabled && ((Behaviour)Player.RightController).isActiveAndEnabled;
					if (_gesture.Tick(flag, flag ? val.Trigger : 0f, flag ? val2.Trigger : 0f, flag && val.BButton, flag && val2.BButton, Time.realtimeSinceStartupAsDouble))
					{
						SetEnabled(value: false);
					}
				}
				Menu();
				RigManager rigManager = Player.RigManager;
				if ((Object)(object)_rig != (Object)(object)rigManager)
				{
					goto IL_0107;
				}
				if ((Object)(object)rigManager != (Object)null)
				{
					Transform? avatar = _avatar;
					Avatar avatar2 = rigManager.avatar;
					if ((Object)(object)avatar != (Object)(object)((avatar2 != null) ? ((Component)avatar2).transform : null))
					{
						goto IL_0107;
					}
				}
				goto IL_013f;
				IL_0107:
				Reset();
				_rig = rigManager;
				_avatar = (((Object)(object)rigManager != (Object)null && (Object)(object)rigManager.avatar != (Object)null) ? ((Component)rigManager.avatar).transform : null);
				goto IL_013f;
				IL_013f:
				bool flag2 = _enabled && (_mode != ObserverMode.Players || NetworkInfo.HasServer) && (Object)(object)_rig != (Object)null && (Object)(object)_rig.physicsRig != (Object)null && (Object)(object)_avatar != (Object)null && (Object)(object)Player.Head != (Object)null && ((Object)(object)_rig.health == (Object)null || _rig.health.curr_Health > 0f);
				if (flag2)
				{
					if (NetworkInfo.HasServer && !_poseHookReady)
					{
						((MelonBase)this).LoggerInstance.Msg("Installing managed Fusion outgoing-pose hook.");
						((MelonBase)this).HarmonyInstance.Patch((MethodBase)AccessTools.Method(typeof(RigPose), "ReadSkeleton", (Type[])null, (Type[])null), (HarmonyMethod)null, new HarmonyMethod(AccessTools.Method(typeof(PoseLock), "AfterReadSkeleton", (Type[])null, (Type[])null)), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
						((MelonBase)this).HarmonyInstance.Patch((MethodBase)AccessTools.Method(typeof(NetworkPlayer), "OnReceivePose", (Type[])null, (Type[])null), (HarmonyMethod)null, new HarmonyMethod(AccessTools.Method(typeof(PlayerGaze), "OnReceivePose", (Type[])null, (Type[])null)), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
						_poseHookReady = true;
					}
					_pose.Track(_rig);
				}
				else
				{
					_pose.StopTracking();
				}
				if (flag2 && NetworkInfo.HasServer && _mode != ObserverMode.NPCs)
				{
					_scanner.Scan(Time.unscaledTime, _rig, _watchers);
				}
				else
				{
					_watchers.Clear();
					_scanner.Clear();
				}
				if (flag2 && _mode != ObserverMode.Players)
				{
					_npcScanner.Scan(Time.unscaledTime, _rig, _npcWatchers);
				}
				else
				{
					_npcWatchers.Clear();
					_npcScanner.Clear();
				}
				int num = _watchers.Count + _npcWatchers.Count;
				bool frozen = _timer.Frozen;
				bool flag3 = _timer.Tick(flag2, num > 0, Time.realtimeSinceStartupAsDouble);
				if (flag3)
				{
					if (!frozen)
					{
						_freezeSegmentSeconds = Math.Clamp((int)Math.Ceiling(_timer.FreezeRemaining), 1, 120);
					}
					if (!_pose.Active)
					{
						_pose.Capture(_rig, _timer.FreezeRemaining);
					}
					_pose.Renew();
				}
				else if (frozen || _pose.Active)
				{
					_pose.StopTracking();
				}
				else
				{
					_pose.Release();
				}
				if (flag3 != frozen)
				{
					((MelonBase)this).LoggerInstance.Msg(flag3 ? $"Frozen: {_watchers.Count} player(s), {_npcWatchers.Count} NPC(s)." : ("Released: " + ((num == 0) ? "unseen" : "freeze limit") + "; pose callbacks cleared."));
				}
				_remote.Publish(flag2 && NetworkInfo.HasServer, _pose.Active, _freezeSegmentSeconds);
				_remote.Update(_rig);
				if (Time.unscaledTime >= _nextStatus)
				{
					_nextStatus = Time.unscaledTime + 0.2f;
					if (_status != null)
					{
						((Element)_status).ElementName = ((!_enabled) ? "OFF  /  COILHEAD" : ((!flag2) ? "WAITING  /  PLAYER OR LOBBY" : (_pose.Active ? $"FROZEN  /  {_timer.FreezeRemaining:F1}s  /  {num} watching" : ((_timer.CooldownRemaining > 0.0) ? $"FREE TO MOVE  /  {_timer.CooldownRemaining:F1}s" : (_timer.CountdownActive ? $"FREE  /  COUNTDOWN {_timer.FreezeRemaining:F1}s" : ((_timer.LookElapsed > 0.0 || num > 0) ? $"LOOK TIME  /  {_timer.LookElapsed:F2} / {_timer.LookSeconds:F2}s" : "READY  /  UNSEEN"))))));
						((Element)_status).ElementColor = ((!_enabled) ? Color.gray : (_pose.Active ? Gold : ((_timer.CooldownRemaining > 0.0) ? Mint : Color.white)));
					}
				}
			}
			catch (Exception ex)
			{
				Fail(ex);
			}
		}

		public override void OnFixedUpdate()
		{
			try
			{
				if (_enabled && _timer.Frozen)
				{
					_pose.Hold();
				}
				else
				{
					_pose.Release();
				}
				_remote.HoldFixed();
			}
			catch (Exception ex)
			{
				Fail(ex);
			}
		}

		public override void OnLateUpdate()
		{
			//IL_00fc: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				if (_enabled && _timer.Frozen)
				{
					_pose.HoldVisual();
				}
				else
				{
					_pose.Release();
				}
			}
			catch (Exception ex)
			{
				Fail(ex);
			}
			if (Time.unscaledTime >= _nextHudRetry)
			{
				try
				{
					_hud.Tick(Time.unscaledTime, _enabled && _showHud, _timer, _watchers.Count + _npcWatchers.Count);
				}
				catch (Exception ex2)
				{
					_nextHudRetry = Time.unscaledTime + 2f;
					_hud.Hide();
					((MelonBase)this).LoggerInstance.Warning("Coilhead HUD retry in 2s: " + ex2.Message);
				}
			}
			if (Time.unscaledTime < _nextVisualRetry)
			{
				return;
			}
			try
			{
				if (_enabled && _showHighlights)
				{
					_outline.Draw(_watchers, _npcWatchers, Player.Head, _settings.Color);
				}
			}
			catch (Exception ex3)
			{
				_nextVisualRetry = Time.unscaledTime + 10f;
				((MelonBase)this).LoggerInstance.Warning("Coilhead visual retry in 10s: " + ex3.Message);
			}
		}

		private void Fail(Exception ex)
		{
			_enabled = false;
			try
			{
				Reset();
				if (_toggle != null)
				{
					_toggle.Value = false;
				}
			}
			catch (Exception ex2)
			{
				((MelonBase)this).LoggerInstance.Error((object)ex2);
			}
			((MelonBase)this).LoggerInstance.Error("Coilhead disabled and released after an error: " + ex);
		}

		private void Reset()
		{
			_pose.StopTracking();
			_timer.Reset();
			_gesture.Reset();
			_scanner.Clear();
			_watchers.Clear();
			_npcScanner.Clear();
			_npcWatchers.Clear();
			_outline.Clear();
			_hud.Hide();
			_nextVisualRetry = (_nextHudRetry = 0f);
			_remote.Publish(enabled: false, frozen: false);
		}

		public override void OnSceneWasLoaded(int buildIndex, string sceneName)
		{
			Reset();
			_remote.ResetPeers();
			_rig = null;
			_avatar = null;
		}

		public override void OnDeinitializeMelon()
		{
			Reset();
			_remote.ResetPeers();
			_outline.Dispose();
			_hud.Dispose();
		}
	}
	internal sealed class CountdownHud : IDisposable
	{
		private GameObject? _root;

		private Canvas? _canvas;

		private Text? _number;

		private Material? _material;

		private Font? _font;

		private int _layer = -1;

		private int _lastSecond = -1;

		internal void Tick(float now, bool visible, WatchTimer timer, int watchers)
		{
			//IL_0093: Unknown result type (might be due to invalid IL or missing references)
			//IL_0098: Unknown result type (might be due to invalid IL or missing references)
			//IL_009b: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bd: Unknown result type (might be due to invalid IL or missing references)
			//IL_019a: Unknown result type (might be due to invalid IL or missing references)
			//IL_017f: Unknown result type (might be due to invalid IL or missing references)
			CountdownReading countdownReading = CountdownReading.Read(visible, timer);
			if (!countdownReading.Visible)
			{
				Hide();
				return;
			}
			Camera val = HeadsetView.Camera();
			if ((Object)(object)val == (Object)null)
			{
				Hide();
				return;
			}
			if ((Object)(object)_root == (Object)null)
			{
				Build();
			}
			_canvas.worldCamera = val;
			Transform transform = _root.transform;
			if ((Object)(object)transform.parent != (Object)(object)((Component)val).transform)
			{
				transform.SetParent(((Component)val).transform, false);
			}
			float num = Math.Max(1.15f, val.nearClipPlane + 0.3f);
			Vector3 localPosition = CornerPosition(val, num);
			transform.localPosition = localPosition;
			transform.localRotation = Quaternion.identity;
			float num2 = num * 0.00085f;
			transform.localScale = new Vector3(num2, num2, num2);
			int num3 = HeadsetView.VisibleLayer(val.cullingMask);
			if (num3 < 0)
			{
				Hide();
				return;
			}
			if (_layer != num3)
			{
				foreach (Transform componentsInChild in _root.GetComponentsInChildren<Transform>(true))
				{
					((Component)componentsInChild).gameObject.layer = num3;
				}
				_layer = num3;
			}
			if (_lastSecond != countdownReading.Seconds)
			{
				_number.text = countdownReading.Seconds.ToString();
				((Graphic)_number).color = ((countdownReading.Seconds <= 3) ? new Color(1f, 0.78f, 0.28f, 1f) : new Color(1f, 0.96f, 0.78f, 1f));
				_lastSecond = countdownReading.Seconds;
			}
			if (!_root.activeSelf)
			{
				_root.SetActive(true);
			}
		}

		private static Vector3 CornerPosition(Camera camera, float distance)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0059: Unknown result type (might be due to invalid IL or missing references)
			//IL_005e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0072: Unknown result type (might be due to invalid IL or missing references)
			//IL_0077: Unknown result type (might be due to invalid IL or missing references)
			//IL_007a: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				Matrix4x4 stereoProjectionMatrix = camera.GetStereoProjectionMatrix((StereoscopicEye)0);
				Matrix4x4 stereoProjectionMatrix2 = camera.GetStereoProjectionMatrix((StereoscopicEye)1);
				return CountdownPlacement.Position(distance, ((Matrix4x4)(ref stereoProjectionMatrix))[0, 0], ((Matrix4x4)(ref stereoProjectionMatrix))[0, 2], ((Matrix4x4)(ref stereoProjectionMatrix))[1, 1], ((Matrix4x4)(ref stereoProjectionMatrix))[1, 2], ((Matrix4x4)(ref stereoProjectionMatrix2))[0, 0], ((Matrix4x4)(ref stereoProjectionMatrix2))[0, 2], ((Matrix4x4)(ref stereoProjectionMatrix2))[1, 1], ((Matrix4x4)(ref stereoProjectionMatrix2))[1, 2]);
			}
			catch
			{
				return new Vector3(distance * 0.48f, (0f - distance) * 0.38f, distance);
			}
		}

		private void Build()
		{
			//IL_0068: Unknown result type (might be due to invalid IL or missing references)
			//IL_006d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0075: Unknown result type (might be due to invalid IL or missing references)
			//IL_0085: Expected O, but got Unknown
			//IL_00aa: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b4: Expected O, but got Unknown
			//IL_011a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0137: Unknown result type (might be due to invalid IL or missing references)
			//IL_013d: Expected O, but got Unknown
			//IL_0162: Unknown result type (might be due to invalid IL or missing references)
			//IL_0167: Unknown result type (might be due to invalid IL or missing references)
			//IL_0168: Unknown result type (might be due to invalid IL or missing references)
			//IL_016e: Unknown result type (might be due to invalid IL or missing references)
			//IL_016f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0170: Unknown result type (might be due to invalid IL or missing references)
			//IL_0176: Unknown result type (might be due to invalid IL or missing references)
			//IL_0186: Unknown result type (might be due to invalid IL or missing references)
			//IL_0216: Unknown result type (might be due to invalid IL or missing references)
			//IL_022a: Unknown result type (might be due to invalid IL or missing references)
			Dispose();
			try
			{
				try
				{
					_font = Resources.GetBuiltinResource<Font>("Arial.ttf");
				}
				catch
				{
					_font = Resources.GetBuiltinResource<Font>("LegacyRuntime.ttf");
				}
				if ((Object)(object)_font == (Object)null)
				{
					_font = Resources.GetBuiltinResource<Font>("LegacyRuntime.ttf");
				}
				if ((Object)(object)_font == (Object)null)
				{
					throw new InvalidOperationException("Countdown font unavailable");
				}
				_material = new Material(Graphic.defaultGraphicMaterial)
				{
					hideFlags = (HideFlags)61,
					renderQueue = 5000
				};
				_material.SetInt("unity_GUIZTestMode", 8);
				_root = new GameObject("Mannequin.VR.Countdown", (Type[])(object)new Type[1] { Il2CppType.Of<RectTransform>() });
				((Object)_root).hideFlags = (HideFlags)61;
				_root.SetActive(false);
				Object.DontDestroyOnLoad((Object)(object)_root);
				_canvas = _root.AddComponent<Canvas>();
				_canvas.renderMode = (RenderMode)2;
				_canvas.sortingOrder = 32700;
				_root.GetComponent<RectTransform>().sizeDelta = new Vector2(110f, 80f);
				GameObject val = new GameObject("Seconds", (Type[])(object)new Type[1] { Il2CppType.Of<RectTransform>() });
				RectTransform component = val.GetComponent<RectTransform>();
				((Transform)component).SetParent(_root.transform, false);
				Vector2 val2 = (component.pivot = new Vector2(0.5f, 0.5f));
				Vector2 anchorMin = (component.anchorMax = val2);
				component.anchorMin = anchorMin;
				component.sizeDelta = new Vector2(110f, 80f);
				_number = val.AddComponent<Text>();
				_number.font = _font;
				_number.fontSize = 56;
				_number.fontStyle = (FontStyle)1;
				((Graphic)_number).material = _material;
				_number.alignment = (TextAnchor)4;
				((Graphic)_number).raycastTarget = false;
				_number.supportRichText = false;
				Shadow obj2 = val.AddComponent<Shadow>();
				obj2.effectColor = new Color(0f, 0f, 0f, 0.85f);
				obj2.effectDistance = new Vector2(1.5f, -1.5f);
			}
			catch
			{
				Dispose();
				throw;
			}
		}

		internal void Hide()
		{
			if ((Object)(object)_root != (Object)null && _root.activeSelf)
			{
				_root.SetActive(false);
			}
			_lastSecond = -1;
		}

		public void Dispose()
		{
			Hide();
			if ((Object)(object)_root != (Object)null)
			{
				Object.Destroy((Object)(object)_root);
			}
			if ((Object)(object)_material != (Object)null)
			{
				Object.Destroy((Object)(object)_material);
			}
			_root = null;
			_canvas = null;
			_number = null;
			_material = null;
			_layer = -1;
		}
	}
	internal static class CountdownPlacement
	{
		internal static Vector3 Position(float distance, float lx, float lcx, float ly, float lcy, float rx, float rcx, float ry, float rcy)
		{
			//IL_0065: Unknown result type (might be due to invalid IL or missing references)
			//IL_0093: Unknown result type (might be due to invalid IL or missing references)
			float num = Math.Min((1f + lcx) / lx, (1f + rcx) / rx);
			float num2 = Math.Min((1f - lcy) / ly, (1f - rcy) / ry);
			if (!float.IsFinite(num) || !float.IsFinite(num2) || num <= 0f || num2 <= 0f)
			{
				return new Vector3(distance * 0.48f, (0f - distance) * 0.38f, distance);
			}
			return new Vector3(distance * Math.Min(num * 0.64f, 0.72f), (0f - distance) * Math.Min(num2 * 0.58f, 0.65f), distance);
		}
	}
	internal readonly record struct CountdownReading(bool Visible, int Seconds, float Fraction)
	{
		internal static CountdownReading Read(bool enabled, WatchTimer timer)
		{
			if (!enabled || !timer.CountdownActive || timer.FreezeRemaining <= 0.0)
			{
				return default(CountdownReading);
			}
			double freezeRemaining = timer.FreezeRemaining;
			return new CountdownReading(Visible: true, (int)Math.Ceiling(freezeRemaining), (float)Math.Clamp(freezeRemaining / timer.FreezeSeconds, 0.0, 1.0));
		}
	}
	internal sealed class DisableGesture
	{
		private enum Phase
		{
			Neutral,
			Ready,
			Gathering,
			Held
		}

		private Phase _phase;

		private bool _leftDown;

		private bool _rightDown;

		private bool _firstTap;

		private double? _neutralSince;

		private double _pressStarted;

		private double _firstReleased;

		private double _last = double.NegativeInfinity;

		public bool Tick(bool available, float leftTrigger, float rightTrigger, bool y, bool b, double now)
		{
			if (!available || !double.IsFinite(now) || !float.IsFinite(leftTrigger) || !float.IsFinite(rightTrigger))
			{
				Reset();
				return false;
			}
			if (now < _last || (double.IsFinite(_last) && now - _last > 0.5))
			{
				Reset();
			}
			_last = now;
			_leftDown = leftTrigger >= (_leftDown ? 0.55f : 0.8f);
			_rightDown = rightTrigger >= (_rightDown ? 0.55f : 0.8f);
			bool flag = leftTrigger < 0.55f && rightTrigger < 0.55f && !y && !b;
			bool flag2 = _leftDown && _rightDown && y && b;
			if (_firstTap && now - _firstReleased > 0.65)
			{
				_firstTap = false;
			}
			if (_phase == Phase.Neutral)
			{
				_neutralSince = (flag ? new double?(_neutralSince ?? now) : ((double?)null));
				if (_neutralSince.HasValue && now - _neutralSince.Value >= 0.04)
				{
					_phase = Phase.Ready;
				}
				return false;
			}
			if (_phase == Phase.Ready)
			{
				if (!_leftDown && !_rightDown && !y && !b)
				{
					return false;
				}
				_pressStarted = now;
				_phase = Phase.Gathering;
			}
			if (_phase == Phase.Gathering)
			{
				if (now - _pressStarted > 0.2 || flag)
				{
					CancelTap();
					return false;
				}
				if (!flag2)
				{
					return false;
				}
				if (_firstTap)
				{
					Reset();
					return true;
				}
				_phase = Phase.Held;
			}
			if (_phase == Phase.Held)
			{
				if (now - _pressStarted > 0.4)
				{
					CancelTap();
					return false;
				}
				if (flag)
				{
					_firstTap = true;
					_firstReleased = now;
					_neutralSince = now;
					_phase = Phase.Neutral;
				}
			}
			return false;
		}

		private void CancelTap()
		{
			_phase = Phase.Neutral;
			_firstTap = false;
			_neutralSince = null;
		}

		public void Reset()
		{
			CancelTap();
			_leftDown = (_rightDown = false);
			_pressStarted = (_firstReleased = 0.0);
			_last = double.NegativeInfinity;
		}
	}
	internal static class EchoMeshSpace
	{
		internal static bool TryGetDrawMatrix(Renderer renderer, SkinnedMeshRenderer? skin, Mesh snapshot, out Matrix4x4 matrix)
		{
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_00be: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00de: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f2: Unknown result type (might be due to invalid IL or missing references)
			//IL_0106: 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_0130: Unknown result type (might be due to invalid IL or missing references)
			//IL_0144: Unknown result type (might be due to invalid IL or missing references)
			//IL_0159: Unknown result type (might be due to invalid IL or missing references)
			//IL_016e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0182: Unknown result type (might be due to invalid IL or missing references)
			//IL_0197: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ab: Unknown result type (might be due to invalid IL or missing references)
			matrix = (((Object)(object)skin != (Object)null) ? Matrix4x4.TRS(((Component)skin).transform.position, ((Component)skin).transform.rotation, Vector3.one) : renderer.localToWorldMatrix);
			for (int i = 0; i < 4; i++)
			{
				for (int j = 0; j < 4; j++)
				{
					if (!float.IsFinite(((Matrix4x4)(ref matrix))[i, j]))
					{
						return false;
					}
				}
			}
			if (Math.Abs(((Matrix4x4)(ref matrix))[3, 0]) > 1E-05f || Math.Abs(((Matrix4x4)(ref matrix))[3, 1]) > 1E-05f || Math.Abs(((Matrix4x4)(ref matrix))[3, 2]) > 1E-05f || Math.Abs(((Matrix4x4)(ref matrix))[3, 3] - 1f) > 1E-05f)
			{
				return false;
			}
			Bounds bounds = snapshot.bounds;
			if (!Usable(bounds))
			{
				return false;
			}
			Vector3 extents = ((Bounds)(ref bounds)).extents;
			Vector3 value = ((Matrix4x4)(ref matrix)).MultiplyPoint3x4(((Bounds)(ref bounds)).center);
			Vector3 value2 = default(Vector3);
			((Vector3)(ref value2))..ctor(Math.Abs(((Matrix4x4)(ref matrix))[0, 0]) * extents.x + Math.Abs(((Matrix4x4)(ref matrix))[0, 1]) * extents.y + Math.Abs(((Matrix4x4)(ref matrix))[0, 2]) * extents.z, Math.Abs(((Matrix4x4)(ref matrix))[1, 0]) * extents.x + Math.Abs(((Matrix4x4)(ref matrix))[1, 1]) * extents.y + Math.Abs(((Matrix4x4)(ref matrix))[1, 2]) * extents.z, Math.Abs(((Matrix4x4)(ref matrix))[2, 0]) * extents.x + Math.Abs(((Matrix4x4)(ref matrix))[2, 1]) * extents.y + Math.Abs(((Matrix4x4)(ref matrix))[2, 2]) * extents.z);
			if (!Finite(value) || !Finite(value2))
			{
				return false;
			}
			return ((Vector3)(ref value2)).sqrMagnitude <= 10000f;
		}

		internal static bool SameScale(Vector3 first, Vector3 second)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//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)
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			//IL_003c: Unknown result type (might be due to invalid IL or missing references)
			if (Finite(first) && Finite(second) && Close(first.x, second.x) && Close(first.y, second.y))
			{
				return Close(first.z, second.z);
			}
			return false;
		}

		private static bool Close(float first, float second)
		{
			return Math.Abs(first - second) <= 0.0001f * Math.Max(0.0001f, Math.Max(Math.Abs(first), Math.Abs(second)));
		}

		private static bool Usable(Bounds bounds)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: 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)
			//IL_0057: Unknown result type (might be due to invalid IL or missing references)
			//IL_005c: Unknown result type (might be due to invalid IL or missing references)
			if (Finite(((Bounds)(ref bounds)).center) && Finite(((Bounds)(ref bounds)).extents) && ((Bounds)(ref bounds)).extents.x >= 0f && ((Bounds)(ref bounds)).extents.y >= 0f && ((Bounds)(ref bounds)).extents.z >= 0f)
			{
				Vector3 extents = ((Bounds)(ref bounds)).extents;
				return ((Vector3)(ref extents)).sqrMagnitude > 0f;
			}
			return false;
		}

		private static bool Finite(Vector3 value)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			if (float.IsFinite(value.x) && float.IsFinite(value.y))
			{
				return float.IsFinite(value.z);
			}
			return false;
		}
	}
	internal static class HeadsetView
	{
		internal static Camera? Camera()
		{
			//IL_0071: 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)
			OpenControllerRig controllerRig = Player.ControllerRig;
			Il2CppReferenceArray<Camera> val = ((controllerRig != null) ? controllerRig.cameras : null);
			if (val != null)
			{
				for (int i = 0; i < ((Il2CppArrayBase<Camera>)(object)val).Length; i++)
				{
					if ((Object)(object)((Il2CppArrayBase<Camera>)(object)val)[i] != (Object)null && ((Behaviour)((Il2CppArrayBase<Camera>)(object)val)[i]).isActiveAndEnabled && (int)((Il2CppArrayBase<Camera>)(object)val)[i].stereoTargetEye != 0)
					{
						return ((Il2CppArrayBase<Camera>)(object)val)[i];
					}
				}
			}
			Camera main = Camera.main;
			if (!((Object)(object)main != (Object)null) || !((Behaviour)main).isActiveAndEnabled || (int)main.stereoTargetEye == 0)
			{
				return null;
			}
			return main;
		}

		internal static int VisibleLayer(int mask)
		{
			if ((mask & 0x20) != 0)
			{
				return 5;
			}
			for (int i = 0; i < 32; i++)
			{
				if ((mask & (1 << i)) != 0)
				{
					return i;
				}
			}
			return -1;
		}
	}
	internal enum OutlineColor
	{
		Yellow,
		White,
		Cyan,
		Green,
		Blue,
		Purple,
		Pink,
		Red
	}
	internal sealed class ModSettings
	{
		private MelonPreferences_Category _category;

		private MelonPreferences_Entry<int> _freeze;

		private MelonPreferences_Entry<int> _cooldown;

		private MelonPreferences_Entry<int> _angle;

		private MelonPreferences_Entry<float> _lookTime;

		private MelonPreferences_Entry<OutlineColor> _color;

		internal int FreezeSeconds
		{
			get
			{
				return Math.Clamp(_freeze.Value, 1, 120);
			}
			set
			{
				_freeze.Value = Math.Clamp(value, 1, 120);
				Save();
			}
		}

		internal int CooldownSeconds
		{
			get
			{
				return Math.Clamp(_cooldown.Value, 0, 120);
			}
			set
			{
				_cooldown.Value = Math.Clamp(value, 0, 120);
				Save();
			}
		}

		internal int ViewAngle
		{
			get
			{
				return Math.Clamp(_angle.Value, 20, 100);
			}
			set
			{
				_angle.Value = Math.Clamp(value, 20, 100);
				Save();
			}
		}

		internal float LookSeconds
		{
			get
			{
				return ClampLookTime(_lookTime.Value);
			}
			set
			{
				_lookTime.Value = ClampLookTime(value);
				Save();
			}
		}

		internal OutlineColor ColorChoice
		{
			get
			{
				if (!Enum.IsDefined(typeof(OutlineColor), _color.Value))
				{
					return OutlineColor.Yellow;
				}
				return _color.Value;
			}
			set
			{
				_color.Value = value;
				Save();
			}
		}

		internal Color Color => (Color)(ColorChoice switch
		{
			OutlineColor.White => new Color(1f, 1f, 1f), 
			OutlineColor.Cyan => new Color(0f, 1f, 1f), 
			OutlineColor.Green => new Color(0.2f, 1f, 0.15f), 
			OutlineColor.Blue => new Color(0.2f, 0.45f, 1f), 
			OutlineColor.Purple => new Color(0.65f, 0.25f, 1f), 
			OutlineColor.Pink => new Color(1f, 0.25f, 0.65f), 
			OutlineColor.Red => new Color(1f, 0.15f, 0.08f), 
			_ => new Color(1f, 0.9f, 0.02f), 
		});

		private static float ClampLookTime(float value)
		{
			if (!float.IsFinite(value))
			{
				return 2.5f;
			}
			return Math.Clamp(value, 0f, 10f);
		}

		internal void Load()
		{
			_category = MelonPreferences.CreateCategory("MannequinMod");
			_freeze = _category.CreateEntry<int>("FreezeSeconds", 20, (string)null, (string)null, false, false, (ValueValidator)null, (string)null);
			_cooldown = _category.CreateEntry<int>("CooldownSeconds", 20, (string)null, (string)null, false, false, (ValueValidator)null, (string)null);
			_angle = _category.CreateEntry<int>("ViewAngleDegrees", 60, (string)null, (string)null, false, false, (ValueValidator)null, (string)null);
			_lookTime = _category.CreateEntry<float>("LookSeconds", 2.5f, (string)null, (string)null, false, false, (ValueValidator)null, (string)null);
			_color = _category.CreateEntry<OutlineColor>("OutlineColor", OutlineColor.Yellow, (string)null, (string)null, false, false, (ValueValidator)null, (string)null);
		}

		private void Save()
		{
			_category.SaveToFile(false);
		}
	}
	internal enum ObserverMode
	{
		Players,
		NPCs,
		Both
	}
	internal sealed class NpcWatcherScanner
	{
		private sealed class Observer
		{
			internal AIBrain Brain;

			internal bool Watching;

			internal float NextCheck;

			internal float LastCheck;
		}

		private readonly List<Observer> _npcs = new List<Observer>();

		private readonly Dictionary<int, Observer> _previous = new Dictionary<int, Observer>();

		private readonly SightQuery _sight = new SightQuery();

		private int _cursor;

		private float _nextRoster;

		internal void Scan(float now, RigManager local, List<AIBrain> watchers)
		{
			//IL_0107: Unknown result type (might be due to invalid IL or missing references)
			//IL_010c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0118: Unknown result type (might be due to invalid IL or missing references)
			//IL_011d: Unknown result type (might be due to invalid IL or missing references)
			//IL_011e: Unknown result type (might be due to invalid IL or missing references)
			//IL_011f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0125: Unknown result type (might be due to invalid IL or missing references)
			//IL_012a: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ef: Unknown result type (might be due to invalid IL or missing references)
			//IL_01fc: Unknown result type (might be due to invalid IL or missing references)
			//IL_020e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0215: Unknown result type (might be due to invalid IL or missing references)
			//IL_0222: Unknown result type (might be due to invalid IL or missing references)
			//IL_0234: Unknown result type (might be due to invalid IL or missing references)
			//IL_023b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0248: Unknown result type (might be due to invalid IL or missing references)
			//IL_02e5: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ec: Unknown result type (might be due to invalid IL or missing references)
			//IL_02f1: Unknown result type (might be due to invalid IL or missing references)
			//IL_02fb: Unknown result type (might be due to invalid IL or missing references)
			//IL_0302: Unknown result type (might be due to invalid IL or missing references)
			//IL_0307: Unknown result type (might be due to invalid IL or missing references)
			//IL_0311: Unknown result type (might be due to invalid IL or missing references)
			//IL_0318: Unknown result type (might be due to invalid IL or missing references)
			//IL_031d: Unknown result type (might be due to invalid IL or missing references)
			if (now >= _nextRoster)
			{
				_nextRoster = now + 2f;
				_previous.Clear();
				foreach (Observer npc in _npcs)
				{
					if ((Object)(object)npc.Brain != (Object)null)
					{
						_previous[((Object)npc.Brain).GetInstanceID()] = npc;
					}
				}
				_npcs.Clear();
				foreach (AIBrain item in Object.FindObjectsOfType<AIBrain>())
				{
					if (Alive(item))
					{
						_npcs.Add(_previous.TryGetValue(((Object)item).GetInstanceID(), out Observer value) ? value : new Observer
						{
							Brain = item
						});
					}
				}
				_previous.Clear();
			}
			Vector3 position = ((Rig)local.physicsRig).m_head.position;
			Vector3 position2 = ((Rig)local.physicsRig).m_pelvis.position;
			Vector3 point = Vector3.Lerp(position, position2, 0.55f);
			int num = 0;
			for (int i = 0; i < _npcs.Count; i++)
			{
				if (num >= 4)
				{
					break;
				}
				if (_cursor >= _npcs.Count)
				{
					_cursor = 0;
				}
				Observer observer = _npcs[_cursor++];
				if (!(now < observer.NextCheck))
				{
					num++;
					observer.NextCheck = now + 0.05f;
					observer.LastCheck = now;
					observer.Watching = false;
					AIBrain brain = observer.Brain;
					if (Alive(brain))
					{
						Transform eyeTran = brain.behaviour.eyeTran;
						Transform transform = ((Component)brain.puppetMaster).transform;
						Transform targetRoot = brain.puppetMaster.targetRoot;
						observer.Watching = _sight.Visible(eyeTran.position, eyeTran.forward, transform, ((Component)local).transform, position, targetRoot) || _sight.Visible(eyeTran.position, eyeTran.forward, transform, ((Component)local).transform, point, targetRoot) || _sight.Visible(eyeTran.position, eyeTran.forward, transform, ((Component)local).transform, position2, targetRoot);
					}
				}
			}
			watchers.Clear();
			foreach (Observer npc2 in _npcs)
			{
				if (!npc2.Watching || now < npc2.LastCheck || now - npc2.LastCheck > 0.35f || !Alive(npc2.Brain))
				{
					npc2.Watching = false;
					continue;
				}
				Transform eyeTran2 = npc2.Brain.behaviour.eyeTran;
				if (!SightQuery.InCone(eyeTran2.position, eyeTran2.forward, position) && !SightQuery.InCone(eyeTran2.position, eyeTran2.forward, point) && !SightQuery.InCone(eyeTran2.position, eyeTran2.forward, position2))
				{
					npc2.Watching = false;
				}
				else
				{
					watchers.Add(npc2.Brain);
				}
			}
		}

		private static bool Alive(AIBrain? brain)
		{
			if ((Object)(object)brain != (Object)null && ((Component)brain).gameObject.activeInHierarchy && !brain.isDead && (Object)(object)brain.puppetMaster != (Object)null && brain.puppetMaster.isAlive && (Object)(object)brain.behaviour != (Object)null)
			{
				return (Object)(object)brain.behaviour.eyeTran != (Object)null;
			}
			return false;
		}

		internal void Clear()
		{
			_npcs.Clear();
			_previous.Clear();
			_cursor = 0;
			_nextRoster = 0f;
		}
	}
	internal static class PlayerGaze
	{
		private sealed class Receipt
		{
			internal double At;
		}

		private static readonly ConditionalWeakTable<NetworkPlayer, Receipt> Receipts = new ConditionalWeakTable<NetworkPlayer, Receipt>();

		internal static void OnReceivePose(NetworkPlayer __instance)
		{
			Received(__instance, Time.realtimeSinceStartupAsDouble);
		}

		internal static void Received(NetworkPlayer player, double now)
		{
			Receipts.GetValue(player, (NetworkPlayer _) => new Receipt()).At = now;
		}

		internal static bool TryRead(NetworkPlayer player, double now, out Vector3 eye, out Vector3 forward)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ee: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f3: Unknown result type (might be due to invalid IL or missing references)
			//IL_0134: Unknown result type (might be due to invalid IL or missing references)
			//IL_0137: Unknown result type (might be due to invalid IL or missing references)
			//IL_013c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0141: Unknown result type (might be due to invalid IL or missing references)
			//IL_0146: Unknown result type (might be due to invalid IL or missing references)
			//IL_014b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0114: Unknown result type (might be due to invalid IL or missing references)
			//IL_011b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0120: Unknown result type (might be due to invalid IL or missing references)
			//IL_0125: Unknown result type (might be due to invalid IL or missing references)
			//IL_012a: Unknown result type (might be due to invalid IL or missing references)
			//IL_012c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0131: Unknown result type (might be due to invalid IL or missing references)
			eye = (forward = Vector3.zero);
			if (!Receipts.TryGetValue(player, out Receipt value) || !double.IsFinite(now) || !double.IsFinite(value.At) || now < value.At || now - value.At > 0.35)
			{
				return false;
			}
			RigPose rigPose = player.RigPose;
			RigRefs rigRefs = player.RigRefs;
			Transform val = ((rigRefs != null) ? rigRefs.Headset : null);
			if (!player.ReceivedPose || rigPose == null || (Object)(object)val == (Object)null || rigPose.TrackedPoints == null || rigPose.TrackedPoints.Length < 1 || rigPose.TrackedPoints[0] == null)
			{
				return false;
			}
			SerializedLocalTransform val2 = rigPose.TrackedPoints[0];
			Transform parent = val.parent;
			eye = (((Object)(object)parent != (Object)null) ? parent.TransformPoint(val2.position) : val2.position);
			Quaternion val3 = (((Object)(object)parent != (Object)null) ? parent.rotation : Quaternion.identity);
			Transform val4 = player.RigSkeleton?.TrackedPlayspace;
			if ((Object)(object)val4 != (Object)null)
			{
				val3 = rigPose.TrackedPlayspaceExpanded * Quaternion.Inverse(val4.rotation) * val3;
			}
			forward = val3 * val2.rotation * Vector3.forward;
			return true;
		}
	}
	internal sealed class PlayerSilhouetteRenderer : IDisposable
	{
		private sealed class CachedMesh
		{
			internal Renderer Renderer;

			internal Mesh Source;

			internal Mesh Mesh;

			internal Transform AvatarRoot;

			internal Transform? RootBone;

			internal Vector3 BakedScale;

			internal bool HasSnapshot;

			internal int Vertices;

			internal Il2CppStructArray<Color>? White;

			internal float NextBake;

			internal float LastSeen;

			internal float ScanTime = float.NegativeInfinity;

			internal Matrix4x4 ScanMatrix;

			internal bool HasScanMatrix;
		}

		private const int MaxMeshVertices = 120000;

		private const int MaxCachedVertices = 1000000;

		private readonly Dictionary<int, CachedMesh> _meshes = new Dictionary<int, CachedMesh>();

		private readonly List<int> _expired = new List<int>();

		private readonly Action<string> _warning;

		private Material? _material;

		private MaterialPropertyBlock? _block;

		private Mesh? _voiceMarker;

		private int _bakes;

		private int _draws;

		private int _attempts;

		private int _bakeVertices;

		private int _cachedVertices;

		private float _now;

		private float _nextAttempt;

		private float _nextCleanup;

		private float _nextWarning;

		private bool _disposed;

		internal bool Ready
		{
			get
			{
				if (!_disposed)
				{
					return (Object)(object)_material != (Object)null;
				}
				return false;
			}
		}

		internal PlayerSilhouetteRenderer(Action<string> warning)
		{
			_warning = warning;
		}

		internal void BeginFrame(float now)
		{
			_now = now;
			_bakes = 1;
			_draws = 96;
			_bakeVertices = 120000;
			if (_disposed)
			{
				return;
			}
			EnsureMaterial();
			if (now < _nextCleanup)
			{
				return;
			}
			_nextCleanup = now + 0.5f;
			_expired.Clear();
			foreach (KeyValuePair<int, CachedMesh> mesh in _meshes)
			{
				if ((Object)(object)mesh.Value.Renderer == (Object)null || now - mesh.Value.LastSeen > 12f)
				{
					_expired.Add(mesh.Key);
				}
			}
			foreach (int item in _expired)
			{
				Remove(item);
			}
		}

		internal void Draw(float now, SilhouetteTarget target, bool visible, float alpha, int layer, Color color, bool forceRed = false, float scanTime = float.NaN, float voiceGlow = 0f)
		{
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: 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)
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			//IL_004f: Unknown result type (might be due to invalid IL or missing references)
			//IL_005c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0061: Unknown result type (might be due to invalid IL or missing references)
			//IL_0122: Unknown result type (might be due to invalid IL or missing references)
			//IL_01bc: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ae: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c1: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c3: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c5: Unknown result type (might be due to invalid IL or missing references)
			//IL_032e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0333: Unknown result type (might be due to invalid IL or missing references)
			//IL_02b7: Unknown result type (might be due to invalid IL or missing references)
			//IL_02bc: Unknown result type (might be due to invalid IL or missing references)
			//IL_02c7: Unknown result type (might be due to invalid IL or missing references)
			//IL_02d4: Expected O, but got Unknown
			//IL_04df: Unknown result type (might be due to invalid IL or missing references)
			//IL_04e4: Unknown result type (might be due to invalid IL or missing references)
			//IL_055c: Unknown result type (might be due to invalid IL or missing references)
			//IL_055e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0505: Unknown result type (might be due to invalid IL or missing references)
			//IL_050a: Unknown result type (might be due to invalid IL or missing references)
			//IL_047a: Unknown result type (might be due to invalid IL or missing references)
			//IL_047c: Unknown result type (might be due to invalid IL or missing references)
			//IL_044f: Unknown result type (might be due to invalid IL or missing references)
			//IL_058c: Unknown result type (might be due to invalid IL or missing references)
			if (_disposed || (Object)(object)_material == (Object)null || !target.Alive || alpha < 0.01f)
			{
				return;
			}
			Color val = color;
			if (voiceGlow > 0f)
			{
				float num = Mathf.Clamp01(voiceGlow);
				val = Color.Lerp(val, new Color(1f, 1f, 0.95f, alpha), num * 0.6f);
			}
			_block.Clear();
			_block.SetColor("_Color", val);
			int num2 = Math.Min(target.Renderers.Length, 8);
			int num3 = 0;
			int num4 = 64;
			int num5 = ((num2 > 0) ? (target.NextMesh % num2) : 0);
			for (int i = 0; i < num2; i++)
			{
				if (num4 <= 0)
				{
					break;
				}
				if (_draws <= 0)
				{
					break;
				}
				int num6 = (num5 + i) % num2;
				Renderer val2 = target.Renderers[num6];
				try
				{
					if ((Object)(object)val2 == (Object)null || !val2.enabled || !((Component)val2).gameObject.activeInHierarchy || ((Object)(object)((Component)val2).transform != (Object)(object)target.AvatarRoot && !((Component)val2).transform.IsChildOf(target.AvatarRoot)))
					{
						continue;
					}
					SkinnedMeshRenderer val3 = ((Il2CppObjectBase)val2).TryCast<SkinnedMeshRenderer>();
					object obj;
					if (!((Object)(object)val3 != (Object)null))
					{
						MeshFilter component = ((Component)val2).GetComponent<MeshFilter>();
						obj = ((component != null) ? component.sharedMesh : null);
					}
					else
					{
						obj = val3.sharedMesh;
					}
					Mesh val4 = (Mesh)obj;
					if ((Object)(object)val4 == (Object)null || val4.vertexCount == 0 || val4.vertexCount > 120000)
					{
						continue;
					}
					int vertexCount = val4.vertexCount;
					int instanceID = ((Object)val2).GetInstanceID();
					Transform val5 = (((Object)(object)val3 != (Object)null) ? val3.rootBone : null);
					Vector3 val6 = (((Object)(object)val3 != (Object)null) ? ((Component)val3).transform.lossyScale : Vector3.one);
					if (!EchoMeshSpace.SameScale(val6, val6))
					{
						continue;
					}
					if (_meshes.TryGetValue(instanceID, out CachedMesh value) && ((Object)(object)value.Renderer != (Object)(object)val2 || (Object)(object)value.Source != (Object)(object)val4 || (Object)(object)value.AvatarRoot != (Object)(object)target.AvatarRoot || (Object)(object)value.RootBone != (Object)(object)val5 || value.Vertices != vertexCount))
					{
						Remove(instanceID);
						value = null;
					}
					if (value != null)
					{
						goto IL_02f4;
					}
					if (_bakes <= 0 || vertexCount > _bakeVertices)
					{
						continue;
					}
					while (_meshes.Count >= 128 || _cachedVertices + vertexCount > 1000000)
					{
						EvictOldest();
					}
					value = new CachedMesh
					{
						Renderer = val2,
						Source = val4,
						AvatarRoot = target.AvatarRoot,
						RootBone = val5,
						Vertices = vertexCount,
						Mesh = new Mesh
						{
							name = "CoilHead.WatcherSilhouette",
							hideFlags = (HideFlags)61
						}
					};
					_meshes[instanceID] = value;
					_cachedVertices += vertexCount;
					goto IL_02f4;
					IL_02f4:
					value.LastSeen = now;
					bool flag = float.IsFinite(scanTime);
					bool flag2 = flag && scanTime > value.ScanTime;
					bool flag3 = (Object)(object)val3 != (Object)null && value.HasSnapshot && !EchoMeshSpace.SameScale(value.BakedScale, val6);
					if ((!flag || flag2) && (now >= value.NextBake || flag3) && _bakes > 0 && vertexCount <= _bakeVertices)
					{
						_bakes--;
						_bakeVertices -= vertexCount;
						target.NextMesh = (num6 + 1) % num2;
						value.HasSnapshot = false;
						value.NextBake = now + 0.2f;
						if ((Object)(object)val3 != (Object)null)
						{
							val3.BakeMesh(value.Mesh, true);
						}
						else
						{
							Object.Destroy((Object)(object)value.Mesh);
							value.Mesh = Object.Instantiate<Mesh>(val4);
							((Object)value.Mesh).hideFlags = (HideFlags)61;
						}
						value.Mesh.RecalculateBounds();
						int vertexCount2 = value.Mesh.vertexCount;
						if (value.White == null || ((Il2CppArrayBase<Color>)(object)value.White).Length != vertexCount2)
						{
							value.White = new Il2CppStructArray<Color>((long)vertexCount2);
							for (int j = 0; j < vertexCount2; j++)
							{
								((Il2CppArrayBase<Color>)(object)value.White)[j] = Color.white;
							}
						}
						value.Mesh.SetColors(value.White);
						value.BakedScale = val6;
						value.HasSnapshot = true;
						value.NextBake = (((Object)(object)val3 != (Object)null) ? (now + ((vertexCount > 120000) ? 0.35f : 0.2f)) : float.PositiveInfinity);
					}
					Matrix4x4 matrix;
					if (value.HasSnapshot && value.Mesh.vertexCount != 0 && (flag || !((Object)(object)val3 != (Object)null) || EchoMeshSpace.SameScale(value.BakedScale, val6)))
					{
						if (flag && !flag2 && value.HasScanMatrix)
						{
							matrix = value.ScanMatrix;
							goto IL_054d;
						}
						if (EchoMeshSpace.TryGetDrawMatrix(val2, val3, value.Mesh, out matrix))
						{
							goto IL_054d;
						}
						if (now >= _nextWarning)
						{
							_nextWarning = now + 10f;
							_warning("Skipped an invalid or oversized watcher mesh snapshot.");
						}
					}
					goto end_IL_00d2;
					IL_054d:
					if (flag2)
					{
						value.ScanTime = scanTime;
						value.ScanMatrix = matrix;
						value.HasScanMatrix = true;
					}
					int draws = _draws;
					for (int k = 0; k < value.Mesh.subMeshCount; k++)
					{
						if (num4 <= 0)
						{
							break;
						}
						if (_draws <= 0)
						{
							break;
						}
						Graphics.DrawMesh(value.Mesh, matrix, _material, layer, (Camera)null, k, _block, (ShadowCastingMode)0, false, (Transform)null, (LightProbeUsage)0, (LightProbeProxyVolume)null);
						_draws--;
						num4--;
					}
					if (_draws < draws)
					{
						num3++;
					}
					end_IL_00d2:;
				}
				catch (Exception ex)
				{
					if (now >= _nextWarning)
					{
						_nextWarning = now + 10f;
						_warning("Player echo mesh: " + ex.Message);
					}
				}
			}
		}

		private void EnsureMaterial()
		{
			//IL_008e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0093: Unknown result type (might be due to invalid IL or missing references)
			//IL_009b: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a8: Expected O, but got Unknown
			//IL_00f2: Unknown result type (might be due to invalid IL or missing references)
			//IL_0166: Unknown result type (might be due to invalid IL or missing references)
			//IL_0170: Expected O, but got Unknown
			if ((Object)(object)_material != (Object)null || _now < _nextAttempt)
			{
				return;
			}
			_attempts++;
			_nextAttempt = _now + ((_attempts >= 6) ? 10f : 2f);
			string[] array = new string[2] { "Hidden/Internal-Colored", "GUI/Text Shader" };
			foreach (string text in array)
			{
				Shader val = Shader.Find(text);
				if ((Object)(object)val == (Object)null || !val.isSupported)
				{
					continue;
				}
				Material val2 = new Material(val)
				{
					hideFlags = (HideFlags)61,
					renderQueue = 5000
				};
				if (text == "Hidden/Internal-Colored" && (!val2.HasProperty("_ZTest") || !val2.HasProperty("_ZWrite")))
				{
					Object.Destroy((Object)(object)val2);
					continue;
				}
				if (val2.HasProperty("_Color"))
				{
					val2.SetColor("_Color", Color.white);
				}
				if (val2.HasProperty("_MainTex"))
				{
					val2.SetTexture("_MainTex", (Texture)(object)Texture2D.whiteTexture);
				}
				Set(val2, "_ZTest", 8);
				Set(val2, "_ZWrite", 0);
				Set(val2, "_Cull", 0);
				Set(val2, "_SrcBlend", 5);
				Set(val2, "_DstBlend", 10);
				_material = val2;
				_block = new MaterialPropertyBlock();
				return;
			}
			if (_attempts == 1 || _attempts == 6)
			{
				_warning("Player echo highlight shader unavailable.");
			}
		}

		private void EvictOldest()
		{
			int key = 0;
			float num = float.PositiveInfinity;
			foreach (KeyValuePair<int, CachedMesh> mesh in _meshes)
			{
				if (mesh.Value.LastSeen < num)
				{
					num = mesh.Value.LastSeen;
					key = mesh.Key;
				}
			}
			Remove(key);
		}

		private void Remove(int key)
		{
			if (_meshes.TryGetValue(key, out CachedMesh value))
			{
				if ((Object)(object)value.Mesh != (Object)null)
				{
					Object.Destroy((Object)(object)value.Mesh);
				}
				_cachedVertices -= value.Vertices;
				_meshes.Remove(key);
			}
		}

		internal void Reset()
		{
			foreach (CachedMesh value in _meshes.Values)
			{
				if ((Object)(object)value.Mesh != (Object)null)
				{
					Object.Destroy((Object)(object)value.Mesh);
				}
			}
			_meshes.Clear();
			_cachedVertices = 0;
			_attempts = 0;
			_nextAttempt = 0f;
			_nextCleanup = 0f;
			if ((Object)(object)_voiceMarker != (Object)null)
			{
				Object.Destroy((Object)(object)_voiceMarker);
			}
			_voiceMarker = null;
		}

		public void Dispose()
		{
			if (!_disposed)
			{
				_disposed = true;
				Reset();
				if ((Object)(object)_material != (Object)null)
				{
					Object.Destroy((Object)(object)_material);
				}
				_material = null;
				_block = null;
			}
		}

		private static void Set(Material material, string name, int value)
		{
			if (material.HasProperty(name))
			{
				material.SetInt(name, value);
			}
		}
	}
	internal sealed class PoseLock
	{
		private record struct Body(Rigidbody Value, Vector3 Position, Quaternion Rotation);

		private record struct Bone(Transform Value, Vector3 Position, Quaternion Rotation, Vector3 LocalPosition, Quaternion LocalRotation);

		private readonly List<Body> _historyBodies = new List<Body>();

		private readonly List<Body> _bodies = new List<Body>();

		private readonly List<Bone> _historyBones = new List<Bone>();

		private readonly List<Bone> _bones = new List<Bone>();

		private readonly HashSet<int> _bodyIds = new HashSet<int>();

		private readonly Func<double> _clock;

		private readonly Action<string>? _warning;

		private readonly bool _localOwner;

		private double _started;

		private double _leaseUntil;

		private double _hardDeadline;

		private double _historyTime = double.NegativeInfinity;

		private RigManager? _rig;

		private Action? _lateCallback;

		private UnityAction? _renderCallback;

		private RigSkeleton? _skeleton;

		private RigPose? _historyPose;

		private RigPose? _networkPose;

		internal static PoseLock? Current { get; private set; }

		public bool Active { get; private set; }

		internal PoseLock(Func<double>? clock = null, Action<string>? warning = null, bool localOwner = true)
		{
			_clock = clock ?? ((Func<double>)(() => Time.realtimeSinceStartupAsDouble));
			_warning = warning;
			_localOwner = localOwner;
		}

		internal void Track(RigManager rig)
		{
			//IL_00c5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cf: Expected O, but got Unknown
			//IL_00d0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00da: Expected O, but got Unknown
			if ((Object)(object)_rig == (Object)(object)rig)
			{
				return;
			}
			StopTracking();
			_rig = rig;
			try
			{
				_bodyIds.Clear();
				Enumerator<Rigidbody> enumerator = rig.physicsRig.selfRbs.GetEnumerator();
				while (enumerator.MoveNext())
				{
					Rigidbody current = enumerator.Current;
					AddBody(current);
				}
				AddBody(rig.physicsRig.rbFeet);
				AddBody(rig.physicsRig.rbKnee);
				foreach (Transform componentsInChild in ((Component)rig.avatar).GetComponentsInChildren<Transform>(true))
				{
					if ((Object)(object)componentsInChild != (Object)null)
					{
						_historyBones.Add(ReadBone(componentsInChild));
					}
				}
				if (_localOwner)
				{
					_skeleton = new RigSkeleton(rig);
					_historyPose = new RigPose();
				}
				_lateCallback = Action.op_Implicit((Action)AfterRigLateUpdate);
				_renderCallback = UnityAction.op_Implicit((Action)BeforeRender);
				rig.OnPostLateUpdate += _lateCallback;
				Application.onBeforeRender += _renderCallback;
				Record();
			}
			catch
			{
				StopTracking();
				throw;
			}
		}

		private void AddBody(Rigidbody? rb)
		{
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)rb != (Object)null && _bodyIds.Add(((Object)rb).GetInstanceID()))
			{
				_historyBodies.Add(new Body(rb, rb.position, rb.rotation));
			}
		}

		private static Bone ReadBone(Transform bone)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			return new Bone(bone, bone.position, bone.rotation, bone.localPosition, bone.localRotation);
		}

		private void Record()
		{
			//IL_0042: Unknown result type (might be due to invalid IL or missing references)
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			if (Active || (Object)(object)_rig == (Object)null)
			{
				return;
			}
			for (int i = 0; i < _historyBodies.Count; i++)
			{
				Rigidbody value = _historyBodies[i].Value;
				if ((Object)(object)value != (Object)null)
				{
					_historyBodies[i] = new Body(value, value.position, value.rotation);
				}
			}
			for (int j = 0; j < _historyBones.Count; j++)
			{
				if ((Object)(object)_historyBones[j].Value != (Object)null)
				{
					_historyBones[j] = ReadBone(_historyBones[j].Value);
				}
			}
			if (_localOwner)
			{
				_historyPose.ReadSkeleton(_skeleton);
			}
			_historyTime = _clock();
		}

		public void Capture(RigManager rig, double duration = 20.0)
		{
			//IL_004e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0062: Unknown result type (might be due to invalid IL or missing references)
			//IL_0067: Unknown result type (might be due to invalid IL or missing references)
			//IL_006c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0130: Unknown result type (might be due to invalid IL or missing references)
			//IL_0135: Unknown result type (might be due to invalid IL or missing references)
			//IL_0136: Unknown result type (might be due to invalid IL or missing references)
			//IL_0137: Unknown result type (might be due to invalid IL or missing references)
			//IL_013c: Unknown result type (might be due to invalid IL or missing references)
			//IL_013d: Unknown result type (might be due to invalid IL or missing references)
			//IL_014d: 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)
			//IL_0162: Unknown result type (might be due to invalid IL or missing references)
			//IL_0167: Unknown result type (might be due to invalid IL or missing references)
			if (Active)
			{
				return;
			}
			Release();
			Track(rig);
			double num = _clock();
			if (!double.IsFinite(num))
			{
				return;
			}
			try
			{
				Vector3 val;
				int num2;
				if (_historyBodies.Count > 0)
				{
					val = _historyBodies[0].Value.position - _historyBodies[0].Position;
					num2 = ((((Vector3)(ref val)).sqrMagnitude > 4f) ? 1 : 0);
				}
				else
				{
					num2 = 0;
				}
				bool flag = (byte)num2 != 0;
				if (num < _historyTime || num - _historyTime > 0.2 || flag)
				{
					Record();
				}
				foreach (Body historyBody in _historyBodies)
				{
					if ((Object)(object)historyBody.Value != (Object)null)
					{
						_bodies.Add(historyBody);
					}
				}
				_bones.AddRange(_historyBones);
				_networkPose = _historyPose;
				if (_networkPose != null)
				{
					val = (_networkPose.PelvisPose.Velocity = (_networkPose.PelvisPose.AngularVelocity = Vector3.zero));
					_networkPose.LeftController.ThumbstickAxis = Vector2.zero;
					_networkPose.RightController.ThumbstickAxis = Vector2.zero;
				}
				_started = num;
				_hardDeadline = num + Math.Clamp(double.IsFinite(duration) ? duration : 20.0, 1.0, 120.0);
				_leaseUntil = num + 0.35;
				Active = true;
				if (_localOwner)
				{
					Current = this;
				}
				HoldVisual();
			}
			catch
			{
				Release();
				throw;
			}
		}

		public void Renew()
		{
			double num = _clock();
			if (Active)
			{
				if (!double.IsFinite(num) || num < _started || num >= _hardDeadline)
				{
					Release();
				}
				else
				{
					_leaseUntil = Math.Min(num + 0.35, _hardDeadline);
				}
			}
		}

		private bool CanHold()
		{
			if (!Active)
			{
				return false;
			}
			double num = _clock();
			if (!double.IsFinite(num) || num < _started || num >= _leaseUntil || num >= _hardDeadline)
			{
				Release();
				return false;
			}
			return true;
		}

		public void Hold()
		{
			//IL_006a: Unknown result type (might be due to invalid IL or missing references)
			//IL_007d: 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_009c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0046: Unknown result type (might be due to invalid IL or missing references)
			//IL_0057: Unknown result type (might be due to invalid IL or missing references)
			if (!CanHold())
			{
				return;
			}
			foreach (Body body in _bodies)
			{
				if (!((Object)(object)body.Value == (Object)null))
				{
					if (!body.Value.isKinematic)
					{
						body.Value.velocity = Vector3.zero;
						body.Value.angularVelocity = Vector3.zero;
					}
					body.Value.position = body.Position;
					body.Value.rotation = body.Rotation;
					((Component)body.Value).transform.SetPositionAndRotation(body.Position, body.Rotation);
				}
			}
		}

		public void HoldVisual()
		{
			//IL_0046: Unknown result type (might be due to invalid IL or missing references)
			//IL_004d: Unknown result type (might be due to invalid IL or missing references)
			if (!CanHold())
			{
				return;
			}
			Hold();
			if (!Active)
			{
				return;
			}
			foreach (Bone bone in _bones)
			{
				if ((Object)(object)bone.Value != (Object)null)
				{
					bone.Value.SetPositionAndRotation(bone.Position, bone.Rotation);
				}
			}
		}

		public void Release()
		{
			//IL_006c: Unknown result type (might be due to invalid IL or missing references)
			//IL_007f: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ee: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fb: Unknown result type (might be due to invalid IL or missing references)
			bool active = Active;
			Active = false;
			if (Current == this)
			{
				Current = null;
			}
			_networkPose = null;
			_leaseUntil = (_hardDeadline = 0.0);
			int num = 0;
			foreach (Bone bone in _bones)
			{
				try
				{
					if ((Object)(object)bone.Value != (Object)null)
					{
						bone.Value.localPosition = bone.LocalPosition;
						bone.Value.localRotation = bone.LocalRotation;
					}
				}
				catch
				{
					num++;
				}
			}
			foreach (Body body in _bodies)
			{
				try
				{
					if ((Object)(object)body.Value != (Object)null && !body.Value.isKinematic)
					{
						Rigidbody value = body.Value;
						Vector3 velocity = (body.Value.angularVelocity = Vector3.zero);
						value.velocity = velocity;
						body.Value.WakeUp();
					}
				}
				catch
				{
					num++;
				}
			}
			_bodies.Clear();
			_bones.Clear();
			if (active)
			{
				_historyTime = double.NegativeInfinity;
			}
			if (active && num > 0)
			{
				Warn($"Mannequin released; {num} unavailable rig parts skipped. No native movement locks were set.");
			}
		}

		internal void StopTracking()
		{
			Release();
			try
			{
				if ((Object)(object)_rig != (Object)null && (Delegate)(object)_lateCallback != (Delegate)null)
				{
					RigManager? rig = _rig;
					rig.OnPostLateUpdate -= _lateCallback;
				}
			}
			catch (Exception ex)
			{
				Warn("Mannequin late callback cleanup: " + ex.Message);
			}
			try
			{
				if ((Delegate)(object)_renderCallback != (Delegate)null)
				{
					Application.onBeforeRender -= _renderCallback;
				}
			}
			catch (Exception ex2)
			{
				Warn("Mannequin render callback cleanup: " + ex2.Message);
			}
			_lateCallback = null;
			_renderCallback = null;
			_rig = null;
			_historyPose = null;
			_skeleton = null;
			_historyBodies.Clear();
			_historyBones.Clear();
			_historyTime = double.NegativeInfinity;
		}

		private void Warn(string message)
		{
			try
			{
				_warning?.Invoke(message);
			}
			catch
			{
			}
		}

		private void AfterRigLateUpdate()
		{
			try
			{
				if (!((Object)(object)_rig == (Object)null))
				{
					if (CanHold())
					{
						HoldVisual();
						return;
					}
					Release();
					Record();
				}
			}
			catch (Exception ex)
			{
				Release();
				Warn(ex.Message);
			}
		}

		private void BeforeRender()
		{
			try
			{
				HoldVisual();
			}
			catch (Exception ex)
			{
				Release();
				Warn(ex.Message);
			}
		}

		internal static void AfterReadSkeleton(RigPose __instance, RigSkeleton skeleton)
		{
			PoseLock current = Current;
			if (current != null && current.CanHold() && !((Object)(object)current._rig == (Object)null) && current._networkPose != null && !((Object)(object)((Component)skeleton.PhysicsPelvis).transform != (Object)(object)((Rig)current._rig.physicsRig).m_pelvis))
			{
				RigPose networkPose = current._networkPose;
				for (int i = 1; i < 3; i++)
				{
					__instance.TrackedPoints[i] = networkPose.TrackedPoints[i];
				}
				networkPose.PelvisPose.CopyTo(__instance.PelvisPose);
				__instance.LeftController = networkPose.LeftController;
				__instance.RightController = networkPose.RightController;
				__instance.CrouchTarget = networkPose.CrouchTarget;
				__instance.FeetOffset = networkPose.FeetOffset;
			}
		}
	}
	internal sealed class RemoteFreeze
	{
		private sealed class Peer
		{
			internal readonly RemoteFreezeLease Lease = new RemoteFreezeLease();

			internal readonly PoseLock Pose = new PoseLock(null, delegate(string message)
			{
				MelonLogger.Warning(message);
			}, localOwner: false);

			internal RigManager Rig;

			internal Transform Avatar;

			internal bool Warned;
		}

		private const string Key = "MannequinMod.Pose.v1";

		private readonly Dictionary<NetworkPlayer, Peer> _peers = new Dictionary<NetworkPlayer, Peer>();

		private readonly HashSet<NetworkPlayer> _seen = new HashSet<NetworkPlayer>();

		private readonly List<NetworkPlayer> _remove = new List<NetworkPlayer>();

		private string _token = "";

		private string _sent = "";

		private long _sequence;

		private bool _wasFrozen;

		private double _nextSend;

		internal void Publish(bool enabled, bool frozen, int duration = 20)
		{
			PlayerMetadata metadata = LocalPlayer.Metadata;
			NetworkMetadata val = ((metadata != null) ? metadata.Metadata : null);
			if (val == null)
			{
				return;
			}
			double realtimeSinceStartupAsDouble = Time.realtimeSinceStartupAsDouble;
			if (!enabled || !NetworkInfo.HasServer)
			{
				if (_sent.Length != 0 && val.TryRemoveMetadata("MannequinMod.Pose.v1"))
				{
					_sent = "";
				}
				_wasFrozen = false;
				return;
			}
			if (frozen && !_wasFrozen)
			{
				_token = Guid.NewGuid().ToString("N");
				_sequence = 0L;
				_nextSend = 0.0;
			}
			if (!frozen || !_wasFrozen || !(realtimeSinceStartupAsDouble < _nextSend))
			{
				string text = (frozen ? $"F|{_token}|{++_sequence}|{Math.Clamp(duration, 1, 120)}" : "R");
				if (text != _sent && val.TrySetMetadata("MannequinMod.Pose.v1", text))
				{
					_sent = text;
					_nextSend = realtimeSinceStartupAsDouble + 0.4;
				}
				_wasFrozen = frozen;
			}
		}

		internal void Update(RigManager? localRig = null)
		{
			if (!NetworkInfo.HasServer)
			{
				ResetPeers();
				return;
			}
			_seen.Clear();
			double realtimeSinceStartupAsDouble = Time.realtimeSinceStartupAsDouble;
			string text = default(string);
			foreach (NetworkPlayer player in NetworkPlayer.Players)
			{
				try
				{
					if (player.PlayerID == null || player.PlayerID.IsMe || !player.PlayerID.IsValid || !player.HasRig || player.ForceHide)
					{
						continue;
					}
					RigRefs rigRefs = player.RigRefs;
					RigManager val = ((rigRefs != null) ? rigRefs.RigManager : null);
					if ((Object)(object)val == (Object)null || (Object)(object)val == (Object)(object)localRig || (Object)(object)val.avatar == (Object)null || ((Object)(object)val.health != (Object)null && val.health.curr_Health <= 0f))
					{
						continue;
					}
					PlayerMetadata metadata = player.PlayerID.Metadata;
					NetworkMetadata val2 = ((metadata != null) ? metadata.Metadata : null);
					_seen.Add(player);
					if (val2 == null || !val2.TryGetMetadata("MannequinMod.Pose.v1", ref text) || (text != "R" && !text.StartsWith("F|", StringComparison.Ordinal)))
					{
						if (_peers.TryGetValue(player, out Peer value))
						{
							value.Lease.Observe(null, realtimeSinceStartupAsDouble);
							value.Pose.StopTracking();
						}
						continue;
					}
					if (!_peers.TryGetValue(player, out Peer value2))
					{
						value2 = (_peers[player] = new Peer());
					}
					Transform transform = ((Component)val.avatar).transform;
					if ((Object)(object)value2.Rig != (Object)(object)val || (Object)(object)value2.Avatar != (Object)(object)transform)
					{
						if ((Object)(object)value2.Rig != (Object)null)
						{
							value2.Lease.Observe(null, realtimeSinceStartupAsDouble);
						}
						value2.Pose.StopTracking();
						value2.Rig = val;
						value2.Avatar = transform;
					}
					value2.Pose.Track(val);
					if (value2.Lease.Observe(text, realtimeSinceStartupAsDouble))
					{
						if (!value2.Pose.Active)
						{
							value2.Pose.Capture(val, value2.Lease.Duration);
						}
						value2.Pose.Renew();
					}
					else
					{
						value2.Pose.Release();
					}
				}
				catch (Exception ex)
				{
					if (_peers.TryGetValue(player, out Peer value3))
					{
						value3.Lease.Observe(null, realtimeSinceStartupAsDouble);
						value3.Pose.StopTracking();
						if (!value3.Warned)
						{
							value3.Warned = true;
							MelonLogger.Warning("Mannequin remote pose released: " + ex.Message);
						}
					}
				}
			}
			_remove.Clear();
			foreach (KeyValuePair<NetworkPlayer, Peer> peer2 in _peers)
			{
				if (!_seen.Contains(peer2.Key))
				{
					_remove.Add(peer2.Key);
				}
			}
			foreach (NetworkPlayer item in _remove)
			{
				Retire(_peers[item].Pose);
				_peers.Remove(item);
			}
		}

		private void Retire(PoseLock pose)
		{
			pose.StopTracking();
		}

		internal void HoldFixed()
		{
			foreach (Peer value in _peers.Values)
			{
				try
				{
					value.Pose.Hold();
				}
				catch
				{
					value.Lease.Observe(null, Time.realtimeSinceStartupAsDouble);
					value.Pose.Release();
				}
			}
		}

		internal void ResetPeers()
		{
			foreach (Peer value in _peers.Values)
			{
				Retire(value.Pose);
			}
			_peers.Clear();
		}
	}
	internal sealed class RemoteFreezeLease
	{
		private string _token = "";

		private long _sequence = -1L;

		private double _lastHeartbeat;

		private double _deadline;

		private bool _expired;

		private string? _wire;

		internal int Duration { get; private set; } = 20;

		internal bool Observe(string? value, double now)
		{
			if (!double.IsFinite(now) || value == null || value.Length > 90 || !value.StartsWith("F|", StringComparison.Ordinal))
			{
				_expired = true;
				return false;
			}
			if (value == _wire)
			{
				if (now < _lastHeartbeat || now - _lastHeartbeat > 1.5 || now >= _deadline)
				{
					_expired = true;
				}
				return !_expired;
			}
			string[] array = value.Split('|');
			int result = 20;
			if ((array.Length != 3 && array.Length != 4) || !Guid.TryParseExact(array[1], "N", out var _) || !long.TryParse(array[2], out var result3) || result3 < 0 || (array.Length == 4 && (!int.TryParse(array[3], out result) || result < 1 || result > 120)))
			{
				_expired = true;
				return false;
			}
			_wire = value;
			if (array[1] != _token)
			{
				_token = array[1];
				_sequence = result3;
				_lastHeartbeat = now;
				Duration = result;
				_deadline = now + (double)result;
				_expired = false;
			}
			else
			{
				if (result != Duration)
				{
					_expired = true;
				}
				if (now < _lastHeartbeat || now - _lastHeartbeat > 1.5 || now >= _deadline)
				{
					_expired = true;
				}
				if (!_expired && result3 > _sequence)
				{
					_sequence = result3;
					_lastHeartbeat = now;
				}
			}
			if (now < _lastHeartbeat || now - _lastHeartbeat > 1.5 || now >= _deadline)
			{
				_expired = true;
			}
			return !_expired;
		}
	}
	internal sealed class SightQuery
	{
		private readonly Il2CppStructArray<RaycastHit> _hits = new Il2CppStructArray<RaycastHit>(64L);

		private static int _viewAngle = 60;

		private static float _cosine = 0.8660254f;

		internal static int ViewAngle
		{
			get
			{
				return _viewAngle;
			}
			set
			{
				_viewAngle = Math.Clamp(value, 20, 100);
				_cosine = (float)Math.Cos((double)_viewAngle * Math.PI / 360.0);
			}
		}

		internal static bool InCone(Vector3 eye, Vector3 forward, Vector3 point)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_0040: 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_004c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0053: Unknown result type (might be due to invalid IL or missing references)
			Vector3 val = point - eye;
			float sqrMagnitude = ((Vector3)(ref val)).sqrMagnitude;
			float sqrMagnitude2 = ((Vector3)(ref forward)).sqrMagnitude;
			if (float.IsFinite(sqrMagnitude) && float.IsFinite(sqrMagnitude2) && sqrMagnitude2 > 1E-06f && sqrMagnitude >= 1E-06f && sqrMagnitude <= 10000f)
			{
				return Vector3.Dot(forward / Mathf.Sqrt(sqrMagnitude2), val / Mathf.Sqrt(sqrMagnitude)) >= _cosine;
			}
			return false;
		}

		internal bool Visible(Vector3 eye, Vector3 forward, Transform observer, Transform target, Vector3 point, Transform? otherObserverRoot = null)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_000d: 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)
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: 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)
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_0055: Unknown result type (might be due to invalid IL or missing references)
			//IL_005a: Unknown result type (might be due to invalid IL or missing references)
			if (!InCone(eye, forward, point))
			{
				return false;
			}
			Vector3 val = point - eye;
			float num = Mathf.Sqrt(((Vector3)(ref val)).sqrMagnitude);
			int num2 = Physics.RaycastNonAlloc(eye, val / num, _hits, num, -1, (QueryTriggerInteraction)1);
			if (num2 >= ((Il2CppArrayBase<RaycastHit>)(object)_hits).Length)
			{
				return false;
			}
			for (int i = 0; i < num2; i++)
			{
				RaycastHit val2 = ((Il2CppArrayBase<RaycastHit>)(object)_hits)[i];
				Collider collider = ((RaycastHit)(ref val2)).collider;
				if (!((Object)(object)collider == (Object)null))
				{
					Transform transform = ((Component)collider).transform;
					if (!Within(transform, observer) && !Within(transform, target) && !Within(transform, otherObserverRoot))
					{
						return false;
					}
				}
			}
			return true;
		}

		private static bool Within(Transform t, Transform? root)
		{
			if ((Object)(object)root != (Object)null)
			{
				if (!((Object)(object)t == (Object)(object)root))
				{
					return t.IsChildOf(root);
				}
				return true;
			}
			return false;
		}
	}
	internal sealed class SilhouetteTarget
	{
		internal Transform Root;

		internal Transform AvatarRoot;

		internal Renderer[] Renderers = Array.Empty<Renderer>();

		internal int NextMesh;

		internal float NextRefresh;

		internal float LastSeen;

		internal bool Alive
		{
			get
			{
				if ((Object)(object)Root != (Object)null && (Object)(object)AvatarRoot != (Object)null)
				{
					return ((Component)Root).gameObject.activeInHierarchy;
				}
				return false;
			}
		}
	}
	internal sealed class WatcherOutline : IDisposable
	{
		private readonly PlayerSilhouetteRenderer _renderer = new PlayerSilhouetteRenderer(delegate(string message)
		{
			MelonLogger.Warning(message);
		});

		private readonly Dictionary<int, SilhouetteTarget> _targets = new Dictionary<int, SilhouetteTarget>();

		private readonly List<int> _expired = new List<int>();

		private readonly List<Renderer> _candidates = new List<Renderer>();

		private float _nextCleanup;

		private int _start;

		public void Draw(List<NetworkPlayer> watchers, List<AIBrain> npcs, Transform? eye, Color color)
		{
			//IL_02cb: Unknown result type (might be due to invalid IL or missing references)
			int num = watchers.Count + npcs.Count;
			if ((Object)(object)eye == (Object)null || num == 0)
			{
				return;
			}
			Camera val = HeadsetView.Camera();
			if ((Object)(object)val == (Object)null)
			{
				return;
			}
			int num2 = HeadsetView.VisibleLayer(val.cullingMask);
			if (num2 < 0)
			{
				return;
			}
			float unscaledTime = Time.unscaledTime;
			_renderer.BeginFrame(unscaledTime);
			int num3 = 1;
			if (_start >= num)
			{
				_start = 0;
			}
			int num4 = _start++;
			for (int i = 0; i < num; i++)
			{
				int num5 = (num4 + i) % num;
				Transform transform;
				Transform val3;
				if (num5 < watchers.Count)
				{
					NetworkPlayer val2 = watchers[num5];
					if (!val2.HasRig)
					{
						continue;
					}
					RigRefs rigRefs = val2.RigRefs;
					if ((Object)(object)((rigRefs != null) ? rigRefs.RigManager : null) == (Object)null)
					{
						continue;
					}
					RigManager rigManager = val2.RigRefs.RigManager;
					if ((Object)(object)rigManager.avatar == (Object)null)
					{
						continue;
					}
					transform = ((Component)rigManager).transform;
					val3 = ((Component)rigManager.avatar).transform;
				}
				else
				{
					AIBrain val4 = npcs[num5 - watchers.Count];
					if ((Object)(object)val4 == (Object)null || val4.isDead || (Object)(object)val4.puppetMaster == (Object)null)
					{
						continue;
					}
					transform = ((Component)val4.puppetMaster).transform;
					val3 = val4.puppetMaster.targetRoot;
					if ((Object)(object)val3 == (Object)null)
					{
						continue;
					}
				}
				int instanceID = ((Object)val3).GetInstanceID();
				if (!_targets.TryGetValue(instanceID, out SilhouetteTarget value) || (Object)(object)value.AvatarRoot != (Object)(object)val3)
				{
					if (num3 == 0)
					{
						continue;
					}
					value = new SilhouetteTarget
					{
						Root = transform,
						AvatarRoot = val3
					};
					_targets[instanceID] = value;
				}
				value.LastSeen = unscaledTime;
				if (unscaledTime >= value.NextRefresh && num3 > 0)
				{
					num3--;
					value.NextRefresh = unscaledTime + 3f;
					_candidates.Clear();
					foreach (Renderer componentsInChild in ((Component)val3).GetComponentsInChildren<Renderer>(false))
					{
						if ((Object)(object)componentsInChild != (Object)null && componentsInChild.enabled)
						{
							_candidates.Add(componentsInChild);
						}
					}
					_candidates.Sort(delegate(Renderer a, Renderer b)
					{
						//IL_0001: Unknown result type (might be due to invalid IL or missing references)
						//IL_0006: Unknown result type (might be due to invalid IL or missing references)
						//IL_0009: Unknown result type (might be due to invalid IL or missing references)
						//IL_000e: Unknown result type (might be due to invalid IL or missing references)
						//IL_001a: Unknown result type (might be due to invalid IL or missing references)
						//IL_001f: Unknown result type (might be due to invalid IL or missing references)
						//IL_0022: Unknown result type (might be due to invalid IL or missing references)
						//IL_0027: Unknown result type (might be due to invalid IL or missing references)
						Bounds bounds = b.bounds;
						Vector3 size = ((Bounds)(ref bounds)).size;
						float sqrMagnitude = ((Vector3)(ref size)).sqrMagnitude;
						bounds = a.bounds;
						size = ((Bounds)(ref bounds)).size;
						return sqrMagnitude.CompareTo(((Vector3)(ref size)).sqrMagnitude);
					});
					int num6 = Math.Min(8, _candidates.Count);
					value.Renderers = (Renderer[])(object)new Renderer[num6];
					for (int num7 = 0; num7 < num6; num7++)
					{
						value.Renderers[num7] = _candidates[num7];
					}
				}
				_renderer.Draw(unscaledTime, value, visible: true, 1f, num2, color);
			}
			if (!(unscaledTime >= _nextCleanup))
			{
				return;
			}
			_nextCleanup = unscaledTime + 2f;
			_expired.Clear();
			foreach (KeyValuePair<int, SilhouetteTarget> target in _targets)
			{
				if (!target.Value.Alive || unscaledTime - target.Value.LastSeen > 12f)
				{
					_expired.Add(target.Key);
				}
			}
			foreach (int item in _expired)
			{
				_targets.Remove(item);
			}
		}

		public void Clear()
		{
			_renderer.Reset();
			_targets.Clear();
			_start = 0;
		}

		public void Dispose()
		{
			Clear();
			_renderer.Dispose();
		}
	}
	internal sealed class WatcherScanner
	{
		private sealed class Observer
		{
			internal NetworkPlayer Player;

			internal bool Watching;

			internal float NextCheck;

			internal float LastCheck;
		}

		private readonly List<Observer> _players = new List<Observer>();

		private readonly Dictionary<NetworkPlayer, Observer> _previous = new Dictionary<NetworkPlayer, Observer>();

		private readonly SightQuery _sight = new SightQuery();

		private int _cursor;

		private float _nextRoster;

		internal void Scan(float now, RigManager local, List<NetworkPlayer> watchers)
		{
			//IL_010c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0111: Unknown result type (might be due to invalid IL or missing references)
			//IL_011d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0122: Unknown result type (might be due to invalid IL or missing references)
			//IL_0123: 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_012a: Unknown result type (might be due to invalid IL or missing references)
			//IL_012f: Unknown result type (might be due to invalid IL or missing references)
			//IL_03ad: Unknown result type (might be due to invalid IL or missing references)
			//IL_03af: Unknown result type (might be due to invalid IL or missing references)
			//IL_03b1: Unknown result type (might be due to invalid IL or missing references)
			//IL_03b9: Unknown result type (might be due to invalid IL or missing references)
			//IL_03bb: Unknown result type (might be due to invalid IL or missing references)
			//IL_03bd: Unknown result type (might be due to invalid IL or missing references)
			//IL_027c: Unknown result type (might be due to invalid IL or missing references)
			//IL_027e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0283: Unknown result type (might be due to invalid IL or missing references)
			//IL_03c5: Unknown result type (might be due to invalid IL or missing references)
			//IL_03c7: Unknown result type (might be due to invalid IL or missing references)
			//IL_03c9: Unknown result type (might be due to invalid IL or missing references)
			//IL_0292: Unknown result type (might be due to invalid IL or missing references)
			//IL_0294: Unknown result type (might be due to invalid IL or missing references)
			//IL_0299: Unknown result type (might be due to invalid IL or missing references)
			//IL_02a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_02aa: Unknown result type (might be due to invalid IL or missing references)
			//IL_02af: Unknown result type (might be due to invalid IL or missing references)
			if (now >= _nextRoster)
			{
				_nextRoster = now + 0.25f;
				_previous.Clear();
				foreach (Observer player3 in _players)
				{
					_previous[player3.Player] = player3;
				}
				_players.Clear();
				foreach (NetworkPlayer player4 in NetworkPlayer.Players)
				{
					if (player4.PlayerID != null && !player4.PlayerID.IsMe && player4.PlayerID.IsValid)
					{
						_players.Add(_previous.TryGetValue(player4, out Observer value) ? value : new Observer
						{
							Player = player4
						});
					}
				}
				_previous.Clear();
			}
			Vector3 position = ((Rig)local.physicsRig).m_head.position;
			Vector3 position2 = ((Rig)local.physicsRig).m_pelvis.position;
			Vector3 point = Vector3.Lerp(position, position2, 0.55f);
			Transform transform = ((Component)local).transform;
			int num = 0;
			for (int i = 0; i < _players.Count; i++)
			{
				if (num >= 8)
				{
					break;
				}
				if (_cursor >= _players.Count)
				{
					_cursor = 0;
				}
				Observer observer = _players[_cursor++];
				if (now < observer.NextCheck)
				{
					continue;
				}
				num++;
				observer.NextCheck = now + 0.05f;
				observer.LastCheck = now;
				observer.Watching = false;
				NetworkPlayer player = observer.Player;
				if (player.PlayerID.IsValid && player.HasRig && !player.ForceHide)
				{
					RigRefs rigRefs = player.RigRefs;
					RigManager val = ((rigRefs != null) ? rigRefs.RigManager : null);
					if (!((Object)(object)val == (Object)null) && !((Object)(object)val == (Object)(object)local) && !((Object)(object)rigRefs.Headset == (Object)null) && !((Object)(object)val.avatar == (Object)null) && (!((Object)(object)val.health != (Object)null) || !(val.health.curr_Health <= 0f)) && PlayerGaze.TryRead(player, Time.realtimeSinceStartupAsDouble, out var eye, out var forward))
					{
						Transform transform2 = ((Component)val).transform;
						observer.Watching = _sight.Visible(eye, forward, transform2, transform, position) || _sight.Visible(eye, forward, transform2, transform, point) || _sight.Visible(eye, forward, transform2, transform, position2);
					}
				}
			}
			watchers.Clear();
			foreach (Observer player5 in _players)
			{
				NetworkPlayer player2 = player5.Player;
				if (player5.Watching && !(now < player5.LastCheck) && !(now - player5.LastCheck > 0.35f) && player2.PlayerID.IsValid && player2.HasRig && !player2.ForceHide && PlayerGaze.TryRead(player2, Time.realtimeSinceStartupAsDouble, out var eye2, out var forward2))
				{
					RigRefs rigRefs2 = player2.RigRefs;
					object obj;
					if (rigRefs2 == null)
					{
						obj = null;
					}
					else
					{
						RigManager rigManager = rigRefs2.RigManager;
						obj = ((rigManager != null) ? rigManager.health : null);
					}
					if ((!((Object)obj != (Object)null) || !(player2.RigRefs.RigManager.health.curr_Health <= 0f)) && (SightQuery.InCone(eye2, forward2, position) || SightQuery.InCone(eye2, forward2, point) || SightQuery.InCone(eye2, forward2, position2)))
					{
						watchers.Add(player2);
						continue;
					}
				}
				player5.Watching = false;
			}
		}

		internal void Clear()
		{
			_players.Clear();
			_previous.Clear();
			_cursor = 0;
			_nextRoster = 0f;
		}
	}
	internal sealed class WatchTimer
	{
		private double? _since;

		private double _cooldownUntil;

		private double _lastTime = double.NegativeInfinity;

		private bool _watchingForLook;

		public double Elapsed { get; private set; }

		public double CooldownRemaining { get; private set; }

		public double FreezeSeconds { get; private set; } = 20.0;

		public double CooldownSeconds { get; private set; } = 20.0;

		public double LookSeconds { get; private set; } = 2.5;

		public double LookElapsed { get; private set; }

		public bool CountdownActive => _since.HasValue;

		public double FreezeRemaining
		{
			get
			{
				if (!CountdownActive)
				{
					return 0.0;
				}
				return Math.Max(0.0, FreezeSeconds - Elapsed);
			}
		}

		public bool Frozen { get; private set; }

		internal void Configure(int freeze, int cooldown, double look = 2.5)
		{
			Reset();
			FreezeSeconds = Math.Clamp(freeze, 1, 120);
			CooldownSeconds = Math.Clamp(cooldown, 0, 120);
			LookSeconds = (double.IsFinite(look) ? Math.Clamp(look, 0.0, 10.0) : 2.5);
		}

		public bool Tick(bool enabled, bool watched, double now)
		{
			if (!enabled || !double.IsFinite(now))
			{
				Reset();
				return false;
			}
			if (now < _lastTime)
			{
				Reset();
			}
			double delta = (double.IsFinite(_lastTime) ? (now - _lastTime) : 0.0);
			_lastTime = now;
			CooldownRemaining = Math.Max(0.0, _cooldownUntil - now);
			if (CooldownRemaining > 0.0)
			{
				ResetLook();
				Frozen = false;
				Elapsed = 0.0;
				return false;
			}
			if (!_since.HasValue)
			{
				if (!Qualifies(watched, delta))
				{
					Elapsed = 0.0;
					return Frozen = false;
				}
				_since = now;
				Elapsed = 0.0;
				return Frozen = true;
			}
			Elapsed = now - _since.Value;
			if (Elapsed >= FreezeSeconds)
			{
				_since = null;
				ResetLook();
				_cooldownUntil = now + CooldownSeconds;
				CooldownRemaining = CooldownSeconds;
				Elapsed = 0.0;
				return Frozen = false;
			}
			if (Frozen)
			{
				if (watched)
				{
					return true;
				}
				ResetLook();
				return Frozen = false;
			}
			if (FreezeRemaining <= 5.0)
			{
				ResetLook();
				return false;
			}
			return Frozen = Qualifies(watched, delta);
		}

		private bool Qualifies(bool watched, double delta)
		{
			if (_watchingForLook && delta >= 0.0 && delta <= 0.35)
			{
				LookElapsed = Math.Min(LookSeconds, LookElapsed + delta);
			}
			_watchingForLook = watched;
			if (!watched || LookElapsed + 1E-09 < LookSeconds)
			{
				return false;
			}
			ResetLook();
			return true;
		}

		private void ResetLook()
		{
			_watchingForLook = false;
			LookElapsed = 0.0;
		}

		public void Reset()
		{
			_since = null;
			_cooldownUntil = 0.0;
			_lastTime = double.NegativeInfinity;
			double elapsed = (CooldownRemaining = 0.0);
			Elapsed = elapsed;
			Frozen = false;
			ResetLook();
		}
	}
}