Decompiled source of PeakSpectatorMode v1.1.1

PeakSpectatorMode.dll

Decompiled 4 days ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using System.Text.RegularExpressions;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using Photon.Pun;
using Photon.Realtime;
using TMPro;
using UnityEngine;
using UnityEngine.Rendering;
using UnityEngine.SceneManagement;
using UnityEngine.UI;
using Zorro.Core;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: IgnoresAccessChecksTo("Ashley.MeshSplitter")]
[assembly: IgnoresAccessChecksTo("Assembly-CSharp-firstpass")]
[assembly: IgnoresAccessChecksTo("Assembly-CSharp")]
[assembly: IgnoresAccessChecksTo("com.rlabrecque.steamworks.net")]
[assembly: IgnoresAccessChecksTo("DemiLib")]
[assembly: IgnoresAccessChecksTo("DOTween")]
[assembly: IgnoresAccessChecksTo("DOTweenPro")]
[assembly: IgnoresAccessChecksTo("HBAO.Runtime")]
[assembly: IgnoresAccessChecksTo("HBAO.Universal.Runtime")]
[assembly: IgnoresAccessChecksTo("LightVolume.Runtime")]
[assembly: IgnoresAccessChecksTo("Mono.Security")]
[assembly: IgnoresAccessChecksTo("Newtonsoft.Json")]
[assembly: IgnoresAccessChecksTo("Photon3Unity3D")]
[assembly: IgnoresAccessChecksTo("PhotonChat")]
[assembly: IgnoresAccessChecksTo("PhotonRealtime")]
[assembly: IgnoresAccessChecksTo("PhotonUnityNetworking.Demos")]
[assembly: IgnoresAccessChecksTo("PhotonUnityNetworking")]
[assembly: IgnoresAccessChecksTo("PhotonUnityNetworking.Utilities")]
[assembly: IgnoresAccessChecksTo("PhotonVoice.API")]
[assembly: IgnoresAccessChecksTo("PhotonVoice")]
[assembly: IgnoresAccessChecksTo("PhotonVoice.PUN")]
[assembly: IgnoresAccessChecksTo("pworld")]
[assembly: IgnoresAccessChecksTo("sc.posteffects.runtime")]
[assembly: IgnoresAccessChecksTo("Sirenix.OdinInspector.Attributes")]
[assembly: IgnoresAccessChecksTo("Sirenix.OdinInspector.Modules.Unity.Addressables")]
[assembly: IgnoresAccessChecksTo("Sirenix.OdinInspector.Modules.UnityLocalization")]
[assembly: IgnoresAccessChecksTo("Sirenix.Serialization.Config")]
[assembly: IgnoresAccessChecksTo("Sirenix.Serialization")]
[assembly: IgnoresAccessChecksTo("Sirenix.Utilities")]
[assembly: IgnoresAccessChecksTo("Tayx.Graphy")]
[assembly: IgnoresAccessChecksTo("unity-websocket-sharp")]
[assembly: IgnoresAccessChecksTo("Unity.Addressables")]
[assembly: IgnoresAccessChecksTo("Unity.AI.Navigation")]
[assembly: IgnoresAccessChecksTo("Unity.Animation.Rigging")]
[assembly: IgnoresAccessChecksTo("Unity.Animation.Rigging.DocCodeExamples")]
[assembly: IgnoresAccessChecksTo("Unity.Burst")]
[assembly: IgnoresAccessChecksTo("Unity.Burst.Unsafe")]
[assembly: IgnoresAccessChecksTo("Unity.Cinemachine")]
[assembly: IgnoresAccessChecksTo("Unity.Collections")]
[assembly: IgnoresAccessChecksTo("Unity.Collections.LowLevel.ILSupport")]
[assembly: IgnoresAccessChecksTo("Unity.InputSystem")]
[assembly: IgnoresAccessChecksTo("Unity.InputSystem.ForUI")]
[assembly: IgnoresAccessChecksTo("Unity.InputSystem.RebindingUI")]
[assembly: IgnoresAccessChecksTo("Unity.InternalAPIEngineBridge.004")]
[assembly: IgnoresAccessChecksTo("Unity.InternalAPIEngineBridge.013")]
[assembly: IgnoresAccessChecksTo("Unity.Localization")]
[assembly: IgnoresAccessChecksTo("Unity.Mathematics")]
[assembly: IgnoresAccessChecksTo("Unity.MemoryProfiler")]
[assembly: IgnoresAccessChecksTo("Unity.Multiplayer.Center.Common")]
[assembly: IgnoresAccessChecksTo("Unity.Multiplayer.Playmode.Common.Runtime")]
[assembly: IgnoresAccessChecksTo("Unity.Multiplayer.Playmode")]
[assembly: IgnoresAccessChecksTo("Unity.Networking.Transport")]
[assembly: IgnoresAccessChecksTo("Unity.Profiling.Core")]
[assembly: IgnoresAccessChecksTo("Unity.Rendering.LightTransport.Runtime")]
[assembly: IgnoresAccessChecksTo("Unity.RenderPipeline.Universal.ShaderLibrary")]
[assembly: IgnoresAccessChecksTo("Unity.RenderPipelines.Core.Runtime")]
[assembly: IgnoresAccessChecksTo("Unity.RenderPipelines.Core.Runtime.Shared")]
[assembly: IgnoresAccessChecksTo("Unity.RenderPipelines.Core.ShaderLibrary")]
[assembly: IgnoresAccessChecksTo("Unity.RenderPipelines.GPUDriven.Runtime")]
[assembly: IgnoresAccessChecksTo("Unity.RenderPipelines.ShaderGraph.ShaderGraphLibrary")]
[assembly: IgnoresAccessChecksTo("Unity.RenderPipelines.Universal.2D.Runtime")]
[assembly: IgnoresAccessChecksTo("Unity.RenderPipelines.Universal.Config.Runtime")]
[assembly: IgnoresAccessChecksTo("Unity.RenderPipelines.Universal.Runtime")]
[assembly: IgnoresAccessChecksTo("Unity.RenderPipelines.Universal.Shaders")]
[assembly: IgnoresAccessChecksTo("Unity.ResourceManager")]
[assembly: IgnoresAccessChecksTo("Unity.ScriptableBuildPipeline")]
[assembly: IgnoresAccessChecksTo("Unity.Services.Authentication")]
[assembly: IgnoresAccessChecksTo("Unity.Services.Authentication.PlayerAccounts")]
[assembly: IgnoresAccessChecksTo("Unity.Services.Core.Analytics")]
[assembly: IgnoresAccessChecksTo("Unity.Services.Core.Components")]
[assembly: IgnoresAccessChecksTo("Unity.Services.Core.Configuration")]
[assembly: IgnoresAccessChecksTo("Unity.Services.Core.Device")]
[assembly: IgnoresAccessChecksTo("Unity.Services.Core")]
[assembly: IgnoresAccessChecksTo("Unity.Services.Core.Environments")]
[assembly: IgnoresAccessChecksTo("Unity.Services.Core.Environments.Internal")]
[assembly: IgnoresAccessChecksTo("Unity.Services.Core.Internal")]
[assembly: IgnoresAccessChecksTo("Unity.Services.Core.Networking")]
[assembly: IgnoresAccessChecksTo("Unity.Services.Core.Registration")]
[assembly: IgnoresAccessChecksTo("Unity.Services.Core.Scheduler")]
[assembly: IgnoresAccessChecksTo("Unity.Services.Core.Telemetry")]
[assembly: IgnoresAccessChecksTo("Unity.Services.Core.Threading")]
[assembly: IgnoresAccessChecksTo("Unity.Services.Multiplayer")]
[assembly: IgnoresAccessChecksTo("Unity.Services.QoS")]
[assembly: IgnoresAccessChecksTo("Unity.Services.Wire.Internal")]
[assembly: IgnoresAccessChecksTo("Unity.Splines")]
[assembly: IgnoresAccessChecksTo("Unity.TextMeshPro")]
[assembly: IgnoresAccessChecksTo("Unity.Timeline")]
[assembly: IgnoresAccessChecksTo("Unity.UnifiedRayTracing.Runtime")]
[assembly: IgnoresAccessChecksTo("Unity.VisualEffectGraph.Runtime")]
[assembly: IgnoresAccessChecksTo("UnityEngine.AccessibilityModule")]
[assembly: IgnoresAccessChecksTo("UnityEngine.AdaptivePerformanceModule")]
[assembly: IgnoresAccessChecksTo("UnityEngine.AIModule")]
[assembly: IgnoresAccessChecksTo("UnityEngine.AMDModule")]
[assembly: IgnoresAccessChecksTo("UnityEngine.AndroidJNIModule")]
[assembly: IgnoresAccessChecksTo("UnityEngine.AnimationModule")]
[assembly: IgnoresAccessChecksTo("UnityEngine.ARModule")]
[assembly: IgnoresAccessChecksTo("UnityEngine.AssetBundleModule")]
[assembly: IgnoresAccessChecksTo("UnityEngine.AudioModule")]
[assembly: IgnoresAccessChecksTo("UnityEngine.ClothModule")]
[assembly: IgnoresAccessChecksTo("UnityEngine.ClusterInputModule")]
[assembly: IgnoresAccessChecksTo("UnityEngine.ClusterRendererModule")]
[assembly: IgnoresAccessChecksTo("UnityEngine.ContentLoadModule")]
[assembly: IgnoresAccessChecksTo("UnityEngine.CoreModule")]
[assembly: IgnoresAccessChecksTo("UnityEngine.CrashReportingModule")]
[assembly: IgnoresAccessChecksTo("UnityEngine.DirectorModule")]
[assembly: IgnoresAccessChecksTo("UnityEngine")]
[assembly: IgnoresAccessChecksTo("UnityEngine.DSPGraphModule")]
[assembly: IgnoresAccessChecksTo("UnityEngine.GameCenterModule")]
[assembly: IgnoresAccessChecksTo("UnityEngine.GIModule")]
[assembly: IgnoresAccessChecksTo("UnityEngine.GraphicsStateCollectionSerializerModule")]
[assembly: IgnoresAccessChecksTo("UnityEngine.GridModule")]
[assembly: IgnoresAccessChecksTo("UnityEngine.HierarchyCoreModule")]
[assembly: IgnoresAccessChecksTo("UnityEngine.HierarchyModule")]
[assembly: IgnoresAccessChecksTo("UnityEngine.HotReloadModule")]
[assembly: IgnoresAccessChecksTo("UnityEngine.IdentifiersModule")]
[assembly: IgnoresAccessChecksTo("UnityEngine.ImageConversionModule")]
[assembly: IgnoresAccessChecksTo("UnityEngine.IMGUIModule")]
[assembly: IgnoresAccessChecksTo("UnityEngine.InputForUIModule")]
[assembly: IgnoresAccessChecksTo("UnityEngine.InputLegacyModule")]
[assembly: IgnoresAccessChecksTo("UnityEngine.InputModule")]
[assembly: IgnoresAccessChecksTo("UnityEngine.InsightsModule")]
[assembly: IgnoresAccessChecksTo("UnityEngine.JSONSerializeModule")]
[assembly: IgnoresAccessChecksTo("UnityEngine.LocalizationModule")]
[assembly: IgnoresAccessChecksTo("UnityEngine.MarshallingModule")]
[assembly: IgnoresAccessChecksTo("UnityEngine.MultiplayerModule")]
[assembly: IgnoresAccessChecksTo("UnityEngine.NVIDIAModule")]
[assembly: IgnoresAccessChecksTo("UnityEngine.ParticleSystemModule")]
[assembly: IgnoresAccessChecksTo("UnityEngine.PerformanceReportingModule")]
[assembly: IgnoresAccessChecksTo("UnityEngine.Physics2DModule")]
[assembly: IgnoresAccessChecksTo("UnityEngine.PhysicsBackendPhysXModule")]
[assembly: IgnoresAccessChecksTo("UnityEngine.PhysicsModule")]
[assembly: IgnoresAccessChecksTo("UnityEngine.PropertiesModule")]
[assembly: IgnoresAccessChecksTo("UnityEngine.RenderAs2DModule")]
[assembly: IgnoresAccessChecksTo("UnityEngine.RuntimeInitializeOnLoadManagerInitializerModule")]
[assembly: IgnoresAccessChecksTo("UnityEngine.ScreenCaptureModule")]
[assembly: IgnoresAccessChecksTo("UnityEngine.ShaderRuntimeModule")]
[assembly: IgnoresAccessChecksTo("UnityEngine.ShaderVariantAnalyticsModule")]
[assembly: IgnoresAccessChecksTo("UnityEngine.SharedInternalsModule")]
[assembly: IgnoresAccessChecksTo("UnityEngine.SpriteMaskModule")]
[assembly: IgnoresAccessChecksTo("UnityEngine.SpriteShapeModule")]
[assembly: IgnoresAccessChecksTo("UnityEngine.StreamingModule")]
[assembly: IgnoresAccessChecksTo("UnityEngine.SubstanceModule")]
[assembly: IgnoresAccessChecksTo("UnityEngine.SubsystemsModule")]
[assembly: IgnoresAccessChecksTo("UnityEngine.TerrainModule")]
[assembly: IgnoresAccessChecksTo("UnityEngine.TerrainPhysicsModule")]
[assembly: IgnoresAccessChecksTo("UnityEngine.TextCoreFontEngineModule")]
[assembly: IgnoresAccessChecksTo("UnityEngine.TextCoreTextEngineModule")]
[assembly: IgnoresAccessChecksTo("UnityEngine.TextRenderingModule")]
[assembly: IgnoresAccessChecksTo("UnityEngine.TilemapModule")]
[assembly: IgnoresAccessChecksTo("UnityEngine.TLSModule")]
[assembly: IgnoresAccessChecksTo("UnityEngine.UI")]
[assembly: IgnoresAccessChecksTo("UnityEngine.UIElementsModule")]
[assembly: IgnoresAccessChecksTo("UnityEngine.UIModule")]
[assembly: IgnoresAccessChecksTo("UnityEngine.UmbraModule")]
[assembly: IgnoresAccessChecksTo("UnityEngine.UnityAnalyticsCommonModule")]
[assembly: IgnoresAccessChecksTo("UnityEngine.UnityAnalyticsModule")]
[assembly: IgnoresAccessChecksTo("UnityEngine.UnityConnectModule")]
[assembly: IgnoresAccessChecksTo("UnityEngine.UnityConsentModule")]
[assembly: IgnoresAccessChecksTo("UnityEngine.UnityCurlModule")]
[assembly: IgnoresAccessChecksTo("UnityEngine.UnityTestProtocolModule")]
[assembly: IgnoresAccessChecksTo("UnityEngine.UnityWebRequestAssetBundleModule")]
[assembly: IgnoresAccessChecksTo("UnityEngine.UnityWebRequestAudioModule")]
[assembly: IgnoresAccessChecksTo("UnityEngine.UnityWebRequestModule")]
[assembly: IgnoresAccessChecksTo("UnityEngine.UnityWebRequestTextureModule")]
[assembly: IgnoresAccessChecksTo("UnityEngine.UnityWebRequestWWWModule")]
[assembly: IgnoresAccessChecksTo("UnityEngine.VectorGraphicsModule")]
[assembly: IgnoresAccessChecksTo("UnityEngine.VehiclesModule")]
[assembly: IgnoresAccessChecksTo("UnityEngine.VFXModule")]
[assembly: IgnoresAccessChecksTo("UnityEngine.VideoModule")]
[assembly: IgnoresAccessChecksTo("UnityEngine.VirtualTexturingModule")]
[assembly: IgnoresAccessChecksTo("UnityEngine.VRModule")]
[assembly: IgnoresAccessChecksTo("UnityEngine.WindModule")]
[assembly: IgnoresAccessChecksTo("UnityEngine.XRModule")]
[assembly: IgnoresAccessChecksTo("UnityUIExtensions")]
[assembly: IgnoresAccessChecksTo("websocket-sharp")]
[assembly: IgnoresAccessChecksTo("Whinarn.UnityMeshSimplifier.Runtime")]
[assembly: IgnoresAccessChecksTo("Zorro.AutoLOD")]
[assembly: IgnoresAccessChecksTo("Zorro.ControllerSupport")]
[assembly: IgnoresAccessChecksTo("Zorro.Core.Runtime")]
[assembly: IgnoresAccessChecksTo("Zorro.JiggleBones")]
[assembly: IgnoresAccessChecksTo("Zorro.PhotonUtility")]
[assembly: IgnoresAccessChecksTo("Zorro.Settings.Runtime")]
[assembly: IgnoresAccessChecksTo("Zorro.UI.Runtime")]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("0.0.0.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace PeakSpectatorMode
{
	internal sealed class BetterPlayerDistanceIntegration
	{
		private const string BpdGuid = "com.AiAe.betterplayerdistance";

		private const string BpdPluginTypeName = "BetterPlayerDistance.Plugin";

		private const string OverlayFieldName = "Overlay";

		private const string CanvasFieldName = "_canvas";

		private bool _detected;

		private string _detectedVersion;

		private FieldInfo _overlayField;

		private FieldInfo _canvasField;

		private bool _suppressed;

		private bool _savedCanvasEnabled = true;

		internal bool IsLoaded => _detected;

		internal string DetectedVersion => _detectedVersion;

		internal void TryDetect()
		{
			try
			{
				if (!Chainloader.PluginInfos.TryGetValue("com.AiAe.betterplayerdistance", out var value) || value == null || (Object)(object)value.Instance == (Object)null)
				{
					L10n.LogDebug("BetterPlayerDistance not detected; skipping BPD2 compatibility (quiet fallback logging).", "BetterPlayerDistance 未检测到,跳过 BPD2 兼容(无噪音降级日志)。");
					return;
				}
				_detectedVersion = ((value.Metadata != null && value.Metadata.Version != null) ? value.Metadata.Version.ToString() : "(unknown)");
				Type type = AccessTools.TypeByName("BetterPlayerDistance.Plugin");
				if (type == null)
				{
					L10n.LogWarning("BetterPlayerDistance v" + _detectedVersion + " loaded, but type BetterPlayerDistance.Plugin was not found.", "BetterPlayerDistance v" + _detectedVersion + " 已加载,但找不到类型 BetterPlayerDistance.Plugin。");
					return;
				}
				_overlayField = AccessTools.Field(type, "Overlay");
				if (_overlayField == null)
				{
					L10n.LogWarning("BetterPlayerDistance v" + _detectedVersion + " loaded, but field BetterPlayerDistance.Plugin.Overlay was not found.", "BetterPlayerDistance v" + _detectedVersion + " 已加载,但找不到字段 BetterPlayerDistance.Plugin.Overlay。");
					return;
				}
				Type fieldType = _overlayField.FieldType;
				_canvasField = AccessTools.Field(fieldType, "_canvas");
				if (_canvasField == null)
				{
					L10n.LogWarning("BetterPlayerDistance v" + _detectedVersion + " loaded, but field _canvas was not found in OverlayManager.", "BetterPlayerDistance v" + _detectedVersion + " 已加载,但 OverlayManager 中找不到 _canvas 字段。");
					return;
				}
				_detected = true;
				L10n.LogInfo("BetterPlayerDistance v" + _detectedVersion + " detected; BPD2 compatibility enabled (Canvas.enabled switching mode).", "BetterPlayerDistance v" + _detectedVersion + " 已检测到,BPD2 兼容启用(Canvas.enabled 切换模式)。");
			}
			catch (Exception ex)
			{
				_detected = false;
				L10n.LogWarning("BetterPlayerDistance compatibility detection failed: " + ex.GetType().Name + ": " + ex.Message, "BetterPlayerDistance 兼容检测失败:" + ex.GetType().Name + ": " + ex.Message);
			}
		}

		private Canvas ResolveCanvas()
		{
			if (!_detected || _overlayField == null || _canvasField == null)
			{
				return null;
			}
			try
			{
				object value = _overlayField.GetValue(null);
				if (value == null)
				{
					return null;
				}
				object? value2 = _canvasField.GetValue(value);
				return (Canvas)((value2 is Canvas) ? value2 : null);
			}
			catch (Exception ex)
			{
				L10n.LogDebug("[BPD2 Compat] ResolveCanvas exception: " + ex.GetType().Name + ": " + ex.Message, "[BPD2兼容] ResolveCanvas 异常:" + ex.GetType().Name + ": " + ex.Message);
				return null;
			}
		}

		internal void Suppress()
		{
			if (!_detected || _suppressed || !Configuration.EnableBetterPlayerDistanceIntegration)
			{
				return;
			}
			Canvas val = ResolveCanvas();
			if ((Object)(object)val == (Object)null)
			{
				L10n.LogDebug("[BPD2 Compat] Canvas is missing during Suppress (BPD2 may not be initialized yet); skipping.", "[BPD2兼容] Suppress 时 Canvas 不存在(BPD2 可能尚未初始化),跳过。");
				return;
			}
			try
			{
				_savedCanvasEnabled = ((Behaviour)val).enabled;
				if (((Behaviour)val).enabled)
				{
					((Behaviour)val).enabled = false;
				}
				_suppressed = true;
				L10n.LogInfo($"[BPD2 Compat] Temporarily disabled BPD2 Canvas (saved enabled={_savedCanvasEnabled})", $"[BPD2兼容] 已临时关闭 BPD2 Canvas(暂存 enabled={_savedCanvasEnabled})");
			}
			catch (Exception ex)
			{
				L10n.LogWarning("[BPD2 Compat] Suppress failed: " + ex.GetType().Name + ": " + ex.Message, "[BPD2兼容] Suppress 失败:" + ex.GetType().Name + ": " + ex.Message);
			}
		}

		internal void Restore()
		{
			if (!_detected || !_suppressed)
			{
				return;
			}
			Canvas val = ResolveCanvas();
			if ((Object)(object)val == (Object)null)
			{
				_suppressed = false;
				L10n.LogDebug("[BPD2 Compat] Canvas is already missing during Restore (scene reload?); marking as reset.", "[BPD2兼容] Restore 时 Canvas 已不存在(Scene 重载?),标记复位。");
				return;
			}
			try
			{
				((Behaviour)val).enabled = _savedCanvasEnabled;
				_suppressed = false;
				L10n.LogInfo($"[BPD2 Compat] Restored BPD2 Canvas.enabled={_savedCanvasEnabled}", $"[BPD2兼容] 已恢复 BPD2 Canvas.enabled={_savedCanvasEnabled}");
			}
			catch (Exception ex)
			{
				L10n.LogWarning("[BPD2 Compat] Restore failed: " + ex.GetType().Name + ": " + ex.Message, "[BPD2兼容] Restore 失败:" + ex.GetType().Name + ": " + ex.Message);
			}
		}
	}
	internal static class CharacterState
	{
		internal static bool IsAliveSpectatorTarget(Character character)
		{
			if ((Object)(object)character == (Object)null || (Object)(object)((Component)character).gameObject == (Object)null || !((Component)character).gameObject.activeInHierarchy || character.isBot)
			{
				return false;
			}
			if (!Configuration.DebugMode && (Object)(object)character == (Object)(object)Character.localCharacter)
			{
				return false;
			}
			return !IsDead(character);
		}

		internal static bool IsDead(Character character)
		{
			try
			{
				return (Object)(object)character == (Object)null || (Object)(object)character.data == (Object)null || character.data.dead;
			}
			catch
			{
				return true;
			}
		}
	}
	internal enum SpectatorArrowStyle
	{
		RoundedGlass,
		OutlineGlass
	}
	internal static class Configuration
	{
		internal static ConfigEntry<KeyCode> ToggleKey;

		internal static ConfigEntry<KeyCode> ResetKey;

		internal static ConfigEntry<KeyCode> PreviousPlayerKey;

		internal static ConfigEntry<KeyCode> NextPlayerKey;

		internal static ConfigEntry<KeyCode> ToggleOverlayKey;

		internal static ConfigEntry<KeyCode> PeakTrailsToggleKey;

		internal static ConfigEntry<KeyCode> ForcedDeathKey;

		internal static ConfigEntry<float> NormalSpeed;

		internal static ConfigEntry<float> FastSpeed;

		internal static ConfigEntry<float> TurnSpeed;

		internal static ConfigEntry<float> AltSlowSpeedMultiplier;

		internal static ConfigEntry<float> MoveDamping;

		internal static ConfigEntry<float> TurnDamping;

		internal static ConfigEntry<KeyCode> TelescopeKey;

		internal static ConfigEntry<float> TelescopeMultiplier;

		internal static ConfigEntry<bool> EnableSoftFollow;

		internal static ConfigEntry<float> SoftFollowMaxDistance;

		internal static ConfigEntry<float> NameFontSize;

		internal static ConfigEntry<float> HeightFontSize;

		internal static ConfigEntry<float> OverlayOpacity;

		internal static ConfigEntry<float> LabelTextOpacity;

		internal static ConfigEntry<SpectatorArrowStyle> HeadArrowStyle;

		internal static ConfigEntry<bool> ShowFullPeakStatsExInfo;

		internal static ConfigEntry<float> SpectatorTeammateStaminaDistance;

		internal static ConfigEntry<KeyCode> OverlayCycleKey;

		internal static ConfigEntry<LogLanguage> LogLang;

		internal const float MaxPeakHeightMeters = 1920f;

		internal static readonly bool DebugMode = true;

		internal static readonly bool ShowOverlay = true;

		internal static readonly bool ShowXraySilhouette = true;

		internal static readonly bool HideHudInFreeCamera = true;

		internal static readonly bool EnablePeakTrailsCompatibility = true;

		internal static readonly bool EnablePeakStatsExCompatibility = true;

		internal static readonly bool ForcePeakStatsExInventoryInFreeCamera = true;

		internal static readonly bool EnableForcedDeath = true;

		internal static readonly bool ShowXrayDetailLayer = true;

		internal static readonly bool EnableSummitRosterCompatibility = true;

		internal static readonly bool MoveSummitRosterRight = true;

		internal static readonly bool ShowSummitRosterFocusArrow = true;

		internal static readonly bool EnableGhostSpectatorIntegration = true;

		internal static readonly bool EnableBetterPlayerDistanceIntegration = true;

		internal const KeyCode ResetZoomKey = (KeyCode)325;

		internal const float ForcedDeathHoldSeconds = 3f;

		internal const float TelescopeTransitionSpeed = 8f;

		internal const float LabelTextOffsetY = 0f;

		internal const float LabelArrowOffsetY = -38f;

		internal const float LabelScreenPadding = 48f;

		internal const float LabelDistanceScreenPadding = 36f;

		internal const float LabelCameraForwardOffset = 0.4f;

		internal const float FloatAmplitude = 7f;

		internal const float FloatSpeed = 1.15f;

		internal const float OverlayFadeSpeed = 5f;

		internal const float XrayOpacity = 0.34f;

		internal const float XrayDetailOpacity = 0.16f;

		internal const float XrayOcclusionCheckInterval = 0.12f;

		internal static void Initialize(ConfigFile config)
		{
			//IL_0149: Unknown result type (might be due to invalid IL or missing references)
			//IL_0153: Expected O, but got Unknown
			//IL_0181: Unknown result type (might be due to invalid IL or missing references)
			//IL_018b: Expected O, but got Unknown
			//IL_01b9: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c3: Expected O, but got Unknown
			//IL_01f1: Unknown result type (might be due to invalid IL or missing references)
			//IL_01fb: Expected O, but got Unknown
			//IL_0229: Unknown result type (might be due to invalid IL or missing references)
			//IL_0233: Expected O, but got Unknown
			//IL_0261: Unknown result type (might be due to invalid IL or missing references)
			//IL_026b: Expected O, but got Unknown
			//IL_0299: Unknown result type (might be due to invalid IL or missing references)
			//IL_02a3: Expected O, but got Unknown
			//IL_02ec: Unknown result type (might be due to invalid IL or missing references)
			//IL_02f6: Expected O, but got Unknown
			//IL_0324: Unknown result type (might be due to invalid IL or missing references)
			//IL_032e: Expected O, but got Unknown
			//IL_0377: Unknown result type (might be due to invalid IL or missing references)
			//IL_0381: Expected O, but got Unknown
			//IL_03af: Unknown result type (might be due to invalid IL or missing references)
			//IL_03b9: Expected O, but got Unknown
			//IL_03e7: Unknown result type (might be due to invalid IL or missing references)
			//IL_03f1: Expected O, but got Unknown
			//IL_041f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0429: Expected O, but got Unknown
			//IL_044e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0455: Invalid comparison between Unknown and I4
			//IL_0468: Unknown result type (might be due to invalid IL or missing references)
			//IL_046f: Invalid comparison between Unknown and I4
			LogLang = config.Bind<LogLanguage>("0. General 常规", "Log Language 日志语言", LogLanguage.Auto, "Language used for the mod's console/log messages. Auto follows the in-game language.\n模组控制台/日志信息使用的语言。Auto 表示跟随游戏内语言。");
			ToggleKey = config.Bind<KeyCode>("1. Hotkeys 热键", "Spectator Toggle 观战开关", (KeyCode)284, "Toggle the free spectator camera on/off.\n开启或关闭自由观战相机。");
			ResetKey = config.Bind<KeyCode>("1. Hotkeys 热键", "Reset Near Self 重置到自己附近", (KeyCode)285, "Reset the free camera near the local player.\n将自由相机重置到本地玩家附近。");
			PreviousPlayerKey = config.Bind<KeyCode>("1. Hotkeys 热键", "Previous Player 上一个玩家", (KeyCode)113, "Snap the free camera near the previous other player.\n将自由相机快速切换到上一个其他玩家附近。");
			NextPlayerKey = config.Bind<KeyCode>("1. Hotkeys 热键", "Next Player 下一个玩家", (KeyCode)101, "Snap the free camera near the next other player.\n将自由相机快速切换到下一个其他玩家附近。");
			ToggleOverlayKey = config.Bind<KeyCode>("1. Hotkeys 热键", "Temporarily Hide Labels 临时隐藏标记", (KeyCode)102, "Smoothly show/hide player names and altitude in free camera.\n自由相机模式下平滑显示或隐藏玩家名称和海拔。");
			OverlayCycleKey = config.Bind<KeyCode>("1. Hotkeys 热键", "Cycle Label Mode 标记显示模式循环", (KeyCode)99, "3-step cycle in free camera: name + arrow -> name only -> hide all -> back to name + arrow.\n自由相机下 3 段循环:名称+箭头 → 仅名称 → 全部隐藏 → 回到名称+箭头。");
			PeakTrailsToggleKey = config.Bind<KeyCode>("1. Hotkeys 热键", "PEAKTrails Toggle PEAKTrails轨迹开关", (KeyCode)114, "Toggle PEAKTrails player trails while in free camera.\n自由相机模式下切换 PEAKTrails 玩家轨迹显示或隐藏。");
			TelescopeKey = config.Bind<KeyCode>("1. Hotkeys 热键", "Telescope Key 望远镜按键", (KeyCode)120, "Hold to smoothly zoom in the free camera; release to smoothly restore the current scroll zoom.\n按住后平滑放大自由相机视角,松开后平滑恢复到当前滚轮缩放。");
			ForcedDeathKey = config.Bind<KeyCode>("1. Hotkeys 热键", "Forced Death Key (Alt+) 强制死亡主按键(Alt+)", (KeyCode)284, "Hold together with Alt to trigger forced death.\n配合 Alt 长按触发强制死亡。");
			NormalSpeed = config.Bind<float>("2. Camera 相机", "Normal Speed 普通速度", 12f, new ConfigDescription("Free camera normal move speed.\n自由相机普通移动速度。", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 80f), Array.Empty<object>()));
			FastSpeed = config.Bind<float>("2. Camera 相机", "Shift Speed shift速度", 60f, new ConfigDescription("Move speed while holding Shift.\n按住 Shift 时的移动速度。", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 200f), Array.Empty<object>()));
			TurnSpeed = config.Bind<float>("2. Camera 相机", "Turn Speed 转向速度", 50f, new ConfigDescription("Free camera mouse turn speed.\n自由相机鼠标转向速度。", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 80f), Array.Empty<object>()));
			AltSlowSpeedMultiplier = config.Bind<float>("2. Camera 相机", "Alt Slow Multiplier Alt慢速倍率", 0.33f, new ConfigDescription("Move speed multiplier while holding Alt in F3 free camera; 0.33 = 33%.\nF3 自由相机模式下按住 Alt 时的移动速度倍率,0.33 表示 33%。", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.05f, 1f), Array.Empty<object>()));
			MoveDamping = config.Bind<float>("2. Camera 相机", "Move Damping 移动阻尼", 3f, new ConfigDescription("Free camera move damping; higher stops faster.\n自由相机移动阻尼,数值越高停下越快。", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.1f, 20f), Array.Empty<object>()));
			TurnDamping = config.Bind<float>("2. Camera 相机", "Turn Damping 转向阻尼", 5f, new ConfigDescription("Free camera turn damping; higher turns more steadily.\n自由相机转向阻尼,数值越高转向越稳。", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.1f, 20f), Array.Empty<object>()));
			TelescopeMultiplier = config.Bind<float>("2. Camera 相机", "Telescope Multiplier 望远镜倍率", 5f, new ConfigDescription("Zoom multiplier while holding the telescope key.\n按住望远镜按键时的放大倍率。", (AcceptableValueBase)(object)new AcceptableValueRange<float>(2f, 30f), Array.Empty<object>()));
			EnableSoftFollow = config.Bind<bool>("2. Camera 相机", "Soft Follow After Switch 切换后镜头软跟随玩家", true, "After switching to a player, auto soft-follow once the transition ends: the camera moves with the player; exits when you press any move key (WASD/Space/Ctrl/Q/E) or the camera goes beyond the set distance.\n切换玩家后过渡结束自动进入软跟随:相机随玩家一起移动;按任意位移键 (WASD/Space/Ctrl/Q/E) 或相机距目标超过设定距离时退出跟随。");
			SoftFollowMaxDistance = config.Bind<float>("2. Camera 相机", "Soft Follow Max Distance 软跟随最大距离", 20f, new ConfigDescription("Auto-exit soft follow when the camera is farther than this many meters from the target.\n软跟随状态下相机距离目标超过此米数时自动退出。", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 50f), Array.Empty<object>()));
			SpectatorTeammateStaminaDistance = config.Bind<float>("2. Camera 相机", "Free Camera Teammate Stamina Distance 自由相机队友体力条距离", 9999f, new ConfigDescription("Temporarily override the PeakStatsEx teammate stamina bar display distance while in free camera.\n自由相机模式下临时覆盖 PeakStatsEx 队友体力条显示距离。", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 10000f), Array.Empty<object>()));
			ShowFullPeakStatsExInfo = config.Bind<bool>("2. Camera 相机", "Show Full PeakStatsEx Info 自由相机显示完整peakstatsex信息", false, "When enabled, F3 free camera no longer hides PeakStatsEx top stats (timer, height, fog/lava, etc.); when disabled it stays minimal.\n开启后,F3 自由相机模式下不再隐藏 PeakStatsEx 的计时、高度、雾/岩浆等顶部统计信息;关闭时保持精简显示。");
			NameFontSize = config.Bind<float>("3. Display 显示", "Name Font Size 名字字号", 12f, new ConfigDescription("Player name font size.\n玩家名称字号。", (AcceptableValueBase)(object)new AcceptableValueRange<float>(9f, 60f), Array.Empty<object>()));
			HeightFontSize = config.Bind<float>("3. Display 显示", "World Altitude Font Size 世界海拔字号", 13f, new ConfigDescription("World altitude font size.\n世界海拔字号。", (AcceptableValueBase)(object)new AcceptableValueRange<float>(9f, 60f), Array.Empty<object>()));
			OverlayOpacity = config.Bind<float>("3. Display 显示", "Marker Opacity 标记透明度", 0.7f, new ConfigDescription("Opacity of the overhead arrow marker; label text is controlled separately by \"Label Text Opacity\" and the two are not multiplied together.\n头顶箭头标记的不透明度;文字另由“标签文字透明度”独立控制,两者互不相乘。", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1f), Array.Empty<object>()));
			LabelTextOpacity = config.Bind<float>("3. Display 显示", "Label Text Opacity 标签文字透明度", 0.8f, new ConfigDescription("Opacity of the overhead label text (including its shadow); independent from \"Marker Opacity\" (arrow) and applied absolutely.\n头顶标签文字(含文字阴影)的不透明度;与“标记透明度”(箭头)相互独立、绝对生效。", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1f), Array.Empty<object>()));
			HeadArrowStyle = config.Bind<SpectatorArrowStyle>("3. Display 显示", "Head Arrow Style 头顶箭头样式", SpectatorArrowStyle.RoundedGlass, "RoundedGlass = rounded thick glass-filled arrow; OutlineGlass = outlined glass-filled arrow.\nRoundedGlass 为圆角粗箭头玻璃填充;OutlineGlass 为线框箭头玻璃填充。");
			if ((int)PreviousPlayerKey.Value == 91)
			{
				PreviousPlayerKey.Value = (KeyCode)113;
			}
			if ((int)NextPlayerKey.Value == 93)
			{
				NextPlayerKey.Value = (KeyCode)101;
			}
			if (Mathf.Approximately(TelescopeMultiplier.Value, 10f))
			{
				TelescopeMultiplier.Value = 5f;
			}
		}
	}
	internal sealed class ForceDeathController
	{
		private readonly MethodInfo _dieMethod = AccessTools.Method(typeof(Character), "Die", (Type[])null, (Type[])null);

		private GameObject _root;

		private CanvasGroup _group;

		private TextMeshProUGUI _text;

		private float _holdTime;

		private bool _triggered;

		internal void Update()
		{
			//IL_00bf: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e6: Unknown result type (might be due to invalid IL or missing references)
			if (!Configuration.EnableForcedDeath)
			{
				ResetState();
				return;
			}
			if (Plugin.GsIntegration != null && Plugin.GsIntegration.IsActive)
			{
				ResetState();
				return;
			}
			bool num = IsHoldingCombo();
			Character localCharacter = Character.localCharacter;
			if (!num || (Object)(object)localCharacter == (Object)null || CharacterState.IsDead(localCharacter))
			{
				ResetState();
				return;
			}
			EnsureUi();
			_holdTime += Time.unscaledDeltaTime;
			float num2 = Mathf.Max(1f, 3f);
			float num3 = Mathf.Clamp01(_holdTime / num2);
			_group.alpha = Mathf.MoveTowards(_group.alpha, 1f, Time.unscaledDeltaTime * 8f);
			((TMP_Text)_text).text = L10n.Game($"Warning: keep holding Alt+{Configuration.ForcedDeathKey.Value} to force death\n{num3 * num2:0.0}/{num2:0.0}s", $"警告:继续按住 Alt+{Configuration.ForcedDeathKey.Value} 将强制死亡\n{num3 * num2:0.0}/{num2:0.0}s");
			if (!_triggered && _holdTime >= num2)
			{
				_triggered = true;
				ForceDie();
				ResetState();
			}
		}

		internal void Dispose()
		{
			if ((Object)(object)_root != (Object)null)
			{
				Object.Destroy((Object)(object)_root);
			}
		}

		private bool IsHoldingCombo()
		{
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			if (Input.GetKey((KeyCode)308) || Input.GetKey((KeyCode)307))
			{
				return Input.GetKey(Configuration.ForcedDeathKey.Value);
			}
			return false;
		}

		private void ForceDie()
		{
			try
			{
				if (_dieMethod != null)
				{
					_dieMethod.Invoke(null, null);
				}
			}
			catch (Exception ex)
			{
				L10n.LogWarning("Alt+F3 forced death failed: " + ex.Message, "Alt+F3 强制死亡失败:" + ex.Message);
			}
		}

		private void ResetState()
		{
			_holdTime = 0f;
			_triggered = false;
			if ((Object)(object)_group != (Object)null)
			{
				_group.alpha = Mathf.MoveTowards(_group.alpha, 0f, Time.unscaledDeltaTime * 8f);
			}
		}

		private void EnsureUi()
		{
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: Expected O, but got Unknown
			//IL_006e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bc: Expected O, but got Unknown
			//IL_00eb: Unknown result type (might be due to invalid IL or missing references)
			//IL_0100: Unknown result type (might be due to invalid IL or missing references)
			//IL_0115: Unknown result type (might be due to invalid IL or missing references)
			//IL_0129: Unknown result type (might be due to invalid IL or missing references)
			//IL_014e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0163: Unknown result type (might be due to invalid IL or missing references)
			//IL_0169: Expected O, but got Unknown
			//IL_0189: Unknown result type (might be due to invalid IL or missing references)
			//IL_0194: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_01bd: Unknown result type (might be due to invalid IL or missing references)
			//IL_020d: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)_root != (Object)null))
			{
				_root = new GameObject("PeakSpectatorForceDeathWarning");
				Object.DontDestroyOnLoad((Object)(object)_root);
				_root.layer = 5;
				Canvas obj = _root.AddComponent<Canvas>();
				obj.renderMode = (RenderMode)0;
				obj.sortingOrder = 1200;
				CanvasScaler obj2 = _root.AddComponent<CanvasScaler>();
				obj2.uiScaleMode = (ScaleMode)1;
				obj2.referenceResolution = new Vector2(1920f, 1080f);
				_group = _root.AddComponent<CanvasGroup>();
				_group.alpha = 0f;
				_group.blocksRaycasts = false;
				_group.interactable = false;
				GameObject val = new GameObject("Panel");
				val.layer = 5;
				val.transform.SetParent(_root.transform, false);
				RectTransform obj3 = val.AddComponent<RectTransform>();
				obj3.anchorMin = new Vector2(0.5f, 0.82f);
				obj3.anchorMax = new Vector2(0.5f, 0.82f);
				obj3.pivot = new Vector2(0.5f, 0.5f);
				obj3.sizeDelta = new Vector2(720f, 120f);
				Image obj4 = val.AddComponent<Image>();
				((Graphic)obj4).color = new Color(0.12f, 0.02f, 0.02f, 0.78f);
				((Graphic)obj4).raycastTarget = false;
				GameObject val2 = new GameObject("Text");
				val2.layer = 5;
				val2.transform.SetParent(val.transform, false);
				RectTransform obj5 = val2.AddComponent<RectTransform>();
				obj5.anchorMin = Vector2.zero;
				obj5.anchorMax = Vector2.one;
				obj5.offsetMin = new Vector2(20f, 10f);
				obj5.offsetMax = new Vector2(-20f, -10f);
				_text = val2.AddComponent<TextMeshProUGUI>();
				((TMP_Text)_text).alignment = (TextAlignmentOptions)514;
				((TMP_Text)_text).fontSize = 28f;
				((Graphic)_text).color = new Color(1f, 0.78f, 0.58f, 1f);
				((Graphic)_text).raycastTarget = false;
				((TMP_Text)_text).textWrappingMode = (TextWrappingModes)0;
			}
		}
	}
	internal sealed class GhostSpectatorIntegration
	{
		private const string GhostSpectatorGuid = "SisyphusMD.GhostSpectator";

		private bool _detected;

		private ConfigEntry<bool> _spectatorEnabledEntry;

		private string _detectedVersion;

		internal bool IsLoaded => _detected;

		internal string DetectedVersion => _detectedVersion;

		internal bool IsActive
		{
			get
			{
				//IL_0058: Unknown result type (might be due to invalid IL or missing references)
				//IL_005d: Unknown result type (might be due to invalid IL or missing references)
				if (!_detected || _spectatorEnabledEntry == null)
				{
					return false;
				}
				if (!Configuration.EnableGhostSpectatorIntegration)
				{
					return false;
				}
				if (!_spectatorEnabledEntry.Value)
				{
					return false;
				}
				Character localCharacter = Character.localCharacter;
				if ((Object)(object)localCharacter == (Object)null || (Object)(object)localCharacter.data == (Object)null)
				{
					return false;
				}
				if (!localCharacter.data.fullyPassedOut)
				{
					return false;
				}
				Scene activeScene = SceneManager.GetActiveScene();
				if (((Scene)(ref activeScene)).name == "Airport")
				{
					return false;
				}
				return true;
			}
		}

		internal bool IsCharacterPermaSpectator(Character character)
		{
			if (!_detected || (Object)(object)character == (Object)null)
			{
				return false;
			}
			try
			{
				if ((Object)(object)character == (Object)(object)Character.localCharacter)
				{
					return IsActive;
				}
				CharacterRefs refs = character.refs;
				if (refs == null)
				{
					return false;
				}
				PhotonView view = refs.view;
				if ((Object)(object)view == (Object)null)
				{
					return false;
				}
				Player owner = view.Owner;
				if (owner == null)
				{
					return false;
				}
				IDictionary customProperties = (IDictionary)owner.CustomProperties;
				if (customProperties == null)
				{
					return false;
				}
				if (customProperties["GhostSpectator.IsSpectator"] is bool result)
				{
					return result;
				}
			}
			catch (Exception ex)
			{
				L10n.LogDebug("IsCharacterPermaSpectator exception: " + ex.GetType().Name + ": " + ex.Message, "IsCharacterPermaSpectator 异常:" + ex.GetType().Name + ": " + ex.Message);
			}
			return false;
		}

		internal void TryDetect()
		{
			//IL_00bd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c3: Expected O, but got Unknown
			try
			{
				if (!Chainloader.PluginInfos.TryGetValue("SisyphusMD.GhostSpectator", out var value) || value == null || (Object)(object)value.Instance == (Object)null)
				{
					L10n.LogDebug("GhostSpectator not detected; running in standalone mode (quiet fallback logging).", "GhostSpectator 未检测到,运行在独立模式(无噪音降级日志)。");
					return;
				}
				_detectedVersion = ((value.Metadata != null && value.Metadata.Version != null) ? value.Metadata.Version.ToString() : "(unknown)");
				ConfigFile config = value.Instance.Config;
				if (config == null)
				{
					L10n.LogWarning("GhostSpectator v" + _detectedVersion + " loaded, but its Config is inaccessible; compatibility mode cannot be enabled.", "GhostSpectator v" + _detectedVersion + " 已加载,但其 Config 不可访问,兼容模式无法启用。");
					return;
				}
				ConfigDefinition val = new ConfigDefinition("Spectator", "Enabled");
				ConfigEntry<bool> val2 = default(ConfigEntry<bool>);
				if (!config.TryGetEntry<bool>(val, ref val2) || val2 == null)
				{
					L10n.LogWarning("GhostSpectator v" + _detectedVersion + " loaded, but the Spectator/Enabled config entry was not found. The version may be incompatible.", "GhostSpectator v" + _detectedVersion + " 已加载,但未找到 Spectator/Enabled 配置项。可能是版本不兼容。");
					return;
				}
				_spectatorEnabledEntry = val2;
				_detected = true;
				L10n.LogInfo($"GhostSpectator v{_detectedVersion} detected; compatibility mode enabled. Current SpectatorEnabled value={_spectatorEnabledEntry.Value}.", $"GhostSpectator v{_detectedVersion} 已检测到,兼容模式启用。SpectatorEnabled 当前值={_spectatorEnabledEntry.Value}。");
			}
			catch (Exception ex)
			{
				_detected = false;
				_spectatorEnabledEntry = null;
				L10n.LogWarning("GhostSpectator compatibility detection failed: " + ex.GetType().Name + ": " + ex.Message + ". Running in standalone mode.", "GhostSpectator 兼容检测失败:" + ex.GetType().Name + ": " + ex.Message + "。运行在独立模式。");
			}
		}
	}
	internal enum LogLanguage
	{
		Auto,
		English,
		Chinese
	}
	internal static class L10n
	{
		internal static bool GameIsChinese
		{
			get
			{
				//IL_0000: Unknown result type (might be due to invalid IL or missing references)
				//IL_0005: 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: Invalid comparison between Unknown and I4
				//IL_000b: Unknown result type (might be due to invalid IL or missing references)
				//IL_000e: Invalid comparison between Unknown and I4
				Language cURRENT_LANGUAGE = LocalizedText.CURRENT_LANGUAGE;
				if ((int)cURRENT_LANGUAGE != 9)
				{
					return (int)cURRENT_LANGUAGE == 10;
				}
				return true;
			}
		}

		internal static bool UseChineseForLogs => ((Configuration.LogLang != null) ? Configuration.LogLang.Value : LogLanguage.Auto) switch
		{
			LogLanguage.English => false, 
			LogLanguage.Chinese => true, 
			_ => GameIsChinese, 
		};

		internal static string Game(string en, string zh)
		{
			if (!GameIsChinese)
			{
				return en;
			}
			return zh;
		}

		internal static void LogInfo(string en, string zh)
		{
			ManualLogSource log = Plugin.Log;
			if (log != null)
			{
				log.LogInfo((object)(UseChineseForLogs ? zh : en));
			}
		}

		internal static void LogWarning(string en, string zh)
		{
			ManualLogSource log = Plugin.Log;
			if (log != null)
			{
				log.LogWarning((object)(UseChineseForLogs ? zh : en));
			}
		}

		internal static void LogError(string en, string zh)
		{
			ManualLogSource log = Plugin.Log;
			if (log != null)
			{
				log.LogError((object)(UseChineseForLogs ? zh : en));
			}
		}

		internal static void LogDebug(string en, string zh)
		{
			ManualLogSource log = Plugin.Log;
			if (log != null)
			{
				log.LogDebug((object)(UseChineseForLogs ? zh : en));
			}
		}
	}
	internal sealed class PeakStatsExCompatibility
	{
		private struct InventoryOverrideState
		{
			internal RuntimeOverrideToken<bool> SlotsToken;

			internal PeakStatsExInfoOverrideState InfoState;
		}

		private struct PeakStatsExInfoOverrideState
		{
			internal RuntimeOverrideToken<bool> DisplayTimerToken;

			internal RuntimeOverrideToken<bool> DisplayHeightToken;

			internal RuntimeOverrideToken<bool> DisplayLevelToken;

			internal RuntimeOverrideToken<bool> DisplayBiomesToken;

			internal RuntimeOverrideToken<bool> DisplayDayNightCountdownToken;

			internal RuntimeOverrideToken<bool> DisplayFogToken;

			internal RuntimeOverrideToken<bool> DisplayLavaToken;

			internal RuntimeOverrideToken<bool> DisplayTerrainRandomiserSeedToken;

			internal RuntimeOverrideToken<bool> DisplayTerrainCustomiserSeedToken;

			internal RuntimeOverrideToken<bool> ShowStaminaInfoToken;

			internal RuntimeOverrideToken<bool> StaminaInfoShowAfflictionCountdownToken;
		}

		private sealed class ConfigValue<T>
		{
			private readonly object _entry;

			private readonly PropertyInfo _valueProperty;

			private readonly FieldInfo _typedValueField;

			internal bool IsValid
			{
				get
				{
					if (_entry != null)
					{
						return _valueProperty != null;
					}
					return false;
				}
			}

			internal object EntryObject => _entry;

			internal ConfigValue(object entry)
			{
				_entry = entry;
				if (_entry != null)
				{
					_valueProperty = _entry.GetType().GetProperty("Value");
					_typedValueField = AccessTools.Field(_entry.GetType(), "_typedValue");
				}
			}

			internal T Get(T fallback)
			{
				if (_entry == null)
				{
					return fallback;
				}
				object obj = ((_typedValueField != null) ? _typedValueField.GetValue(_entry) : _valueProperty?.GetValue(_entry, null));
				if (obj is T)
				{
					return (T)obj;
				}
				return fallback;
			}

			internal void Set(T value)
			{
				if (_entry != null)
				{
					if (_typedValueField != null)
					{
						_typedValueField.SetValue(_entry, value);
					}
					else if (_entry is ConfigEntry<T> val)
					{
						val.Value = value;
					}
					else
					{
						_valueProperty?.SetValue(_entry, value, null);
					}
				}
			}
		}

		private readonly Harmony _harmony;

		private readonly RuntimeOverrideManager _overrides = new RuntimeOverrideManager();

		private ConfigValue<float> _proximityDistance;

		private ConfigValue<bool> _displayTimer;

		private ConfigValue<bool> _displayHeight;

		private ConfigValue<bool> _displayLevel;

		private ConfigValue<bool> _displayBiomes;

		private ConfigValue<bool> _displayDayNightCountdown;

		private ConfigValue<bool> _displayFog;

		private ConfigValue<bool> _displayLava;

		private ConfigValue<bool> _displayTerrainRandomiserSeed;

		private ConfigValue<bool> _displayTerrainCustomiserSeed;

		private ConfigValue<bool> _showInventorySlots;

		private ConfigValue<bool> _showStaminaInfo;

		private ConfigValue<bool> _staminaInfoShowAfflictionCountdown;

		private FieldInfo _staminaBarsField;

		private PropertyInfo _observedCharacterProperty;

		private FieldInfo _isEnabledField;

		private FieldInfo _animateDisableCoroutineField;

		private object _lastProximityManager;

		private bool _initialized;

		private bool _initAttempted;

		private bool _loggedMissing;

		private bool _fullInfoOverrideActive;

		private PeakStatsExInfoOverrideState _fullInfoState;

		private bool _wasSpectatorActive;

		private float _clearInventoryUntil;

		internal PeakStatsExCompatibility(Harmony harmony)
		{
			_harmony = harmony;
		}

		internal void Update(bool spectatorActive)
		{
			if (!Configuration.EnablePeakStatsExCompatibility)
			{
				Restore();
				_wasSpectatorActive = spectatorActive;
				return;
			}
			EnsureInitialized();
			if (!spectatorActive)
			{
				if (_wasSpectatorActive)
				{
					_clearInventoryUntil = Time.time + 1.5f;
				}
				Restore();
				ClearResidualInventoryIfNeeded();
				_wasSpectatorActive = false;
			}
			else
			{
				_wasSpectatorActive = true;
				UpdateFullPeakStatsExInfoOverride();
			}
		}

		internal void Restore()
		{
			_overrides.ReleaseAll();
			_fullInfoOverrideActive = false;
			_fullInfoState = default(PeakStatsExInfoOverrideState);
		}

		private void EnsureInitialized()
		{
			if (_initialized || _initAttempted)
			{
				return;
			}
			Type type = AccessTools.TypeByName("PeakStatsEx.PluginConfig");
			if (type == null)
			{
				_initAttempted = true;
				LogMissingOnce();
				return;
			}
			_proximityDistance = CreateConfigValue<float>(type, "TeammateStaminaBarProximity");
			if (_proximityDistance == null)
			{
				_initAttempted = true;
				LogMissingOnce();
				return;
			}
			_displayTimer = CreateConfigValue<bool>(type, "DisplayTimer");
			_displayHeight = CreateConfigValue<bool>(type, "DisplayHeight");
			_displayLevel = CreateConfigValue<bool>(type, "DisplayLevel");
			_displayBiomes = CreateConfigValue<bool>(type, "DisplayBiomes");
			_displayDayNightCountdown = CreateConfigValue<bool>(type, "DisplayDayNightCountdown");
			_displayFog = CreateConfigValue<bool>(type, "DisplayFog");
			_displayLava = CreateConfigValue<bool>(type, "DisplayLava");
			_displayTerrainRandomiserSeed = CreateConfigValue<bool>(type, "DisplayTerrainRandomiserSeed");
			_displayTerrainCustomiserSeed = CreateConfigValue<bool>(type, "DisplayTerrainCustomiserSeed");
			_showInventorySlots = CreateConfigValue<bool>(type, "ShowInventorySlots");
			_showStaminaInfo = CreateConfigValue<bool>(type, "ShowStaminaInfo");
			_staminaInfoShowAfflictionCountdown = CreateConfigValue<bool>(type, "StaminaInfoShowAfflictionCountdown");
			Type type2 = AccessTools.TypeByName("PeakStatsEx.MonoBehaviours.ProximityStaminaManager");
			_staminaBarsField = ((type2 != null) ? AccessTools.Field(type2, "staminaBars") : null);
			Type type3 = AccessTools.TypeByName("PeakStatsEx.MonoBehaviours.CharacterStaminaBar");
			_observedCharacterProperty = ((type3 != null) ? AccessTools.Property(type3, "ObservedCharacter") : null);
			_isEnabledField = ((type3 != null) ? AccessTools.Field(type3, "isEnabled") : null);
			_animateDisableCoroutineField = ((type3 != null) ? AccessTools.Field(type3, "animateDisableCoroutine") : null);
			TryPatchPeakStatsEx();
			_initialized = true;
			L10n.LogInfo("PeakStatsEx free-camera stamina bar distance compatibility enabled.", "已启用 PeakStatsEx 自由相机体力条距离兼容。");
		}

		private void TryPatchPeakStatsEx()
		{
			PatchMethod("PeakStatsEx.MonoBehaviours.ProximityStaminaManager", "Update", "ProximityManagerUpdatePrefix", "ProximityManagerUpdatePostfix");
			PatchMethod("PeakStatsEx.MonoBehaviours.TimerHeightStats", "Update", "TimerHeightStatsUpdatePrefix", "TimerHeightStatsUpdatePostfix");
			PatchMethod("PeakStatsEx.MonoBehaviours.MapStats", "Update", "MapStatsUpdatePrefix", "MapStatsUpdatePostfix");
			PatchMethod("PeakStatsEx.MonoBehaviours.CharacterStaminaBar", "Update", "CharacterStaminaBarUpdatePrefix", "CharacterStaminaBarUpdatePostfix");
			PatchMethod("StaminaBar", "Update", "StaminaBarUpdatePrefix", "StaminaBarUpdatePostfix");
		}

		private void PatchMethod(string typeName, string methodName, string prefixName, string postfixName)
		{
			//IL_0067: 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_007a: Expected O, but got Unknown
			//IL_007a: Expected O, but got Unknown
			Type type = AccessTools.TypeByName(typeName);
			MethodInfo methodInfo = ((type != null) ? AccessTools.Method(type, methodName, (Type[])null, (Type[])null) : null);
			MethodInfo methodInfo2 = AccessTools.Method(typeof(PeakStatsExCompatibility), prefixName, (Type[])null, (Type[])null);
			MethodInfo methodInfo3 = AccessTools.Method(typeof(PeakStatsExCompatibility), postfixName, (Type[])null, (Type[])null);
			if (methodInfo != null && methodInfo2 != null && methodInfo3 != null)
			{
				_harmony.Patch((MethodBase)methodInfo, new HarmonyMethod(methodInfo2), new HarmonyMethod(methodInfo3), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			}
		}

		private bool ShouldOverrideDistance()
		{
			if (Configuration.EnablePeakStatsExCompatibility && Plugin.CameraController != null && Plugin.CameraController.IsActive)
			{
				return _proximityDistance != null;
			}
			return false;
		}

		private bool ShouldHidePeakStatsExExtras()
		{
			if (Configuration.EnablePeakStatsExCompatibility && !Configuration.ShowFullPeakStatsExInfo.Value)
			{
				return SpectatorHudManager.ShouldHideHud();
			}
			return false;
		}

		private bool ShouldShowFullPeakStatsExInfo()
		{
			if (Configuration.EnablePeakStatsExCompatibility && Configuration.ShowFullPeakStatsExInfo.Value && Plugin.CameraController != null)
			{
				return Plugin.CameraController.IsActive;
			}
			return false;
		}

		private bool ShouldForceInventoryInFreeCamera()
		{
			if (Configuration.EnablePeakStatsExCompatibility && Configuration.ForcePeakStatsExInventoryInFreeCamera && Plugin.CameraController != null)
			{
				return Plugin.CameraController.IsActive;
			}
			return false;
		}

		private void UpdateFullPeakStatsExInfoOverride()
		{
			if (ShouldShowFullPeakStatsExInfo())
			{
				if (!_fullInfoOverrideActive)
				{
					_fullInfoState = BeginFullPeakStatsExInfoOverride();
					_fullInfoOverrideActive = true;
				}
			}
			else if (_fullInfoOverrideActive)
			{
				EndPeakStatsExInfoOverride(_fullInfoState);
				_fullInfoState = default(PeakStatsExInfoOverrideState);
				_fullInfoOverrideActive = false;
			}
		}

		private RuntimeOverrideToken<float> BeginTemporaryDistanceOverride()
		{
			if (_proximityDistance == null)
			{
				return RuntimeOverrideToken<float>.Inactive;
			}
			return _overrides.Apply(GetOverrideKey(_proximityDistance), () => _proximityDistance.Get(30f), delegate(float value)
			{
				_proximityDistance.Set(value);
			}, Configuration.SpectatorTeammateStaminaDistance.Value);
		}

		private void EndTemporaryDistanceOverride(RuntimeOverrideToken<float> token)
		{
			token.Release();
		}

		private RuntimeOverrideToken<bool> BeginBoolOverride(ConfigValue<bool> entry, bool value)
		{
			if (entry == null)
			{
				return RuntimeOverrideToken<bool>.Inactive;
			}
			return _overrides.Apply(GetOverrideKey(entry), () => entry.Get(fallback: true), delegate(bool current)
			{
				entry.Set(current);
			}, value);
		}

		private void EndBoolOverride(RuntimeOverrideToken<bool> token)
		{
			token.Release();
		}

		private InventoryOverrideState BeginInventoryOverride()
		{
			InventoryOverrideState result = default(InventoryOverrideState);
			if (_showInventorySlots != null)
			{
				result.SlotsToken = _overrides.Apply(GetOverrideKey(_showInventorySlots), () => _showInventorySlots.Get(fallback: false), delegate(bool value)
				{
					_showInventorySlots.Set(value);
				}, value: true);
			}
			return result;
		}

		private void EndInventoryOverride(InventoryOverrideState state)
		{
			state.SlotsToken.Release();
			EndPeakStatsExInfoOverride(state.InfoState);
		}

		private PeakStatsExInfoOverrideState BeginCompactPeakStatsExInfoOverride()
		{
			return new PeakStatsExInfoOverrideState
			{
				DisplayHeightToken = BeginBoolOverride(_displayHeight, value: false)
			};
		}

		private PeakStatsExInfoOverrideState BeginFullPeakStatsExInfoOverride()
		{
			return new PeakStatsExInfoOverrideState
			{
				DisplayTimerToken = BeginBoolOverride(_displayTimer, value: true),
				DisplayHeightToken = BeginBoolOverride(_displayHeight, value: true),
				DisplayLevelToken = BeginBoolOverride(_displayLevel, value: true),
				DisplayBiomesToken = BeginBoolOverride(_displayBiomes, value: true),
				DisplayDayNightCountdownToken = BeginBoolOverride(_displayDayNightCountdown, value: true),
				DisplayFogToken = BeginBoolOverride(_displayFog, value: true),
				DisplayLavaToken = BeginBoolOverride(_displayLava, value: true),
				DisplayTerrainRandomiserSeedToken = BeginBoolOverride(_displayTerrainRandomiserSeed, value: true),
				DisplayTerrainCustomiserSeedToken = BeginBoolOverride(_displayTerrainCustomiserSeed, value: true),
				ShowStaminaInfoToken = BeginBoolOverride(_showStaminaInfo, value: true),
				StaminaInfoShowAfflictionCountdownToken = BeginBoolOverride(_staminaInfoShowAfflictionCountdown, value: true)
			};
		}

		private void EndPeakStatsExInfoOverride(PeakStatsExInfoOverrideState state)
		{
			state.DisplayTimerToken.Release();
			state.DisplayHeightToken.Release();
			state.DisplayLevelToken.Release();
			state.DisplayBiomesToken.Release();
			state.DisplayDayNightCountdownToken.Release();
			state.DisplayFogToken.Release();
			state.DisplayLavaToken.Release();
			state.DisplayTerrainRandomiserSeedToken.Release();
			state.DisplayTerrainCustomiserSeedToken.Release();
			state.ShowStaminaInfoToken.Release();
			state.StaminaInfoShowAfflictionCountdownToken.Release();
		}

		private static object GetOverrideKey<T>(ConfigValue<T> entry)
		{
			return entry?.EntryObject;
		}

		private bool TryDisableDeadStaminaBar(object characterStaminaBar)
		{
			Character observedCharacter = GetObservedCharacter(characterStaminaBar);
			if ((Object)(object)observedCharacter == (Object)null || !CharacterState.IsDead(observedCharacter))
			{
				return false;
			}
			ForceDisableStaminaBar(characterStaminaBar);
			return true;
		}

		private void HideDeadStaminaBars(object proximityManager)
		{
			TrackProximityManager(proximityManager);
			if (!Configuration.EnablePeakStatsExCompatibility || proximityManager == null || _staminaBarsField == null || !(_staminaBarsField.GetValue(proximityManager) is IDictionary dictionary))
			{
				return;
			}
			foreach (DictionaryEntry item in dictionary)
			{
				object key = item.Key;
				Character val = (Character)((key is Character) ? key : null);
				if ((Object)(object)val != (Object)null && CharacterState.IsDead(val))
				{
					ForceDisableStaminaBar(item.Value);
				}
			}
		}

		private Character GetObservedCharacter(object characterStaminaBar)
		{
			if (characterStaminaBar == null || _observedCharacterProperty == null)
			{
				return null;
			}
			object? value = _observedCharacterProperty.GetValue(characterStaminaBar, null);
			return (Character)((value is Character) ? value : null);
		}

		private void ForceDisableStaminaBar(object characterStaminaBar)
		{
			if (characterStaminaBar != null)
			{
				object obj = ((characterStaminaBar is MonoBehaviour) ? characterStaminaBar : null);
				if (obj != null)
				{
					((MonoBehaviour)obj).StopAllCoroutines();
				}
				_isEnabledField?.SetValue(characterStaminaBar, false);
				_animateDisableCoroutineField?.SetValue(characterStaminaBar, null);
				Component val = (Component)((characterStaminaBar is Component) ? characterStaminaBar : null);
				if ((Object)(object)val != (Object)null && (Object)(object)val.gameObject != (Object)null && val.gameObject.activeSelf)
				{
					val.gameObject.SetActive(false);
				}
			}
		}

		private void ClearInventorySlots(object characterStaminaBar)
		{
			if (characterStaminaBar != null)
			{
				ClearSlotList(characterStaminaBar, "inventorySlotUIs");
				ClearSlotList(characterStaminaBar, "backpackSlotUIs");
				ClearInventorySlot(AccessTools.Field(characterStaminaBar.GetType(), "heldItemSlot")?.GetValue(characterStaminaBar));
			}
		}

		private void TrackProximityManager(object proximityManager)
		{
			if (proximityManager != null)
			{
				_lastProximityManager = proximityManager;
			}
		}

		private void ClearResidualInventoryIfNeeded()
		{
			if (!(Time.time > _clearInventoryUntil) && (_showInventorySlots == null || !_showInventorySlots.Get(fallback: false)))
			{
				ClearInventorySlotsFromManager(_lastProximityManager);
			}
		}

		private void ClearInventorySlotsFromManager(object proximityManager)
		{
			if (proximityManager == null || _staminaBarsField == null || !(_staminaBarsField.GetValue(proximityManager) is IDictionary dictionary))
			{
				return;
			}
			foreach (DictionaryEntry item in dictionary)
			{
				ClearInventorySlots(item.Value);
			}
		}

		private static void ClearSlotList(object owner, string fieldName)
		{
			if (!(AccessTools.Field(owner.GetType(), fieldName)?.GetValue(owner) is IEnumerable enumerable))
			{
				return;
			}
			foreach (object item in enumerable)
			{
				ClearInventorySlot(item);
			}
		}

		private static void ClearInventorySlot(object slot)
		{
			if (slot == null)
			{
				return;
			}
			MethodInfo methodInfo = AccessTools.Method(slot.GetType(), "Clear", (Type[])null, (Type[])null);
			if (methodInfo == null)
			{
				return;
			}
			try
			{
				methodInfo.Invoke(slot, null);
			}
			catch (TargetInvocationException ex) when (ex.InnerException is NullReferenceException || ex.InnerException is MissingReferenceException)
			{
			}
			catch (NullReferenceException)
			{
			}
			catch (MissingReferenceException)
			{
			}
		}

		private static ConfigValue<T> CreateConfigValue<T>(Type configType, string propertyName)
		{
			object obj = AccessTools.Property(configType, propertyName)?.GetValue(null, null);
			if (obj == null)
			{
				return null;
			}
			ConfigValue<T> configValue = new ConfigValue<T>(obj);
			if (!configValue.IsValid)
			{
				return null;
			}
			return configValue;
		}

		private void LogMissingOnce()
		{
			if (!_loggedMissing)
			{
				_loggedMissing = true;
				L10n.LogInfo("No compatible PeakStatsEx version detected (1.2.0 / 1.2.1); skipped stamina bar distance compatibility.", "未检测到可兼容的 PeakStatsEx(1.2.0 / 1.2.1),已跳过体力条距离兼容。");
			}
		}

		private static void ProximityManagerUpdatePrefix(out RuntimeOverrideToken<float> __state)
		{
			__state = RuntimeOverrideToken<float>.Inactive;
			if (Plugin.PeakStatsEx != null && Plugin.PeakStatsEx.ShouldOverrideDistance())
			{
				__state = Plugin.PeakStatsEx.BeginTemporaryDistanceOverride();
			}
		}

		private static void ProximityManagerUpdatePostfix(object __instance, RuntimeOverrideToken<float> __state)
		{
			if (Plugin.PeakStatsEx != null)
			{
				Plugin.PeakStatsEx.EndTemporaryDistanceOverride(__state);
				Plugin.PeakStatsEx.HideDeadStaminaBars(__instance);
			}
		}

		private static void TimerHeightStatsUpdatePrefix(out PeakStatsExInfoOverrideState __state)
		{
			__state = default(PeakStatsExInfoOverrideState);
			if (Plugin.PeakStatsEx != null)
			{
				if (Plugin.PeakStatsEx.ShouldShowFullPeakStatsExInfo())
				{
					__state = Plugin.PeakStatsEx.BeginFullPeakStatsExInfoOverride();
				}
				else if (Plugin.PeakStatsEx.ShouldHidePeakStatsExExtras())
				{
					__state = Plugin.PeakStatsEx.BeginCompactPeakStatsExInfoOverride();
				}
			}
		}

		private static void TimerHeightStatsUpdatePostfix(PeakStatsExInfoOverrideState __state)
		{
			if (Plugin.PeakStatsEx != null)
			{
				Plugin.PeakStatsEx.EndPeakStatsExInfoOverride(__state);
			}
		}

		private static void MapStatsUpdatePrefix(out PeakStatsExInfoOverrideState __state)
		{
			__state = default(PeakStatsExInfoOverrideState);
			if (Plugin.PeakStatsEx != null && Plugin.PeakStatsEx.ShouldShowFullPeakStatsExInfo())
			{
				__state = Plugin.PeakStatsEx.BeginFullPeakStatsExInfoOverride();
			}
		}

		private static void MapStatsUpdatePostfix(PeakStatsExInfoOverrideState __state)
		{
			if (Plugin.PeakStatsEx != null)
			{
				Plugin.PeakStatsEx.EndPeakStatsExInfoOverride(__state);
			}
		}

		private static void StaminaBarUpdatePrefix(out PeakStatsExInfoOverrideState __state)
		{
			__state = default(PeakStatsExInfoOverrideState);
			if (Plugin.PeakStatsEx != null && Plugin.PeakStatsEx.ShouldShowFullPeakStatsExInfo())
			{
				__state = Plugin.PeakStatsEx.BeginFullPeakStatsExInfoOverride();
			}
		}

		private static void StaminaBarUpdatePostfix(PeakStatsExInfoOverrideState __state)
		{
			if (Plugin.PeakStatsEx != null)
			{
				Plugin.PeakStatsEx.EndPeakStatsExInfoOverride(__state);
			}
		}

		private static bool CharacterStaminaBarUpdatePrefix(object __instance, out InventoryOverrideState __state)
		{
			__state = default(InventoryOverrideState);
			if (Plugin.PeakStatsEx == null)
			{
				return true;
			}
			if (Plugin.PeakStatsEx.TryDisableDeadStaminaBar(__instance))
			{
				return false;
			}
			if (Plugin.PeakStatsEx.ShouldForceInventoryInFreeCamera())
			{
				__state = Plugin.PeakStatsEx.BeginInventoryOverride();
			}
			if (Plugin.PeakStatsEx.ShouldShowFullPeakStatsExInfo())
			{
				__state.InfoState = Plugin.PeakStatsEx.BeginFullPeakStatsExInfoOverride();
			}
			return true;
		}

		private static void CharacterStaminaBarUpdatePostfix(InventoryOverrideState __state)
		{
			if (Plugin.PeakStatsEx != null)
			{
				Plugin.PeakStatsEx.EndInventoryOverride(__state);
			}
		}
	}
	internal sealed class PeakTrailsCompatibility
	{
		private readonly Harmony _harmony;

		private FieldInfo _showTrailsField;

		private bool _initialized;

		private bool _initAttempted;

		private bool _available;

		private bool _overrideVisible;

		private bool _loggedMissing;

		internal bool ShouldControlTrails
		{
			get
			{
				if (Configuration.EnablePeakTrailsCompatibility && _available && Plugin.CameraController != null)
				{
					return Plugin.CameraController.IsActive;
				}
				return false;
			}
		}

		internal PeakTrailsCompatibility(Harmony harmony)
		{
			_harmony = harmony;
		}

		internal void UpdateInput(bool spectatorActive)
		{
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			if (!Configuration.EnablePeakTrailsCompatibility)
			{
				_overrideVisible = false;
				return;
			}
			EnsureInitialized();
			if (!_available)
			{
				return;
			}
			if (!spectatorActive)
			{
				_overrideVisible = false;
				return;
			}
			if (Input.GetKeyDown(Configuration.PeakTrailsToggleKey.Value))
			{
				_overrideVisible = !_overrideVisible;
			}
			ApplySpectatorTrailState();
		}

		internal void ApplySpectatorTrailState()
		{
			SetShowTrails(_overrideVisible);
		}

		private void EnsureInitialized()
		{
			//IL_00a6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b4: Expected O, but got Unknown
			if (_initialized || _initAttempted)
			{
				return;
			}
			Type type = AccessTools.TypeByName("PEAKTrails.Patching+PlayerVisualUpdatePatch");
			if (type == null)
			{
				_initAttempted = true;
				LogMissingOnce();
				return;
			}
			_initialized = true;
			_showTrailsField = AccessTools.Field(type, "ShowTrails");
			MethodInfo methodInfo = AccessTools.Method(type, "UpdateLocalTrailControls", (Type[])null, (Type[])null);
			MethodInfo methodInfo2 = AccessTools.Method(typeof(PeakTrailsCompatibility), "UpdateLocalTrailControlsPrefix", (Type[])null, (Type[])null);
			if (_showTrailsField == null || methodInfo == null || methodInfo2 == null)
			{
				_initAttempted = true;
				LogMissingOnce();
			}
			else
			{
				_harmony.Patch((MethodBase)methodInfo, new HarmonyMethod(methodInfo2), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
				_available = true;
				L10n.LogInfo("PEAKTrails free-camera trail compatibility enabled. Use the configured key to toggle trail display in the spectator camera.", "已启用 PEAKTrails 自由相机轨迹兼容。按配置按键可在观战相机中切换轨迹显示。");
			}
		}

		private void SetShowTrails(bool value)
		{
			try
			{
				_showTrailsField?.SetValue(null, value);
			}
			catch
			{
			}
		}

		private void LogMissingOnce()
		{
			if (!_loggedMissing)
			{
				_loggedMissing = true;
				L10n.LogInfo("No compatible PEAKTrails 1.1.3 detected; skipped trail compatibility.", "未检测到可兼容的 PEAKTrails 1.1.3,已跳过轨迹兼容。");
			}
		}

		private static bool UpdateLocalTrailControlsPrefix()
		{
			if (Plugin.PeakTrails != null && Plugin.PeakTrails.ShouldControlTrails)
			{
				Plugin.PeakTrails.ApplySpectatorTrailState();
				return false;
			}
			return true;
		}
	}
	[BepInPlugin("com.AiAe.peakspectatormode", "PeakSpectatorMode", "1.1.1")]
	public sealed class Plugin : BaseUnityPlugin
	{
		internal static ManualLogSource Log;

		internal static SpectatorCameraController CameraController;

		internal static SpectatorOverlay Overlay;

		internal static XraySilhouetteManager Xray;

		internal static PeakTrailsCompatibility PeakTrails;

		internal static PeakStatsExCompatibility PeakStatsEx;

		internal static SummitRosterCompatibility SummitRoster;

		internal static SpectatorHudManager HudManager;

		internal static ForceDeathController ForceDeath;

		internal static GhostSpectatorIntegration GsIntegration;

		internal static BetterPlayerDistanceIntegration BpdIntegration;

		private Harmony _harmony;

		private void Awake()
		{
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: Expected O, but got Unknown
			Log = ((BaseUnityPlugin)this).Logger;
			Configuration.Initialize(((BaseUnityPlugin)this).Config);
			_harmony = new Harmony("com.AiAe.peakspectatormode");
			_harmony.PatchAll();
			CameraController = new SpectatorCameraController();
			Overlay = new SpectatorOverlay();
			Xray = new XraySilhouetteManager();
			PeakTrails = new PeakTrailsCompatibility(_harmony);
			PeakStatsEx = new PeakStatsExCompatibility(_harmony);
			SummitRoster = new SummitRosterCompatibility(_harmony);
			HudManager = new SpectatorHudManager();
			ForceDeath = new ForceDeathController();
			GsIntegration = new GhostSpectatorIntegration();
			GsIntegration.TryDetect();
			BpdIntegration = new BetterPlayerDistanceIntegration();
			BpdIntegration.TryDetect();
			L10n.LogInfo("PeakSpectatorMode v1.1.1 loaded.", "更好的观战视角 v1.1.1 已加载。");
		}

		private void Start()
		{
			Overlay.TryInitialize();
		}

		private void Update()
		{
			CameraController.UpdateInput();
			Overlay.UpdateInput(CameraController.IsActive);
			PeakTrails.UpdateInput(CameraController.IsActive);
			PeakStatsEx.Update(CameraController.IsActive);
			ForceDeath.Update();
		}

		private void LateUpdate()
		{
			CameraController.LateUpdate();
			CameraController.UpdateSoftFollow();
			Overlay.LateUpdate(CameraController.IsActive);
			Xray.LateUpdate(CameraController.IsActive);
			HudManager.LateUpdate(CameraController.IsActive);
		}

		private void OnDestroy()
		{
			CameraController.SetActive(active: false);
			BpdIntegration?.Restore();
			HudManager.Restore();
			PeakStatsEx.Restore();
			SummitRoster?.Dispose();
			ForceDeath.Dispose();
			Overlay.Dispose();
			Xray.Dispose();
			Harmony harmony = _harmony;
			if (harmony != null)
			{
				harmony.UnpatchSelf();
			}
		}
	}
	[HarmonyPatch(typeof(Character))]
	internal static class CharacterPatches
	{
		[HarmonyPatch("Awake")]
		[HarmonyPostfix]
		private static void AwakePostfix(Character __instance)
		{
			Plugin.Overlay?.RegisterCharacter(__instance);
			Plugin.Xray?.RegisterCharacter(__instance);
		}

		[HarmonyPatch("OnDestroy")]
		[HarmonyPostfix]
		private static void OnDestroyPostfix(Character __instance)
		{
			Plugin.Overlay?.UnregisterCharacter(__instance);
			Plugin.Xray?.UnregisterCharacter(__instance);
		}
	}
	[HarmonyPatch(typeof(GodCam), "DoFOV")]
	internal static class GodCamFovPatch
	{
		[HarmonyPrefix]
		private static bool Prefix(GodCam __instance, Transform transform, MainCamera cam)
		{
			if (Plugin.CameraController != null)
			{
				return !Plugin.CameraController.TryOverrideGodCamFov(__instance, transform, cam);
			}
			return true;
		}
	}
	[HarmonyPatch(typeof(GUIManager))]
	internal static class GuiManagerHudPatches
	{
		[HarmonyPatch("UpdateDyingBar")]
		[HarmonyPrefix]
		[HarmonyPriority(0)]
		private static bool UpdateDyingBarPrefix(GUIManager __instance)
		{
			return HideAndSkipIfNeeded(__instance);
		}

		[HarmonyPatch("UpdateSpectate")]
		[HarmonyPrefix]
		[HarmonyPriority(0)]
		private static bool UpdateSpectatePrefix(GUIManager __instance)
		{
			return HideAndSkipIfNeeded(__instance);
		}

		[HarmonyPatch("UpdateItems")]
		[HarmonyPrefix]
		[HarmonyPriority(0)]
		private static bool UpdateItemsPrefix(GUIManager __instance)
		{
			return HideAndSkipIfNeeded(__instance);
		}

		[HarmonyPatch("UpdateItemPrompts")]
		[HarmonyPrefix]
		[HarmonyPriority(0)]
		private static bool UpdateItemPromptsPrefix(GUIManager __instance)
		{
			return HideAndSkipIfNeeded(__instance);
		}

		private static bool HideAndSkipIfNeeded(GUIManager gui)
		{
			if (!SpectatorHudManager.ShouldHideHud())
			{
				return true;
			}
			Plugin.HudManager?.HideGuiElements(gui);
			return false;
		}
	}
	internal sealed class RuntimeOverrideManager
	{
		private interface IRuntimeOverride
		{
			int RefCount { get; }

			void AddRef();

			void ReleaseRef();

			void Restore();
		}

		private sealed class RuntimeOverride<T> : IRuntimeOverride
		{
			private readonly Action<T> _setter;

			private readonly T _original;

			private int _refCount;

			public int RefCount => _refCount;

			internal RuntimeOverride(Func<T> getter, Action<T> setter)
			{
				_setter = setter;
				_original = getter();
			}

			public void AddRef()
			{
				_refCount++;
			}

			public void ReleaseRef()
			{
				if (_refCount > 0)
				{
					_refCount--;
				}
			}

			internal void Set(T value)
			{
				_setter(value);
			}

			public void Restore()
			{
				_setter(_original);
				_refCount = 0;
			}
		}

		private readonly Dictionary<object, IRuntimeOverride> _overrides = new Dictionary<object, IRuntimeOverride>();

		internal RuntimeOverrideToken<T> Apply<T>(object key, Func<T> getter, Action<T> setter, T value)
		{
			if (key == null || getter == null || setter == null)
			{
				return RuntimeOverrideToken<T>.Inactive;
			}
			if (!_overrides.TryGetValue(key, out var value2))
			{
				value2 = new RuntimeOverride<T>(getter, setter);
				_overrides.Add(key, value2);
			}
			if (!(value2 is RuntimeOverride<T> runtimeOverride))
			{
				return RuntimeOverrideToken<T>.Inactive;
			}
			runtimeOverride.AddRef();
			runtimeOverride.Set(value);
			return new RuntimeOverrideToken<T>(this, key, active: true);
		}

		internal void Release<T>(RuntimeOverrideToken<T> token)
		{
			if (token.Active && token.Key != null && _overrides.TryGetValue(token.Key, out var value))
			{
				value.ReleaseRef();
				if (value.RefCount <= 0)
				{
					value.Restore();
					_overrides.Remove(token.Key);
				}
			}
		}

		internal void ReleaseAll()
		{
			foreach (IRuntimeOverride value in _overrides.Values)
			{
				value.Restore();
			}
			_overrides.Clear();
		}
	}
	internal struct RuntimeOverrideToken<T>
	{
		internal static readonly RuntimeOverrideToken<T> Inactive = new RuntimeOverrideToken<T>(null, null, active: false);

		private readonly RuntimeOverrideManager _manager;

		internal object Key { get; }

		internal bool Active { get; }

		internal RuntimeOverrideToken(RuntimeOverrideManager manager, object key, bool active)
		{
			_manager = manager;
			Key = key;
			Active = active;
		}

		internal void Release()
		{
			_manager?.Release(this);
		}
	}
	internal sealed class SpectatorCameraController
	{
		private const float MaxCameraPitch = 89.5f;

		private const float MinSwitchDuration = 0.2f;

		private const float MaxSwitchDuration = 0.5f;

		private const float MaxSwitchDistance = 80f;

		private const float EaseEdgeRatio = 0.25f;

		private const float AltSlowTransitionSpeed = 10f;

		private readonly FieldInfo _isGodCamField = AccessTools.Field(typeof(MainCameraMovement), "isGodCam");

		private readonly FieldInfo _lookDataField = AccessTools.Field(typeof(GodCam), "lookData");

		private readonly FieldInfo _targetFovField = AccessTools.Field(typeof(GodCam), "targetFov");

		private readonly FieldInfo _forceField = AccessTools.Field(typeof(GodCam), "force");

		private readonly FieldInfo _dragField = AccessTools.Field(typeof(GodCam), "drag");

		private readonly FieldInfo _lookSensField = AccessTools.Field(typeof(GodCam), "lookSens");

		private readonly FieldInfo _lookDragField = AccessTools.Field(typeof(GodCam), "lookDrag");

		private Character _focusedPlayer;

		private bool _switchTransitionActive;

		private Vector3 _switchStartPosition;

		private Vector3 _switchTargetPosition;

		private Quaternion _switchStartRotation;

		private Quaternion _switchTargetRotation;

		private float _switchElapsed;

		private float _switchDuration;

		private bool _hasFovState;

		private float _defaultFov = 70f;

		private float _scrollFovTarget = 70f;

		private bool _followActive;

		private Character _followTarget;

		private Vector3 _followTargetPosSnapshot;

		private float _altSlowMultiplier = 1f;

		internal bool IsActive { get; private set; }

		internal Character FollowingTarget
		{
			get
			{
				if (!_followActive || !((Object)(object)_followTarget != (Object)null) || !CharacterState.IsAliveSpectatorTarget(_followTarget))
				{
					return null;
				}
				return _followTarget;
			}
		}

		internal Character FocusedPlayer
		{
			get
			{
				if (!IsActive || !((Object)(object)_focusedPlayer != (Object)null) || !CharacterState.IsAliveSpectatorTarget(_focusedPlayer))
				{
					return null;
				}
				return _focusedPlayer;
			}
		}

		internal void UpdateInput()
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_005d: Unknown result type (might be due to invalid IL or missing references)
			//IL_007c: 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)
			if (Input.GetKeyDown(Configuration.ToggleKey.Value) && !Input.GetKey((KeyCode)308) && !Input.GetKey((KeyCode)307))
			{
				SetActive(!IsActive);
			}
			if (IsActive && Input.GetKeyDown((KeyCode)27))
			{
				SetActive(active: false);
			}
			if (IsActive && Input.GetKeyDown(Configuration.ResetKey.Value))
			{
				ResetToLocalPlayer();
			}
			if (IsActive && Input.GetKeyDown(Configuration.PreviousPlayerKey.Value))
			{
				CycleFocusedPlayer(-1);
			}
			if (IsActive && Input.GetKeyDown(Configuration.NextPlayerKey.Value))
			{
				CycleFocusedPlayer(1);
			}
			if (IsActive)
			{
				ApplyGodCamSettings();
			}
		}

		internal void LateUpdate()
		{
			UpdateSwitchTransition();
		}

		internal void SetActive(bool active)
		{
			bool isActive = IsActive;
			MainCameraMovement instance = Singleton<MainCameraMovement>.Instance;
			if ((Object)(object)instance == (Object)null)
			{
				IsActive = false;
				_focusedPlayer = null;
				return;
			}
			IsActive = active;
			_isGodCamField?.SetValue(instance, active);
			if (active)
			{
				if (!isActive)
				{
					InitializeFovState();
				}
				SyncGodCamState(instance);
				ResetCursorForCamera();
			}
			else
			{
				_hasFovState = false;
				_focusedPlayer = null;
				_switchTransitionActive = false;
				_followActive = false;
				_followTarget = null;
				_altSlowMultiplier = 1f;
			}
		}

		private void ApplyGodCamSettings()
		{
			MainCameraMovement instance = Singleton<MainCameraMovement>.Instance;
			if (instance?.godcam != null)
			{
				float num = (Input.GetKey((KeyCode)304) ? Mathf.Max(Configuration.NormalSpeed.Value, Configuration.FastSpeed.Value / 10f) : Configuration.NormalSpeed.Value);
				float num2 = (IsAltHeld() ? Mathf.Clamp(Configuration.AltSlowSpeedMultiplier.Value, 0.05f, 1f) : 1f);
				_altSlowMultiplier = Mathf.Lerp(_altSlowMultiplier, num2, Time.unscaledDeltaTime * 10f);
				_forceField?.SetValue(instance.godcam, num * _altSlowMultiplier);
				_dragField?.SetValue(instance.godcam, Configuration.MoveDamping.Value);
				_lookSensField?.SetValue(instance.godcam, Configuration.TurnSpeed.Value);
				_lookDragField?.SetValue(instance.godcam, Configuration.TurnDamping.Value);
			}
		}

		private static bool IsAltHeld()
		{
			if (!Input.GetKey((KeyCode)308))
			{
				return Input.GetKey((KeyCode)307);
			}
			return true;
		}

		internal bool TryOverrideGodCamFov(GodCam godCam, Transform cameraTransform, MainCamera mainCamera)
		{
			//IL_0076: Unknown result type (might be due to invalid IL or missing references)
			//IL_00dd: Unknown result type (might be due to invalid IL or missing references)
			if (!IsActive || godCam == null || (Object)(object)mainCamera == (Object)null || (Object)(object)mainCamera.cam == (Object)null)
			{
				return false;
			}
			ClampGodCamPitch(godCam, cameraTransform);
			EnsureFovState(mainCamera.cam);
			float num = Mathf.Clamp(mainCamera.cam.fieldOfView, 1f, 120f);
			float num2 = Mathf.Lerp(num / 70f, 1f, 0.25f);
			_scrollFovTarget += (0f - Input.mouseScrollDelta.y) * 2f * num2;
			_scrollFovTarget = Mathf.Clamp(_scrollFovTarget, 1f, 120f);
			if (Input.GetKeyDown((KeyCode)325))
			{
				_scrollFovTarget = Mathf.Clamp(_defaultFov, 1f, 120f);
			}
			float num3 = _scrollFovTarget;
			if (Input.GetKey(Configuration.TelescopeKey.Value))
			{
				num3 = CalculateZoomFov(_scrollFovTarget, Configuration.TelescopeMultiplier.Value);
			}
			float num4 = Mathf.Max(0.01f, 8f);
			mainCamera.cam.fieldOfView = Mathf.Lerp(num, num3, Time.unscaledDeltaTime * num4);
			_targetFovField?.SetValue(godCam, _scrollFovTarget);
			return true;
		}

		private void ClampGodCamPitch(GodCam godCam, Transform cameraTransform)
		{
			//IL_0031: 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_003a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0051: Unknown result type (might be due to invalid IL or missing references)
			//IL_006e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0079: 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_008a: Unknown result type (might be due to invalid IL or missing references)
			//IL_008f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0094: Unknown result type (might be due to invalid IL or missing references)
			//IL_0099: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ab: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b0: Unknown result type (might be due to invalid IL or missing references)
			if (_lookDataField == null || godCam == null || (Object)(object)cameraTransform == (Object)null || !(_lookDataField.GetValue(godCam) is Vector2 val))
			{
				return;
			}
			float num = Mathf.Clamp(val.y, -89.5f, 89.5f);
			if (!Mathf.Approximately(num, val.y))
			{
				val.y = num;
				_lookDataField.SetValue(godCam, val);
				Vector3 val2 = HelperFunctions.LookToDirection(new Vector3(val.x, val.y, 0f), Vector3.forward);
				if (((Vector3)(ref val2)).sqrMagnitude > 0.0001f)
				{
					cameraTransform.rotation = Quaternion.LookRotation(((Vector3)(ref val2)).normalized);
				}
			}
		}

		private void SyncGodCamState(MainCameraMovement movement)
		{
			//IL_000f: 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)
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: 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)
			//IL_004e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0054: Unknown result type (might be due to invalid IL or missing references)
			if (movement.godcam != null)
			{
				Vector3 val = DirectionToLook(((Component)movement).transform.forward);
				val.y = Mathf.Clamp(val.y, -89.5f, 89.5f);
				_lookDataField?.SetValue(movement.godcam, (object)new Vector2(val.x, val.y));
				Camera val2 = (((Object)(object)MainCamera.instance != (Object)null) ? MainCamera.instance.cam : Camera.main);
				if ((Object)(object)val2 != (Object)null)
				{
					_targetFovField?.SetValue(movement.godcam, val2.fieldOfView);
				}
				ApplyGodCamSettings();
			}
		}

		private void InitializeFovState()
		{
			Camera val = (((Object)(object)MainCamera.instance != (Object)null) ? MainCamera.instance.cam : Camera.main);
			if ((Object)(object)val == (Object)null)
			{
				_hasFovState = false;
				_defaultFov = 70f;
				_scrollFovTarget = 70f;
			}
			else
			{
				_defaultFov = Mathf.Clamp(val.fieldOfView, 1f, 120f);
				_scrollFovTarget = _defaultFov;
				_hasFovState = true;
			}
		}

		private void EnsureFovState(Camera cam)
		{
			if (!_hasFovState)
			{
				if ((Object)(object)cam == (Object)null)
				{
					_defaultFov = 70f;
					_scrollFovTarget = 70f;
				}
				else
				{
					_defaultFov = Mathf.Clamp(cam.fieldOfView, 1f, 120f);
					_scrollFovTarget = _defaultFov;
				}
				_hasFovState = true;
			}
		}

		private static float CalculateZoomFov(float baseFov, float multiplier)
		{
			baseFov = Mathf.Clamp(baseFov, 1f, 120f);
			multiplier = Mathf.Max(1f, multiplier);
			float num = baseFov * (MathF.PI / 180f);
			return Mathf.Clamp(2f * Mathf.Atan(Mathf.Tan(num * 0.5f) / multiplier) * 57.29578f, 1f, 120f);
		}

		internal void ResetToLocalPlayer()
		{
			//IL_0043: 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)
			//IL_004a: 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_0056: Unknown result type (might be due to invalid IL or missing references)
			//IL_005b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0060: Unknown result type (might be due to invalid IL or missing references)
			//IL_006a: Unknown result type (might be due to invalid IL or missing references)
			//IL_006f: Unknown result type (might be due to invalid IL or missing references)
			MainCameraMovement instance = Singleton<MainCameraMovement>.Instance;
			Character localCharacter = Character.localCharacter;
			if (!((Object)(object)instance == (Object)null) && !((Object)(object)localCharacter == (Object)null))
			{
				Transform transform = ((Component)instance).transform;
				_focusedPlayer = null;
				_switchTransitionActive = false;
				_followActive = false;
				_followTarget = null;
				Vector3 characterResetPosition = GetCharacterResetPosition(localCharacter);
				transform.position = characterResetPosition - transform.forward * 2.4f + Vector3.up * 1.2f;
				SyncGodCamState(instance);
			}
		}

		private void CycleFocusedPlayer(int direction)
		{
			List<Character> cycleTargets = GetCycleTargets();
			if (cycleTargets.Count == 0)
			{
				_focusedPlayer = null;
				return;
			}
			int num = cycleTargets.IndexOf(_focusedPlayer);
			int index = ((num >= 0) ? ((num + direction + cycleTargets.Count) % cycleTargets.Count) : ((direction <= 0) ? (cycleTargets.Count - 1) : 0));
			_focusedPlayer = cycleTargets[index];
			SetActive(active: true);
			StartCameraSwitchTransition(_focusedPlayer);
		}

		private void StartCameraSwitchTransition(Character target)
		{
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_003c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			//IL_0047: 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)
			//IL_004e: 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_0061: 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)
			MainCameraMovement instance = Singleton<MainCameraMovement>.Instance;
			if (!((Object)(object)instance == (Object)null) && !((Object)(object)target == (Object)null))
			{
				Transform transform = ((Component)instance).transform;
				if (TryGetTargetCameraPose(target, transform, out var position, out var rotation))
				{
					_switchStartPosition = transform.position;
					_switchStartRotation = transform.rotation;
					_switchTargetPosition = position;
					_switchTargetRotation = rotation;
					_switchElapsed = 0f;
					_switchDuration = CalculateSwitchDuration(Vector3.Distance(_switchStartPosition, _switchTargetPosition));
					_switchTransitionActive = true;
				}
			}
		}

		private void UpdateSwitchTransition()
		{
			//IL_0093: Unknown result type (might be due to invalid IL or missing references)
			//IL_0099: Unknown result type (might be due to invalid IL or missing references)
			//IL_009f: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ab: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b7: Unknown result type (might be due to invalid IL or missing references)
			//IL_0082: Unknown result type (might be due to invalid IL or missing references)
			//IL_0084: Unknown result type (might be due to invalid IL or missing references)
			//IL_008a: Unknown result type (might be due to invalid IL or missing references)
			//IL_008c: Unknown result type (might be due to invalid IL or missing references)
			if (!_switchTransitionActive || !IsActive)
			{
				return;
			}
			MainCameraMovement instance = Singleton<MainCameraMovement>.Instance;
			Character focusedPlayer = FocusedPlayer;
			if ((Object)(object)instance == (Object)null || (Object)(object)focusedPlayer == (Object)null)
			{
				_switchTransitionActive = false;
				return;
			}
			_switchElapsed += Time.unscaledDeltaTime;
			float num = Mathf.Clamp01(_switchElapsed / Mathf.Max(0.01f, _switchDuration));
			float num2 = TripleEase(num);
			Transform transform = ((Component)instance).transform;
			if (TryGetTargetCameraPose(focusedPlayer, transform, out var position, out var rotation))
			{
				_switchTargetPosition = position;
				_switchTargetRotation = rotation;
			}
			transform.position = Vector3.LerpUnclamped(_switchStartPosition, _switchTargetPosition, num2);
			transform.rotation = Quaternion.Slerp(_switchStartRotation, _switchTargetRotation, num2);
			SyncGodCamState(instance);
			if (num >= 1f)
			{
				_switchTransitionActive = false;
				StartSoftFollow(focusedPlayer);
			}
		}

		private void StartSoftFollow(Character target)
		{
			//IL_002d: 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)
			if ((Object)(object)target == (Object)null || !Configuration.EnableSoftFollow.Value)
			{
				_followActive = false;
				_followTarget = null;
			}
			else
			{
				_followTarget = target;
				_followTargetPosSnapshot = SafeGetTargetCenter(target);
				_followActive = true;
			}
		}

		internal void UpdateSoftFollow()
		{
			//IL_0061: Unknown result type (might be due to invalid IL or missing references)
			//IL_0066: Unknown result type (might be due to invalid IL or missing references)
			//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_009a: 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_00a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ca: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b8: 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_00bf: Unknown result type (might be due to invalid IL or missing references)
			if (!_followActive || !IsActive || _switchTransitionActive)
			{
				return;
			}
			if ((Object)(object)_followTarget == (Object)null || !CharacterState.IsAliveSpectatorTarget(_followTarget))
			{
				_followActive = false;
				_followTarget = null;
				return;
			}
			MainCameraMovement instance = Singleton<MainCameraMovement>.Instance;
			if ((Object)(object)instance == (Object)null)
			{
				return;
			}
			Transform transform = ((Component)instance).transform;
			Vector3 val = SafeGetTargetCenter(_followTarget);
			float num = Vector3.Distance(transform.position, val);
			float num2 = Mathf.Max(1f, Configuration.SoftFollowMaxDistance.Value);
			if (num > num2)
			{
				_followActive = false;
				_followTarget = null;
				return;
			}
			Vector3 val2 = val - _followTargetPosSnapshot;
			if (((Vector3)(ref val2)).sqrMagnitude > 0f)
			{
				transform.position += val2;
			}
			_followTargetPosSnapshot = val;
		}

		private static bool HasMovementInput()
		{
			if (!Input.GetKey((KeyCode)119) && !Input.GetKey((KeyCode)97) && !Input.GetKey((KeyCode)115) && !Input.GetKey((KeyCode)100) && !Input.GetKey((KeyCode)32) && !Input.GetKey((KeyCode)306) && !Input.GetKey((KeyCode)113))
			{
				return Input.GetKey((KeyCode)101);
			}
			return true;
		}

		private static Vector3 SafeGetTargetCenter(Character target)
		{
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: 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_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_003a: 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)
			if ((Object)(object)target == (Object)null)
			{
				return Vector3.zero;
			}
			try
			{
				return target.Center;
			}
			catch
			{
				return ((Object)(object)((Component)target).transform != (Object)null) ? ((Component)target).transform.position : Vector3.zero;
			}
		}

		private static float CalculateSwitchDuration(float distance)
		{
			float num = Mathf.InverseLerp(0f, 80f, Mathf.Max(0f, distance));
			return Mathf.Lerp(0.2f, 0.5f, num);
		}

		private static float TripleEase(float t)
		{
			t = Mathf.Clamp01(t);
			float num = Mathf.Clamp(0.25f, 0.0001f, 0.4999f);
			float num2 = 1f / (1f - num);
			if (t <= num)
			{
				return num2 * t * t / (2f * num);
			}
			if (t < 1f - num)
			{
				return num2 * num / 2f + num2 * (t - num);
			}
			float num3 = num2 * num / 2f;
			float num4 = num2 * (1f - 2f * num);
			float num5 = t - (1f - num);
			float num6 = num2 * num5 - num2 * num5 * num5 / (2f * num);
			return num3 + num4 + num6;
		}

		private static bool TryGetTargetCameraPose(Character target, Transform cameraTransform, out Vector3 position, out Quaternion rotation)
		{
			//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_000c: 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_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)
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_002f: 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_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0042: 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_0051: Unknown result type (might be due to invalid IL or missing references)
			//IL_0056: Unknown result type (might be due to invalid IL or missing references)
			//IL_005b: Unknown result type (might be due to invalid IL or missing references)
			//IL_005d: 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_0079: Unknown result type (might be due to invalid IL or missing references)
			//IL_007e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0083: Unknown result type (might be due to invalid IL or missing references)
			//IL_0088: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_0099: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a6: Unknown result type (might be due to invalid IL or missing references)
			position = Vector3.zero;
			rotation = Quaternion.identity;
			if ((Object)(object)target == (Object)null)
			{
				return false;
			}
			Vector3 characterFocusPoint = GetCharacterFocusPoint(target);
			Vector3 characterBackDirection = GetCharacterBackDirection(target, cameraTransform);
			position = characterFocusPoint - characterBackDirection * 4f + Vector3.up * 1.4f;
			Vector3 val = characterFocusPoint - position;
			if (((Vector3)(ref val)).sqrMagnitude > 0.001f)
			{
				rotation = Quaternion.LookRotation(((Vector3)(ref val)).normalized, Vector3.up);
				return true;
			}
			rotation = (((Object)(object)cameraTransform != (Object)null) ? cameraTransform.rotation : Quaternion.identity);
			return true;
		}

		private static List<Character> GetCycleTargets()
		{
			List<Character> list = new List<Character>();
			foreach (Character allCharacter in Character.AllCharacters)
			{
				if (CharacterState.IsAliveSpectatorTarget(allCharacter))
				{
					list.Add(allCharacter);
				}
			}
			list.Sort((Character a, Character b) => GetSortKey(a).CompareTo(GetSortKey(b)));
			return list;
		}

		private static int GetSortKey(Character character)
		{
			try
			{
				if ((Object)(object)((MonoBehaviourPun)character).photonView != (Object)null)
				{
					return ((MonoBehaviourPun)character).photonView.OwnerActorNr;
				}
			}
			catch
			{
			}
			return ((Object)character).GetInstanceID();
		}

		private static Vector3 GetCharacterResetPosition(Character character)
		{
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: 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_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: 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_0037: 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_0016: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)character == (Object)null)
			{
				return Vector3.zero;
			}
			try
			{
				return character.Head;
			}
			catch
			{
				return character.Center + Vector3.up * 1.2f;
			}
		}

		private static Vector3 GetCharacterFocusPoint(Character character)
		{
			//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_000b: 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_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_0024: 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)
			try
			{
				return character.Head;
			}
			catch
			{
				return character.Center + Vector3.up * 1.2f;
			}
		}

		private static Vector3 GetCharacterBackDirection(Character character, Tr