Decompiled source of TeamSpectate v1.0.0

plugins/TeamSpectate.dll

Decompiled 3 days ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using Photon.Pun;
using Photon.Realtime;
using Photon.Voice.Unity;
using UnityEngine;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETFramework,Version=v4.8.1", FrameworkDisplayName = ".NET Framework 4.8.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 TeamSpectate
{
	internal static class L
	{
		public static bool English;

		public static string T(string chinese, string english)
		{
			if (!English)
			{
				return chinese;
			}
			return english;
		}

		public static void Apply(ConfigEntry<bool> entry)
		{
			English = entry?.Value ?? false;
		}
	}
	internal static class MenuTheme
	{
		public static readonly Color Accent = Hex("B8720A");

		public static readonly Color TextMain = Hex("1A1C1F");

		public static readonly Color TextSub = Hex("454B55");

		public static readonly Color TextHint = Hex("6C7480");

		public static readonly Color Green = Hex("2E7D32");

		public static readonly Color TitleBar = Hex("E3E6EB");

		public static readonly Color OnVideoText = Hex("FFFFFFFF");

		public static GUIStyle Window;

		public static GUIStyle Title;

		public static GUIStyle Label;

		public static GUIStyle Sub;

		public static GUIStyle Hint;

		public static GUIStyle Button;

		public static GUIStyle ButtonActive;

		public static GUIStyle ButtonPrimary;

		public static GUIStyle CellLabel;

		public static GUIStyle Small;

		private static Texture2D _windowTex;

		private static Texture2D _cardTex;

		private static Texture2D _titleTex;

		private static Texture2D _btnTex;

		private static Texture2D _btnHoverTex;

		private static Texture2D _btnActiveTex;

		private static Texture2D _btnPrimaryTex;

		private static Texture2D _labelBgTex;

		private static Texture2D _accentTex;

		private static Font _font;

		private static bool _built;

		public static Texture2D AccentTex
		{
			get
			{
				//IL_000d: Unknown result type (might be due to invalid IL or missing references)
				if ((Object)(object)_accentTex == (Object)null)
				{
					_accentTex = Tex(Accent);
				}
				return _accentTex;
			}
		}

		public static void EnsureBuilt()
		{
			//IL_0086: 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_00ae: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ea: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fe: Unknown result type (might be due to invalid IL or missing references)
			//IL_0112: Unknown result type (might be due to invalid IL or missing references)
			//IL_0121: Unknown result type (might be due to invalid IL or missing references)
			//IL_0126: Unknown result type (might be due to invalid IL or missing references)
			//IL_0136: Unknown result type (might be due to invalid IL or missing references)
			//IL_013f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0149: Expected O, but got Unknown
			//IL_0149: 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_0158: Expected O, but got Unknown
			//IL_015d: Expected O, but got Unknown
			//IL_015d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0162: Unknown result type (might be due to invalid IL or missing references)
			//IL_016d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0175: Unknown result type (might be due to invalid IL or missing references)
			//IL_017c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0183: Unknown result type (might be due to invalid IL or missing references)
			//IL_0189: Unknown result type (might be due to invalid IL or missing references)
			//IL_0198: Expected O, but got Unknown
			//IL_0198: Unknown result type (might be due to invalid IL or missing references)
			//IL_019d: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b7: 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_01cc: Expected O, but got Unknown
			//IL_01cc: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d1: Unknown result type (might be due to invalid IL or missing references)
			//IL_01dc: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e4: Unknown result type (might be due to invalid IL or missing references)
			//IL_01eb: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f1: Unknown result type (might be due to invalid IL or missing references)
			//IL_0200: Expected O, but got Unknown
			//IL_0200: Unknown result type (might be due to invalid IL or missing references)
			//IL_0205: Unknown result type (might be due to invalid IL or missing references)
			//IL_0210: Unknown result type (might be due to invalid IL or missing references)
			//IL_0218: Unknown result type (might be due to invalid IL or missing references)
			//IL_021f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0226: Unknown result type (might be due to invalid IL or missing references)
			//IL_022c: Unknown result type (might be due to invalid IL or missing references)
			//IL_023b: Expected O, but got Unknown
			//IL_023b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0240: Unknown result type (might be due to invalid IL or missing references)
			//IL_024b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0253: Unknown result type (might be due to invalid IL or missing references)
			//IL_025a: Unknown result type (might be due to invalid IL or missing references)
			//IL_025f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0269: Expected O, but got Unknown
			//IL_0269: Unknown result type (might be due to invalid IL or missing references)
			//IL_0279: Unknown result type (might be due to invalid IL or missing references)
			//IL_027f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0289: Unknown result type (might be due to invalid IL or missing references)
			//IL_0299: Unknown result type (might be due to invalid IL or missing references)
			//IL_029f: Unknown result type (might be due to invalid IL or missing references)
			//IL_02a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_02b9: Unknown result type (might be due to invalid IL or missing references)
			//IL_02bf: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ce: Expected O, but got Unknown
			//IL_02d3: Unknown result type (might be due to invalid IL or missing references)
			//IL_02d8: Unknown result type (might be due to invalid IL or missing references)
			//IL_02e8: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ee: Unknown result type (might be due to invalid IL or missing references)
			//IL_02f8: Unknown result type (might be due to invalid IL or missing references)
			//IL_0308: Unknown result type (might be due to invalid IL or missing references)
			//IL_030e: Unknown result type (might be due to invalid IL or missing references)
			//IL_031d: Expected O, but got Unknown
			//IL_0322: Unknown result type (might be due to invalid IL or missing references)
			//IL_0327: Unknown result type (might be due to invalid IL or missing references)
			//IL_0337: Unknown result type (might be due to invalid IL or missing references)
			//IL_0342: Unknown result type (might be due to invalid IL or missing references)
			//IL_034c: Unknown result type (might be due to invalid IL or missing references)
			//IL_035c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0367: Unknown result type (might be due to invalid IL or missing references)
			//IL_0376: Expected O, but got Unknown
			//IL_0376: Unknown result type (might be due to invalid IL or missing references)
			//IL_037b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0386: Unknown result type (might be due to invalid IL or missing references)
			//IL_038e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0395: Unknown result type (might be due to invalid IL or missing references)
			//IL_039c: Unknown result type (might be due to invalid IL or missing references)
			//IL_03a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_03ab: Expected O, but got Unknown
			//IL_03ab: Unknown result type (might be due to invalid IL or missing references)
			//IL_03bb: Unknown result type (might be due to invalid IL or missing references)
			//IL_03c1: Unknown result type (might be due to invalid IL or missing references)
			//IL_03d0: Expected O, but got Unknown
			//IL_03d0: Unknown result type (might be due to invalid IL or missing references)
			//IL_03d5: Unknown result type (might be due to invalid IL or missing references)
			//IL_03e0: Unknown result type (might be due to invalid IL or missing references)
			//IL_03e8: Unknown result type (might be due to invalid IL or missing references)
			//IL_03ef: Unknown result type (might be due to invalid IL or missing references)
			//IL_03f6: Unknown result type (might be due to invalid IL or missing references)
			//IL_03fd: Unknown result type (might be due to invalid IL or missing references)
			//IL_0402: Unknown result type (might be due to invalid IL or missing references)
			//IL_040c: Expected O, but got Unknown
			//IL_040c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0412: Unknown result type (might be due to invalid IL or missing references)
			//IL_0421: Expected O, but got Unknown
			if (!_built || Window == null || !((Object)(object)Window.normal.background != (Object)null))
			{
				_font = Font.CreateDynamicFontFromOSFont(new string[6] { "Microsoft YaHei", "微软雅黑", "SimHei", "黑体", "Noto Sans CJK SC", "Arial" }, 13);
				if ((Object)(object)_font != (Object)null)
				{
					((Object)_font).hideFlags = (HideFlags)61;
				}
				_windowTex = Tex(Hex("FFFFFFFF"));
				_cardTex = Tex(Hex("FFF2F3F6"));
				_titleTex = Tex(Hex("FFE3E6EB"));
				_btnTex = Tex(Hex("FFE4E7EC"));
				_btnHoverTex = Tex(Hex("FFD5DAE2"));
				_btnActiveTex = Tex(Hex("FFBCC4D0"));
				_btnPrimaryTex = Tex(Hex("FFD08A2A"));
				_labelBgTex = Tex(Hex("B0000000"));
				GUIStyle val = new GUIStyle();
				val.normal.background = _windowTex;
				val.padding = new RectOffset(10, 10, 10, 10);
				val.border = new RectOffset(1, 1, 1, 1);
				Window = val;
				GUIStyle val2 = new GUIStyle
				{
					font = _font,
					fontSize = 15,
					fontStyle = (FontStyle)1,
					alignment = (TextAnchor)3
				};
				val2.normal.textColor = TextMain;
				Title = val2;
				GUIStyle val3 = new GUIStyle
				{
					font = _font,
					fontSize = 13,
					alignment = (TextAnchor)3
				};
				val3.normal.textColor = TextMain;
				Label = val3;
				GUIStyle val4 = new GUIStyle
				{
					font = _font,
					fontSize = 12,
					alignment = (TextAnchor)3
				};
				val4.normal.textColor = TextSub;
				Sub = val4;
				GUIStyle val5 = new GUIStyle
				{
					font = _font,
					fontSize = 11,
					wordWrap = true,
					alignment = (TextAnchor)0
				};
				val5.normal.textColor = TextHint;
				Hint = val5;
				GUIStyle val6 = new GUIStyle
				{
					font = _font,
					fontSize = 12,
					alignment = (TextAnchor)4,
					padding = new RectOffset(8, 8, 4, 4)
				};
				val6.normal.background = _btnTex;
				val6.normal.textColor = TextMain;
				val6.hover.background = _btnHoverTex;
				val6.hover.textColor = TextMain;
				val6.active.background = _btnActiveTex;
				val6.active.textColor = TextMain;
				Button = val6;
				GUIStyle val7 = new GUIStyle(Button);
				val7.normal.background = _btnHoverTex;
				val7.normal.textColor = Accent;
				val7.hover.background = _btnActiveTex;
				val7.hover.textColor = Accent;
				ButtonActive = val7;
				GUIStyle val8 = new GUIStyle(Button);
				val8.normal.background = _btnPrimaryTex;
				val8.normal.textColor = Hex("FF1A1206");
				val8.hover.background = _btnPrimaryTex;
				val8.hover.textColor = Hex("FF1A1206");
				ButtonPrimary = val8;
				GUIStyle val9 = new GUIStyle
				{
					font = _font,
					fontSize = 13,
					fontStyle = (FontStyle)1,
					alignment = (TextAnchor)3,
					padding = new RectOffset(6, 6, 2, 2)
				};
				val9.normal.background = _labelBgTex;
				val9.normal.textColor = OnVideoText;
				CellLabel = val9;
				GUIStyle val10 = new GUIStyle
				{
					font = _font,
					fontSize = 10,
					wordWrap = false,
					clipping = (TextClipping)1,
					alignment = (TextAnchor)3,
					padding = new RectOffset(2, 2, 0, 0)
				};
				val10.normal.textColor = OnVideoText;
				Small = val10;
				_built = true;
			}
		}

		private static Texture2D Tex(Color color)
		{
			//IL_0004: 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_0011: 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_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Expected O, but got Unknown
			Texture2D val = new Texture2D(1, 1, (TextureFormat)4, false)
			{
				hideFlags = (HideFlags)61
			};
			val.SetPixel(0, 0, color);
			val.Apply();
			return val;
		}

		private static Color Hex(string hex)
		{
			//IL_001a: 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)
			Color result = default(Color);
			if (!ColorUtility.TryParseHtmlString("#" + hex, ref result))
			{
				return Color.white;
			}
			return result;
		}
	}
	internal static class ModConfig
	{
		public static ConfigEntry<KeyCode> MenuKey;

		public static ConfigEntry<bool> UseEnglish;

		public static ConfigEntry<bool> SelfWindowEnabled;

		public static ConfigEntry<int> SelfWindowCorner;

		public static ConfigEntry<float> SelfWindowWidth;

		public static ConfigEntry<float> SelfWindowHeight;

		public static ConfigEntry<float> SelfWindowMargin;

		public static ConfigEntry<float> SelfWindowX;

		public static ConfigEntry<float> SelfWindowY;

		public static ConfigEntry<float> SpectateZoom;

		public static ConfigEntry<float> FieldOfView;

		public static ConfigEntry<float> ResolutionScale;

		public static ConfigEntry<float> MaxRenderDistance;

		public static ConfigEntry<bool> RenderShadows;

		public static ConfigEntry<bool> ShowNameLabel;

		public static ConfigEntry<bool> ShowStatusOverlay;

		public static ConfigEntry<float> OverlayScale;

		public static ConfigEntry<bool> UseNativeSpectateMode;

		public static ConfigEntry<bool> GhostVoiceInNativeSpectate;

		public static bool MonitorOnly;

		internal static bool NativeSpectateWasActive;

		public static ConfigEntry<bool> DetailedLog;

		public static void Init(ConfigFile config)
		{
			//IL_00a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ad: Expected O, but got Unknown
			//IL_00db: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e5: Expected O, but got Unknown
			//IL_0113: Unknown result type (might be due to invalid IL or missing references)
			//IL_011d: Expected O, but got Unknown
			//IL_014b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0155: Expected O, but got Unknown
			//IL_0183: Unknown result type (might be due to invalid IL or missing references)
			//IL_018d: Expected O, but got Unknown
			//IL_01bb: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c5: Expected O, but got Unknown
			//IL_01f3: Unknown result type (might be due to invalid IL or missing references)
			//IL_01fd: Expected O, but got Unknown
			//IL_022b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0235: Expected O, but got Unknown
			//IL_0263: Unknown result type (might be due to invalid IL or missing references)
			//IL_026d: Expected O, but got Unknown
			MenuKey = config.Bind<KeyCode>("菜单", "菜单按键", (KeyCode)290, "打开/关闭队友观战菜单的按键。菜单关闭后,正在观战的分屏会继续显示。");
			UseEnglish = config.Bind<bool>("菜单", "界面语言(英文)", false, "菜单界面是否使用英文。也可在菜单右上角按钮里随时切换。");
			L.Apply(UseEnglish);
			SelfWindowEnabled = config.Bind<bool>("自身小窗", "启用自身小窗", false, "是否在屏幕角落额外显示一扇小窗,播放你自己角色的观战视角。多路分屏与原生观战模式下均可显示。");
			SelfWindowCorner = config.Bind<int>("自身小窗", "小窗位置", 0, "自身小窗的默认角落:0=右下,1=右上,2=左下,3=左上。仅当尚未手动拖动过小窗时用于初始摆放。");
			SelfWindowWidth = config.Bind<float>("自身小窗", "小窗宽度(像素)", 320f, new ConfigDescription("自身小窗的宽度(像素)。也可直接在游戏里拖动小窗右下角调整,会自动写回此处。", (AcceptableValueBase)(object)new AcceptableValueRange<float>(120f, 960f), Array.Empty<object>()));
			SelfWindowHeight = config.Bind<float>("自身小窗", "小窗高度(像素)", 0f, new ConfigDescription("自身小窗的高度(像素)。0 表示按 16:9 由宽度自动推算;拖动右下角调整后会自动写回此处。", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1080f), Array.Empty<object>()));
			SelfWindowMargin = config.Bind<float>("自身小窗", "小窗边距(像素)", 16f, new ConfigDescription("自身小窗按角落自动摆放时与屏幕边缘的距离(像素)。", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 200f), Array.Empty<object>()));
			SelfWindowX = config.Bind<float>("自身小窗", "小窗水平位置", -1f, new ConfigDescription("自身小窗左上角的 X 坐标(像素)。-1 表示按“小窗位置”角落自动摆放;手动拖动后自动写回此处。", (AcceptableValueBase)(object)new AcceptableValueRange<float>(-1f, 8192f), Array.Empty<object>()));
			SelfWindowY = config.Bind<float>("自身小窗", "小窗垂直位置", -1f, new ConfigDescription("自身小窗左上角的 Y 坐标(像素)。-1 表示按“小窗位置”角落自动摆放;手动拖动后自动写回此处。", (AcceptableValueBase)(object)new AcceptableValueRange<float>(-1f, 8192f), Array.Empty<object>()));
			SpectateZoom = config.Bind<float>("观战视角", "跟随距离", 2.5f, new ConfigDescription("观战相机与目标角色之间的距离,越大视角越远(与原版观战一致约 2.5)。", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.5f, 8f), Array.Empty<object>()));
			FieldOfView = config.Bind<float>("观战视角", "视野角度", 70f, new ConfigDescription("观战相机视野(度)。", (AcceptableValueBase)(object)new AcceptableValueRange<float>(30f, 110f), Array.Empty<object>()));
			ResolutionScale = config.Bind<float>("观战视角", "分辨率比例", 1f, new ConfigDescription("每个分屏画面的渲染分辨率比例:1 为与屏幕上的窗口同分辨率,越大越清晰但越耗性能,可在菜单里用 -/+ 调节。", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.2f, 3f), Array.Empty<object>()));
			MaxRenderDistance = config.Bind<float>("观战视角", "渲染最大距离(米)", 400f, new ConfigDescription("每路观战相机能看到的最远距离(米)。调小可显著降低多路分屏的渲染开销,画面远处会被截掉。", (AcceptableValueBase)(object)new AcceptableValueRange<float>(50f, 2000f), Array.Empty<object>()));
			RenderShadows = config.Bind<bool>("观战视角", "启用观战画面阴影", false, "是否让每路观战相机单独渲染阴影。默认关闭:每路分屏可省去一轮阴影渲染,明显减少多路观战的卡顿。");
			ShowNameLabel = config.Bind<bool>("观战视角", "显示名字标签", true, "是否在每格画面左上角显示被观战队友的名字与编号。");
			ShowStatusOverlay = config.Bind<bool>("观战视角", "显示状态条与物品栏", true, "是否在每格画面左下角显示该队友的状态条与物品栏。状态条只使用游戏原生样式渲染,外观与 HUD 完全一致。");
			OverlayScale = config.Bind<float>("观战视角", "状态栏缩放", 1f, "状态条与物品栏在“随分屏大小自动缩放”基础上的额外缩放倍数。不设上限,可在菜单里用 -/+ 调节。");
			UseNativeSpectateMode = config.Bind<bool>("观战视角", "使用原生观战模式", false, "直接接管主相机显示单一观战目标(原版观战画质,全分辨率、无额外渲染开销)。同一时间只能观战一个目标,仅作监看、不代打。开启时会屏蔽原版切换观战目标的按键,请在菜单中点击“上一个/下一个”切换;接管期间角落的自身小窗仍可正常显示。");
			GhostVoiceInNativeSpectate = config.Bind<bool>("观战视角", "原生观战使用幽灵语音", false, "独立开关:原生观战接管期间为本机生成跟随目标的网络幽灵,使队友听到的语音位置与观战画面一致,便于与目标附近的队友正常对话;关闭(默认)时不生成任何幽灵,对方无法察觉你在观战。关闭、退出接管时会移除已生成的幽灵;本机完全昏死后原版自动生成幽灵,无需此开关。");
			DetailedLog = config.Bind<bool>("调试", "详细日志", false, "输出详细日志,便于排查问题。");
		}

		public static void Log(string message)
		{
			if (DetailedLog != null && DetailedLog.Value && Plugin.Logger != null)
			{
				Plugin.Logger.LogInfo((object)("[队友观战] " + message));
			}
		}

		public static void Info(string message)
		{
			if (Plugin.Logger != null)
			{
				Plugin.Logger.LogInfo((object)("[队友观战] " + message));
			}
		}

		public static void Warn(string message)
		{
			if (Plugin.Logger != null)
			{
				Plugin.Logger.LogWarning((object)("[队友观战] " + message));
			}
		}
	}
	internal static class MonitorModeState
	{
		public static bool Active;
	}
	internal sealed class NativeBarClone : IDisposable
	{
		private const float PadX = 2f;

		private const int MaxTexWidth = 4096;

		private readonly Transform _parent;

		private GameObject _camGo;

		private Camera _cam;

		private object _urpData;

		private RectTransform _canvasRect;

		private GameObject _barGo;

		private StaminaBar _sb;

		private BarAffliction[] _affs;

		private RenderTexture _rt;

		private Rect _uv;

		private float _aspect = 0.2f;

		private float _canvasW = 1f;

		private float _canvasH = 1f;

		private float _texW = 1f;

		private float _texH = 1f;

		private bool _ready;

		private bool _failed;

		private int _lastMeasureFrame = -8;

		private readonly Vector3[] _cornerBuf = (Vector3[])(object)new Vector3[4];

		private FieldInfo _invincibleField;

		public Texture Texture => (Texture)(object)_rt;

		public float Aspect => _aspect;

		public Rect Uv => _uv;

		public bool IsReady
		{
			get
			{
				if (_ready)
				{
					return (Object)(object)_sb != (Object)null;
				}
				return false;
			}
		}

		public NativeBarClone(Transform parent)
		{
			_parent = parent;
		}

		public void SetVisible(bool visible)
		{
			if ((Object)(object)_camGo != (Object)null && _camGo.activeSelf != visible)
			{
				_camGo.SetActive(visible);
			}
		}

		public bool Ensure()
		{
			if (IsReady)
			{
				return true;
			}
			if (_failed)
			{
				return false;
			}
			try
			{
				GUIManager instance = GUIManager.instance;
				StaminaBar val = (((Object)(object)instance != (Object)null) ? instance.bar : null);
				if ((Object)(object)val == (Object)null)
				{
					_failed = true;
					ModConfig.Log("原生状态条:HUD 尚未创建(GUIManager.bar 为空)");
					return false;
				}
				Transform val2 = (((Object)(object)((Component)val).transform.parent != (Object)null) ? ((Component)val).transform.parent : ((Component)val).transform);
				if (!Build(val2))
				{
					return false;
				}
				ModConfig.Warn("原生状态条渲染已建立:贴图 " + _texW + "x" + _texH + ",画布 " + _canvasW + "x" + _canvasH);
				return true;
			}
			catch (Exception ex)
			{
				_failed = true;
				ModConfig.Warn("原生状态条初始化失败:" + ex.Message);
				Dispose();
				return false;
			}
		}

		private bool Build(Transform group)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: Expected O, but got Unknown
			//IL_00d3: Unknown result type (might be due to invalid IL or missing references)
			//IL_0145: Unknown result type (might be due to invalid IL or missing references)
			//IL_014b: Expected O, but got Unknown
			//IL_0389: Unknown result type (might be due to invalid IL or missing references)
			//IL_0390: Unknown result type (might be due to invalid IL or missing references)
			//IL_03a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_03a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_03ee: Unknown result type (might be due to invalid IL or missing references)
			//IL_03f8: Expected O, but got Unknown
			//IL_0452: Unknown result type (might be due to invalid IL or missing references)
			//IL_046c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0486: Unknown result type (might be due to invalid IL or missing references)
			//IL_049c: Unknown result type (might be due to invalid IL or missing references)
			//IL_04ac: Unknown result type (might be due to invalid IL or missing references)
			//IL_04cb: Unknown result type (might be due to invalid IL or missing references)
			//IL_04e0: Unknown result type (might be due to invalid IL or missing references)
			//IL_04e5: Unknown result type (might be due to invalid IL or missing references)
			//IL_04f7: Unknown result type (might be due to invalid IL or missing references)
			//IL_0513: Unknown result type (might be due to invalid IL or missing references)
			//IL_052f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0541: Unknown result type (might be due to invalid IL or missing references)
			_camGo = new GameObject("TeamSpectate_NativeBarCam");
			((Object)_camGo).hideFlags = (HideFlags)61;
			_camGo.transform.SetParent(_parent, false);
			int num = LayerMask.NameToLayer("UI");
			int num2 = ((num >= 0) ? num : 0);
			_camGo.layer = num2;
			_cam = _camGo.AddComponent<Camera>();
			((Behaviour)_cam).enabled = true;
			_cam.orthographic = true;
			_cam.orthographicSize = 5f;
			_cam.nearClipPlane = 0.1f;
			_cam.farClipPlane = 100f;
			_cam.clearFlags = (CameraClearFlags)2;
			_cam.backgroundColor = new Color(0f, 0f, 0f, 0f);
			_cam.allowHDR = false;
			_cam.allowMSAA = false;
			_cam.stereoTargetEye = (StereoTargetEyeMask)0;
			_cam.cullingMask = 1 << num2;
			EnsureUrpCameraData(_cam);
			SetUrpBool(_urpData, "renderPostProcessing", value: false);
			SetUrpBool(_urpData, "renderShadows", value: false);
			GameObject val = new GameObject("TeamSpectate_NativeBarCanvas");
			((Object)val).hideFlags = (HideFlags)61;
			val.transform.SetParent(_camGo.transform, false);
			val.layer = num2;
			Canvas obj = val.AddComponent<Canvas>();
			obj.renderMode = (RenderMode)2;
			obj.overrideSorting = true;
			obj.sortingOrder = 30000;
			obj.scaleFactor = 1f;
			_canvasRect = val.GetComponent<RectTransform>();
			_barGo = Object.Instantiate<GameObject>(((Component)group).gameObject, (Transform)(object)_canvasRect, false);
			((Object)_barGo).name = "TeamSpectate_NativeBar";
			((Object)_barGo).hideFlags = (HideFlags)61;
			SetLayer(_barGo, num2);
			Strip(_barGo);
			_sb = _barGo.GetComponentInChildren<StaminaBar>(true);
			if ((Object)(object)_sb == (Object)null || (Object)(object)_sb.fullBar == (Object)null || (Object)(object)_sb.staminaBar == (Object)null || (Object)(object)_sb.maxStaminaBar == (Object)null)
			{
				_failed = true;
				ModConfig.Warn("原生状态条:克隆中未找到 StaminaBar 或其字段");
				Dispose();
				return false;
			}
			((Behaviour)_sb).enabled = false;
			_affs = _barGo.GetComponentsInChildren<BarAffliction>(true);
			BarAffliction[] affs = _affs;
			foreach (BarAffliction val2 in affs)
			{
				if ((Object)(object)val2 != (Object)null)
				{
					((Behaviour)val2).enabled = false;
				}
			}
			affs = _affs;
			foreach (BarAffliction val3 in affs)
			{
				if ((Object)(object)val3 != (Object)null)
				{
					((Component)val3).gameObject.SetActive(true);
				}
			}
			if ((Object)(object)_sb.extraBar != (Object)null)
			{
				((Component)_sb.extraBar).gameObject.SetActive(true);
			}
			if ((Object)(object)_sb.extraBarOutline != (Object)null)
			{
				((Component)_sb.extraBarOutline).gameObject.SetActive(true);
			}
			if ((Object)(object)_sb.extraBarStamina != (Object)null)
			{
				((Component)_sb.extraBarStamina).gameObject.SetActive(true);
			}
			Canvas.ForceUpdateCanvases();
			LayoutRebuilder.ForceRebuildLayoutImmediate(_canvasRect);
			ComputeBounds(out var min, out var max);
			float num3 = Mathf.Max(1f, max.x - min.x);
			int num4 = Mathf.Clamp(Mathf.CeilToInt(Mathf.Max(1f, max.y - min.y)) + 2, 8, 2048);
			int num5 = Mathf.Clamp(Mathf.CeilToInt(num3 * 6f) + 16, 512, 4096);
			_rt = new RenderTexture(num5, num4, 0, (RenderTextureFormat)0);
			((Object)_rt).hideFlags = (HideFlags)61;
			((Texture)_rt).filterMode = (FilterMode)1;
			_rt.Create();
			_cam.targetTexture = _rt;
			_cam.orthographicSize = (float)num4 * 0.5f;
			_canvasRect.anchorMin = new Vector2(0.5f, 0.5f);
			_canvasRect.anchorMax = new Vector2(0.5f, 0.5f);
			_canvasRect.pivot = new Vector2(0.5f, 0.5f);
			_canvasRect.sizeDelta = new Vector2((float)num5, (float)num4);
			((Transform)_canvasRect).localRotation = Quaternion.identity;
			((Transform)_canvasRect).localPosition = new Vector3(0f, 0f, 10f);
			Vector3 lossyScale = _camGo.transform.lossyScale;
			((Transform)_canvasRect).localScale = new Vector3(1f / Mathf.Max(0.0001f, Mathf.Abs(lossyScale.x)), 1f / Mathf.Max(0.0001f, Mathf.Abs(lossyScale.y)), 1f / Mathf.Max(0.0001f, Mathf.Abs(lossyScale.z)));
			Canvas.ForceUpdateCanvases();
			_texW = num5;
			_texH = num4;
			_canvasW = num5;
			_canvasH = num4;
			PlaceContent();
			_ready = true;
			return true;
		}

		private void PlaceContent()
		{
			//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_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: 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_0026: 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_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_0050: 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_0068: 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_0087: 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)
			//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)
			//IL_00c9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ce: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e9: Unknown result type (might be due to invalid IL or missing references)
			//IL_010e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0117: Unknown result type (might be due to invalid IL or missing references)
			//IL_011e: Unknown result type (might be due to invalid IL or missing references)
			RectTransform val = (RectTransform)_barGo.transform;
			val.anchorMin = Vector2.zero;
			val.anchorMax = Vector2.zero;
			val.pivot = Vector2.zero;
			val.anchoredPosition = Vector2.zero;
			Canvas.ForceUpdateCanvases();
			ComputeBounds(out var min, out var max);
			Mathf.Max(1f, max.x - min.x);
			float num = Mathf.Max(1f, max.y - min.y);
			Rect rect = _canvasRect.rect;
			_canvasW = Mathf.Max(1f, ((Rect)(ref rect)).width);
			rect = _canvasRect.rect;
			_canvasH = Mathf.Max(1f, ((Rect)(ref rect)).height);
			rect = _canvasRect.rect;
			float num2 = ((Rect)(ref rect)).xMin + 2f;
			rect = _canvasRect.rect;
			float num3 = ((Rect)(ref rect)).yMin + Mathf.Max(0f, (_canvasH - num) * 0.5f);
			val.anchoredPosition = new Vector2(num2 - min.x, num3 - min.y);
			Canvas.ForceUpdateCanvases();
		}

		private void ComputeBounds(out Vector2 min, out Vector2 max)
		{
			//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_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_019e: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b8: Unknown result type (might be due to invalid IL or missing references)
			min = new Vector2(float.MaxValue, float.MaxValue);
			max = new Vector2(float.MinValue, float.MinValue);
			Vector3[] cornerBuf = _cornerBuf;
			Include(_sb.fullBar, cornerBuf, ref min, ref max);
			Include(_sb.maxStaminaBar, cornerBuf, ref min, ref max);
			Include(_sb.staminaBarOutline, cornerBuf, ref min, ref max);
			Include(_sb.staminaBar, cornerBuf, ref min, ref max);
			if ((Object)(object)_sb.extraBar != (Object)null && ((Component)_sb.extraBar).gameObject.activeInHierarchy)
			{
				Include(_sb.extraBar, cornerBuf, ref min, ref max);
			}
			if ((Object)(object)_sb.extraBarOutline != (Object)null && ((Component)_sb.extraBarOutline).gameObject.activeInHierarchy)
			{
				Include(_sb.extraBarOutline, cornerBuf, ref min, ref max);
			}
			if ((Object)(object)_sb.extraBarStamina != (Object)null && ((Component)_sb.extraBarStamina).gameObject.activeInHierarchy)
			{
				Include(_sb.extraBarStamina, cornerBuf, ref min, ref max);
			}
			if (_affs != null)
			{
				BarAffliction[] affs = _affs;
				foreach (BarAffliction val in affs)
				{
					if ((Object)(object)val != (Object)null && (Object)(object)val.rtf != (Object)null && ((Component)val).gameObject.activeInHierarchy)
					{
						Include(val.rtf, cornerBuf, ref min, ref max);
					}
				}
			}
			if (min.x > max.x)
			{
				min = Vector2.zero;
				max = new Vector2(100f, 20f);
			}
		}

		private void Include(RectTransform rt, Vector3[] buf, ref Vector2 min, ref Vector2 max)
		{
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0045: 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_005f: 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)
			//IL_007b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0070: 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 ((Object)(object)rt == (Object)null)
			{
				return;
			}
			rt.GetWorldCorners(buf);
			for (int i = 0; i < 4; i++)
			{
				Vector3 val = ((Transform)_canvasRect).InverseTransformPoint(buf[i]);
				if (val.x < min.x)
				{
					min.x = val.x;
				}
				if (val.y < min.y)
				{
					min.y = val.y;
				}
				if (val.x > max.x)
				{
					max.x = val.x;
				}
				if (val.y > max.y)
				{
					max.y = val.y;
				}
			}
		}

		public void Render(Character c)
		{
			//IL_006a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0070: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a7: Unknown result type (might be due to invalid IL or missing references)
			if (!IsReady || (Object)(object)_rt == (Object)null || (Object)(object)c == (Object)null || ModConfig.ShowStatusOverlay == null || !ModConfig.ShowStatusOverlay.Value)
			{
				return;
			}
			try
			{
				Drive(c);
				if (Time.frameCount - _lastMeasureFrame >= 4)
				{
					_lastMeasureFrame = Time.frameCount;
					Canvas.ForceUpdateCanvases();
					ComputeBounds(out var min, out var max);
					float num = Mathf.Max(1f, max.x - min.x);
					float num2 = Mathf.Clamp01((2f + num) / _texW);
					_uv = new Rect(0f, 0f, num2, 1f);
					_aspect = _canvasH / Mathf.Max(1f, 2f + num);
				}
			}
			catch (Exception ex)
			{
				ModConfig.Log("原生状态条渲染失败:" + ex.Message);
			}
		}

		private void Drive(Character c)
		{
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_0191: Unknown result type (might be due to invalid IL or missing references)
			//IL_0196: Unknown result type (might be due to invalid IL or missing references)
			//IL_019a: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e7: Unknown result type (might be due to invalid IL or missing references)
			//IL_0213: Unknown result type (might be due to invalid IL or missing references)
			//IL_0218: Unknown result type (might be due to invalid IL or missing references)
			//IL_021c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0253: Unknown result type (might be due to invalid IL or missing references)
			//IL_026a: Unknown result type (might be due to invalid IL or missing references)
			//IL_02c8: Unknown result type (might be due to invalid IL or missing references)
			//IL_02d2: Unknown result type (might be due to invalid IL or missing references)
			//IL_0143: Unknown result type (might be due to invalid IL or missing references)
			//IL_0148: Unknown result type (might be due to invalid IL or missing references)
			//IL_014c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0167: Unknown result type (might be due to invalid IL or missing references)
			//IL_0115: 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_03af: Unknown result type (might be due to invalid IL or missing references)
			//IL_03f4: Unknown result type (might be due to invalid IL or missing references)
			//IL_03fe: Unknown result type (might be due to invalid IL or missing references)
			//IL_054b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0499: Unknown result type (might be due to invalid IL or missing references)
			//IL_04a3: Unknown result type (might be due to invalid IL or missing references)
			float num = Mathf.Min(Time.deltaTime * 10f, 0.1f);
			float num2 = Time.deltaTime * 10f;
			float num3 = Mathf.Max(1f, _sb.fullBar.sizeDelta.x);
			if (_affs != null)
			{
				BarAffliction[] affs = _affs;
				foreach (BarAffliction val in affs)
				{
					if ((Object)(object)val == (Object)null)
					{
						continue;
					}
					float num4;
					try
					{
						num4 = (val.isPetrify ? ((float)c.data.petrifyAmount / 100f) : c.refs.afflictions.GetCurrentStatus(val.afflictionType));
					}
					catch
					{
						num4 = 0f;
					}
					float num5 = num3 * num4;
					if (num4 > 0.01f)
					{
						if (num5 < _sb.minAfflictionWidth)
						{
							num5 = _sb.minAfflictionWidth;
						}
						if (!((Component)val).gameObject.activeSelf)
						{
							((Component)val).gameObject.SetActive(true);
							if ((Object)(object)val.icon != (Object)null)
							{
								((Component)val.icon).transform.localScale = Vector3.one;
							}
						}
					}
					else if (((Component)val).gameObject.activeSelf)
					{
						((Component)val).gameObject.SetActive(false);
					}
					Vector2 sizeDelta = val.rtf.sizeDelta;
					sizeDelta.x = Mathf.Lerp(sizeDelta.x, num5, num);
					val.rtf.sizeDelta = sizeDelta;
				}
			}
			float num6 = SafeGetStamina(c);
			Vector2 sizeDelta2 = _sb.staminaBar.sizeDelta;
			sizeDelta2.x = Mathf.Lerp(sizeDelta2.x, Mathf.Max(0f, num6 * num3 + _sb.staminaBarOffset), num2);
			_sb.staminaBar.sizeDelta = sizeDelta2;
			((Component)_sb.staminaBar).gameObject.SetActive(sizeDelta2.x > _sb.minStaminaBarWidth);
			float num7 = SafeGetMaxStamina(c);
			Vector2 sizeDelta3 = _sb.maxStaminaBar.sizeDelta;
			sizeDelta3.x = Mathf.Lerp(sizeDelta3.x, Mathf.Max(0f, num7 * num3 + _sb.staminaBarOffset), num2);
			_sb.maxStaminaBar.sizeDelta = sizeDelta3;
			((Component)_sb.maxStaminaBar).gameObject.SetActive(sizeDelta3.x > _sb.minStaminaBarWidth);
			float num8 = SafeGetStatusSum(c);
			if ((Object)(object)_sb.staminaBarOutline != (Object)null)
			{
				_sb.staminaBarOutline.sizeDelta = new Vector2(14f + Mathf.Max(1f, num8) * num3, _sb.staminaBarOutline.sizeDelta.y);
			}
			if ((Object)(object)_sb.staminaBarOutlineOverflowBar != (Object)null)
			{
				((Component)_sb.staminaBarOutlineOverflowBar).gameObject.SetActive(num8 > 1.005f);
			}
			bool flag = (Object)(object)_sb.petrifyAffliction != (Object)null && ((Component)_sb.petrifyAffliction).gameObject.activeSelf;
			float num9 = SafeGetExtraStamina(c);
			bool flag2 = num9 > 0f || flag;
			if ((Object)(object)_sb.extraBar != (Object)null && ((Component)_sb.extraBar).gameObject.activeSelf != flag2)
			{
				((Component)_sb.extraBar).gameObject.SetActive(flag2);
			}
			if (flag2)
			{
				_sb.extraBar.sizeDelta = new Vector2(45f, 45f);
				float num10 = Mathf.Max(0f, num9 * num3);
				if ((Object)(object)_sb.extraBarStamina != (Object)null)
				{
					_sb.extraBarStamina.sizeDelta = new Vector2(num10, _sb.extraBarStamina.sizeDelta.y);
					((Component)_sb.extraBarStamina).gameObject.SetActive(num10 > 6.1f);
				}
				if ((Object)(object)_sb.extraStaminaIcon != (Object)null)
				{
					((Component)_sb.extraStaminaIcon).gameObject.SetActive(num10 > 6.1f);
				}
				if ((Object)(object)_sb.extraBarOutline != (Object)null)
				{
					_sb.extraBarOutline.sizeDelta = new Vector2(Mathf.Max(20f, (flag ? num3 : num10) + 12f), _sb.extraBarOutline.sizeDelta.y);
				}
			}
			if ((Object)(object)_sb.shield != (Object)null)
			{
				_sb.shield.SetActive(SafeInvincible(c));
			}
			if ((Object)(object)_sb.campfire != (Object)null)
			{
				_sb.campfire.SetActive(!SafeCanGetHungry(c));
			}
			if ((Object)(object)_sb.rainbowStamina != (Object)null)
			{
				((Behaviour)_sb.rainbowStamina).enabled = false;
			}
			if ((Object)(object)_sb.backing != (Object)null)
			{
				((Graphic)_sb.backing).color = _sb.defaultBackingColor;
			}
		}

		private static float SafeGetStamina(Character c)
		{
			try
			{
				return c.data.currentStamina;
			}
			catch
			{
				return 0f;
			}
		}

		private static float SafeGetMaxStamina(Character c)
		{
			try
			{
				return c.GetMaxStamina();
			}
			catch
			{
				return 1f;
			}
		}

		private static float SafeGetStatusSum(Character c)
		{
			try
			{
				return c.refs.afflictions.statusSum;
			}
			catch
			{
				return 0f;
			}
		}

		private static float SafeGetExtraStamina(Character c)
		{
			try
			{
				return c.data.extraStamina;
			}
			catch
			{
				return 0f;
			}
		}

		private static bool SafeCanGetHungry(Character c)
		{
			try
			{
				return c.refs.afflictions.canGetHungry;
			}
			catch
			{
				return true;
			}
		}

		private bool SafeInvincible(Character c)
		{
			try
			{
				CharacterData val = (((Object)(object)c != (Object)null) ? c.data : null);
				if ((Object)(object)val == (Object)null)
				{
					return false;
				}
				if (_invincibleField == null)
				{
					_invincibleField = ((object)val).GetType().GetField("isInvincible", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
				}
				return _invincibleField != null && _invincibleField.FieldType == typeof(bool) && (bool)_invincibleField.GetValue(val);
			}
			catch
			{
				return false;
			}
		}

		private static void SetLayer(GameObject go, int layer)
		{
			go.layer = layer;
			Transform transform = go.transform;
			for (int i = 0; i < transform.childCount; i++)
			{
				SetLayer(((Component)transform.GetChild(i)).gameObject, layer);
			}
		}

		private static void Strip(GameObject go)
		{
			try
			{
				Canvas[] components = go.GetComponents<Canvas>();
				for (int i = 0; i < components.Length; i++)
				{
					Object.Destroy((Object)(object)components[i]);
				}
				CanvasScaler[] components2 = go.GetComponents<CanvasScaler>();
				for (int i = 0; i < components2.Length; i++)
				{
					Object.Destroy((Object)(object)components2[i]);
				}
				GraphicRaycaster[] components3 = go.GetComponents<GraphicRaycaster>();
				for (int i = 0; i < components3.Length; i++)
				{
					Object.Destroy((Object)(object)components3[i]);
				}
			}
			catch
			{
			}
		}

		private void EnsureUrpCameraData(Camera cam)
		{
			try
			{
				Type type = Type.GetType("UnityEngine.Rendering.Universal.UniversalAdditionalCameraData, Unity.RenderPipelines.Universal.Runtime");
				if (type == null)
				{
					Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies();
					for (int i = 0; i < assemblies.Length; i++)
					{
						type = assemblies[i].GetType("UnityEngine.Rendering.Universal.UniversalAdditionalCameraData", throwOnError: false);
						if (type != null)
						{
							break;
						}
					}
				}
				if (type != null)
				{
					if ((Object)(object)((Component)cam).gameObject.GetComponent(type) == (Object)null)
					{
						((Component)cam).gameObject.AddComponent(type);
					}
					_urpData = ((Component)cam).gameObject.GetComponent(type);
				}
			}
			catch (Exception ex)
			{
				ModConfig.Log("原生状态条补充 URP 相机数据失败:" + ex.Message);
			}
		}

		private static void SetUrpBool(object data, string property, bool value)
		{
			if (data == null)
			{
				return;
			}
			try
			{
				PropertyInfo property2 = data.GetType().GetProperty(property);
				if (property2 != null && property2.CanWrite)
				{
					property2.SetValue(data, value, null);
				}
			}
			catch
			{
			}
		}

		public void Dispose()
		{
			try
			{
				if ((Object)(object)_cam != (Object)null)
				{
					_cam.targetTexture = null;
				}
				if ((Object)(object)_barGo != (Object)null)
				{
					Object.Destroy((Object)(object)_barGo);
					_barGo = null;
				}
				if ((Object)(object)_rt != (Object)null)
				{
					_rt.Release();
					Object.Destroy((Object)(object)_rt);
					_rt = null;
				}
				if ((Object)(object)_camGo != (Object)null)
				{
					Object.Destroy((Object)(object)_camGo);
					_camGo = null;
				}
			}
			catch
			{
			}
			_sb = null;
			_affs = null;
			_ready = false;
		}
	}
	internal static class NativeGhostVoice
	{
		private static bool _spawnedByUs;

		public static void Tick()
		{
			//IL_010a: Unknown result type (might be due to invalid IL or missing references)
			//IL_010f: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				Character localCharacter = Character.localCharacter;
				if ((Object)(object)localCharacter == (Object)null || (Object)(object)localCharacter.data == (Object)null)
				{
					_spawnedByUs = false;
				}
				else if (!NativeSpectateController.Active || ModConfig.GhostVoiceInNativeSpectate == null || !ModConfig.GhostVoiceInNativeSpectate.Value || localCharacter.data.dead)
				{
					if (_spawnedByUs && (Object)(object)localCharacter.Ghost != (Object)null && !localCharacter.data.dead)
					{
						PhotonNetwork.Destroy(((Component)localCharacter.Ghost).gameObject);
						ModConfig.Info("幽灵语音:已移除观战幽灵。");
					}
					_spawnedByUs = false;
				}
				else if (!((Object)(object)localCharacter.Ghost != (Object)null) && PhotonNetwork.InRoom)
				{
					Character target = NativeSpectateController.Target;
					if (!((Object)(object)target == (Object)null) && target.refs != null && !((Object)(object)target.refs.view == (Object)null) && localCharacter.refs != null && !((Object)(object)localCharacter.refs.view == (Object)null))
					{
						PhotonNetwork.Instantiate("PlayerGhost", Vector3.zero, Quaternion.identity, (byte)0, (object[])null).GetComponent<PlayerGhost>().m_view.RPC("RPCA_InitGhost", (RpcTarget)3, new object[2]
						{
							localCharacter.refs.view,
							target.refs.view
						});
						_spawnedByUs = true;
						ModConfig.Info("幽灵语音:已生成观战幽灵(目标 " + SpectateTargets.GetDisplayName(target) + ")。");
					}
				}
			}
			catch (Exception ex)
			{
				ModConfig.Warn("幽灵语音异常:" + ex.Message);
			}
		}
	}
	internal static class NativeSpectateController
	{
		private static Character _target;

		private static Action<Character> _setSpecCharacter;

		private static bool _reflectionResolved;

		public static Character Target => _target;

		public static bool TargetValid
		{
			get
			{
				Character target = _target;
				if ((Object)(object)target != (Object)null)
				{
					return (Object)(object)target.data != (Object)null;
				}
				return false;
			}
		}

		public static bool LocalPassedOut
		{
			get
			{
				Character localCharacter = Character.localCharacter;
				if ((Object)(object)localCharacter != (Object)null && (Object)(object)localCharacter.data != (Object)null)
				{
					return localCharacter.data.fullyPassedOut;
				}
				return false;
			}
		}

		public static bool ControlActive
		{
			get
			{
				if (LocalPassedOut)
				{
					return true;
				}
				if (ModConfig.UseNativeSpectateMode != null)
				{
					return ModConfig.UseNativeSpectateMode.Value;
				}
				return false;
			}
		}

		public static bool Active
		{
			get
			{
				if (ControlActive)
				{
					return TargetValid;
				}
				return false;
			}
		}

		public static void ResolveReflection()
		{
			if (_reflectionResolved)
			{
				return;
			}
			_reflectionResolved = true;
			try
			{
				MethodInfo setter = AccessTools.PropertySetter(typeof(MainCameraMovement), "specCharacter");
				if (setter != null)
				{
					_setSpecCharacter = delegate(Character value)
					{
						setter.Invoke(null, new object[1] { value });
					};
					ModConfig.Info("原生观战:specCharacter 写入器解析成功(属性 setter)。");
					return;
				}
			}
			catch (Exception ex)
			{
				ModConfig.Warn("原生观战:解析 specCharacter 属性 setter 异常:" + ex.Message);
			}
			try
			{
				FieldInfo backing = AccessTools.Field(typeof(MainCameraMovement), "<specCharacter>k__BackingField");
				if (backing != null)
				{
					_setSpecCharacter = delegate(Character value)
					{
						backing.SetValue(null, value);
					};
					ModConfig.Info("原生观战:specCharacter 写入器解析成功(后备字段)。");
					return;
				}
			}
			catch (Exception ex2)
			{
				ModConfig.Warn("原生观战:解析 specCharacter 后备字段异常:" + ex2.Message);
			}
			ModConfig.Warn("原生观战:未找到 specCharacter 的写入器,原生观战将无法接管观战目标。");
		}

		internal static void EnforceTarget()
		{
			if (_setSpecCharacter == null)
			{
				ResolveReflection();
				if (_setSpecCharacter == null)
				{
					return;
				}
			}
			Character val = _target;
			if ((Object)(object)val == (Object)null || (Object)(object)val.data == (Object)null)
			{
				val = Character.localCharacter;
			}
			if (!((Object)(object)val == (Object)null))
			{
				_setSpecCharacter(val);
			}
		}

		public static void Toggle(Character target)
		{
			if (!((Object)(object)target == (Object)null))
			{
				_target = ((_target == target) ? null : target);
				LogTargetChange("切换观战目标");
			}
		}

		public static void Stop()
		{
			if (!((Object)(object)_target == (Object)null))
			{
				_target = null;
				ModConfig.Info("原生观战:已停止(目标清空)。");
			}
		}

		public static void SelectDefault()
		{
			if (TargetValid)
			{
				return;
			}
			List<Character> candidates = GetCandidates();
			if (candidates.Count == 0)
			{
				return;
			}
			Character localCharacter = Character.localCharacter;
			Character val = null;
			for (int i = 0; i < candidates.Count; i++)
			{
				if (candidates[i] != localCharacter)
				{
					val = candidates[i];
					break;
				}
			}
			if ((Object)(object)val == (Object)null)
			{
				val = candidates[0];
			}
			_target = val;
			LogTargetChange("自动选择观战目标");
		}

		public static void Next()
		{
			Shift(1);
		}

		public static void Prev()
		{
			Shift(-1);
		}

		private static void Shift(int direction)
		{
			List<Character> candidates = GetCandidates();
			if (candidates.Count == 0)
			{
				if ((Object)(object)_target != (Object)null)
				{
					_target = null;
					ModConfig.Info("原生观战:没有候选目标,已清空。");
				}
				return;
			}
			int index;
			if ((Object)(object)_target == (Object)null)
			{
				index = ((direction < 0) ? (candidates.Count - 1) : 0);
			}
			else
			{
				index = candidates.IndexOf(_target);
				index = ((index >= 0) ? ((index + direction + candidates.Count) % candidates.Count) : ((direction < 0) ? (candidates.Count - 1) : 0));
			}
			_target = candidates[index];
			LogTargetChange("切换观战目标");
		}

		public static void Validate()
		{
			Character target = _target;
			if ((Object)(object)target != (Object)null && (Object)(object)target.data == (Object)null)
			{
				_target = null;
				ModConfig.Info("原生观战:目标已失效,自动清空。");
			}
		}

		public static List<Character> GetCandidates()
		{
			List<Character> list = new List<Character>();
			List<Character> characters = SpectateTargets.GetCharacters();
			if (characters == null)
			{
				return list;
			}
			for (int i = 0; i < characters.Count; i++)
			{
				Character val = characters[i];
				if ((Object)(object)val != (Object)null && (Object)(object)val.data != (Object)null && !val.isBot)
				{
					list.Add(val);
				}
			}
			return list;
		}

		public static int GetCurrentIndex()
		{
			if ((Object)(object)_target == (Object)null)
			{
				return -1;
			}
			return GetCandidates().IndexOf(_target);
		}

		private static void LogTargetChange(string reason)
		{
			ModConfig.Info("原生观战:" + reason + " -> " + (((Object)(object)_target != (Object)null) ? SpectateTargets.GetDisplayName(_target) : "无") + ",Active=" + Active);
		}
	}
	internal static class OverlayBars
	{
		private const float BaseWidth = 1280f;

		private const float BaseHeight = 720f;

		private const int SlotCount = 8;

		private static readonly Color SlotEmpty = new Color(1f, 1f, 1f, 0.06f);

		private static readonly Color SlotFilled = new Color(0f, 0f, 0f, 0.55f);

		private static GUIStyle _itemStyle;

		private static readonly ItemSlot[] SharedSlots = (ItemSlot[])(object)new ItemSlot[8];

		private static readonly ItemSlot HeldSlot = new ItemSlot(byte.MaxValue);

		private static bool _slotPropsResolved;

		private static PropertyInfo _slotIsSome;

		private static PropertyInfo _slotValue;

		public static void Draw(Rect cell, Character c, SpectateView view)
		{
			//IL_0049: Unknown result type (might be due to invalid IL or missing references)
			if (ModConfig.ShowStatusOverlay == null || !ModConfig.ShowStatusOverlay.Value || (Object)(object)c == (Object)null || (Object)(object)c.data == (Object)null || ((Rect)(ref cell)).width < 40f || ((Rect)(ref cell)).height < 24f)
			{
				return;
			}
			try
			{
				DrawInner(cell, c, view);
			}
			catch (Exception ex)
			{
				ModConfig.Log("绘制状态叠加失败:" + ex.Message);
			}
		}

		private static void DrawInner(Rect cell, Character c, SpectateView view)
		{
			//IL_012e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0144: Unknown result type (might be due to invalid IL or missing references)
			//IL_0196: Unknown result type (might be due to invalid IL or missing references)
			//IL_0172: Unknown result type (might be due to invalid IL or missing references)
			//IL_017a: Unknown result type (might be due to invalid IL or missing references)
			float num = Mathf.Min(((Rect)(ref cell)).width / 1280f, ((Rect)(ref cell)).height / 720f);
			float num2 = ((ModConfig.OverlayScale != null) ? ModConfig.OverlayScale.Value : 1f);
			float num3 = Mathf.Max(0.02f, num * Mathf.Max(0.01f, num2));
			float num4 = 6f * num3;
			float num5 = 3f * num3;
			float num6 = 26f * num3;
			Texture val = view?.BarTexture;
			bool flag = (Object)(object)val != (Object)null;
			float num7 = Mathf.Min(((Rect)(ref cell)).width - num4 * 2f, 320f * num3);
			if (!(num7 < 32f * num3))
			{
				float num8 = 4f * num3;
				float num9 = num7 - num8 * 2f;
				float num10 = 0f;
				if (flag)
				{
					float barAspect = view.BarAspect;
					num10 = Mathf.Clamp(num9 * Mathf.Max(0.05f, barAspect), 10f, 140f * num3);
				}
				float num11 = num4 * 2f + num10 + num6;
				Rect rect = default(Rect);
				((Rect)(ref rect))..ctor(((Rect)(ref cell)).x + num4, ((Rect)(ref cell)).y + ((Rect)(ref cell)).height - num4 - num11, num7, num11);
				Fill(rect, new Color(0f, 0f, 0f, 0.55f));
				float num12 = ((Rect)(ref rect)).x + num8;
				float num13 = ((Rect)(ref rect)).y + num8;
				if (flag)
				{
					DrawNativeBar(new Rect(num12, num13, num9, num10), val, view.BarUv);
					num13 += num10 + num5;
				}
				DrawItems(new Rect(num12, num13, num9, num6), c, num3);
			}
		}

		private static void DrawNativeBar(Rect rect, Texture tex, Rect uv)
		{
			//IL_0026: 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)
			if (!((Object)(object)tex == (Object)null) && !(((Rect)(ref rect)).width <= 0f) && !(((Rect)(ref rect)).height <= 0f))
			{
				GUI.DrawTextureWithTexCoords(rect, tex, uv);
			}
		}

		private static void DrawItems(Rect row, Character c, float s)
		{
			//IL_00df: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ec: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f6: Unknown result type (might be due to invalid IL or missing references)
			//IL_0119: Unknown result type (might be due to invalid IL or missing references)
			//IL_0112: Unknown result type (might be due to invalid IL or missing references)
			//IL_0127: Unknown result type (might be due to invalid IL or missing references)
			Player player;
			try
			{
				player = c.player;
			}
			catch
			{
				return;
			}
			if ((Object)(object)player == (Object)null)
			{
				return;
			}
			byte selectedSlot = GetSelectedSlot(c);
			ItemSlot[] array = CollectSlots(player, c);
			float num = Mathf.Max(1f, 2f * s);
			float height = ((Rect)(ref row)).height;
			float border = Mathf.Max(1f, 1f * s);
			GUIStyle style = EnsureItemStyle(Mathf.RoundToInt(Mathf.Clamp(11f * s, 7f, 26f)));
			Rect rect = default(Rect);
			for (int i = 0; i < 8; i++)
			{
				((Rect)(ref rect))..ctor(((Rect)(ref row)).x + (float)i * (height + num), ((Rect)(ref row)).y, height, ((Rect)(ref row)).height);
				ItemSlot val = array[i];
				bool flag = val == null || val.IsEmpty();
				bool flag2 = !flag && (i == 3 || (val != null && val.itemSlotID == selectedSlot));
				Fill(rect, flag ? SlotEmpty : SlotFilled);
				DrawOutline(rect, border, (Color)(flag2 ? MenuTheme.Accent : new Color(1f, 1f, 1f, 0.35f)));
				if (!flag)
				{
					DrawSlotContent(rect, border, val, style);
				}
			}
		}

		private static ItemSlot[] CollectSlots(Player player, Character c)
		{
			ItemSlot[] sharedSlots = SharedSlots;
			for (int i = 0; i < 8; i++)
			{
				sharedSlots[i] = null;
			}
			ItemSlot[] itemSlots = player.itemSlots;
			for (int j = 0; j < 3; j++)
			{
				sharedSlots[j] = ((itemSlots != null && j < itemSlots.Length) ? itemSlots[j] : null);
			}
			Item val = (((Object)(object)c.data != (Object)null) ? c.data.currentItem : null);
			if ((Object)(object)val != (Object)null)
			{
				HeldSlot.SetItem(val, (ItemInstanceData)null);
				sharedSlots[3] = HeldSlot;
			}
			ItemSlot backpackSlot = (ItemSlot)(object)player.backpackSlot;
			BackpackData val2 = default(BackpackData);
			if (backpackSlot != null && !backpackSlot.IsEmpty() && backpackSlot.data != null && backpackSlot.data.TryGetDataEntry<BackpackData>((DataEntryKey)7, ref val2) && val2 != null && val2.itemSlots != null)
			{
				for (int k = 0; k < 4; k++)
				{
					sharedSlots[4 + k] = ((k < val2.itemSlots.Length) ? val2.itemSlots[k] : null);
				}
			}
			return sharedSlots;
		}

		private static void DrawSlotContent(Rect rect, float border, ItemSlot slot, GUIStyle style)
		{
			//IL_007f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0075: Unknown result type (might be due to invalid IL or missing references)
			Rect val = default(Rect);
			((Rect)(ref val))..ctor(((Rect)(ref rect)).x + border, ((Rect)(ref rect)).y + border, ((Rect)(ref rect)).width - border * 2f, ((Rect)(ref rect)).height - border * 2f);
			Texture2D val2 = null;
			try
			{
				if ((Object)(object)slot.prefab != (Object)null && slot.prefab.UIData != null)
				{
					val2 = slot.prefab.UIData.GetIcon();
				}
			}
			catch
			{
				val2 = null;
			}
			if ((Object)(object)val2 != (Object)null)
			{
				GUI.DrawTexture(val, (Texture)(object)val2, (ScaleMode)2, true);
			}
			else
			{
				GUI.Label(val, GetItemName(slot), style);
			}
		}

		private static GUIStyle EnsureItemStyle(int fontSize)
		{
			//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_0018: 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_002b: Expected O, but got Unknown
			if (_itemStyle == null)
			{
				_itemStyle = new GUIStyle(MenuTheme.Small)
				{
					alignment = (TextAnchor)4,
					clipping = (TextClipping)1,
					wordWrap = false
				};
			}
			_itemStyle.fontSize = fontSize;
			return _itemStyle;
		}

		private static byte GetSelectedSlot(Character c)
		{
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				if (c.refs == null || (Object)(object)c.refs.items == (Object)null)
				{
					return byte.MaxValue;
				}
				object obj = c.refs.items.currentSelectedSlot;
				if (obj == null)
				{
					return byte.MaxValue;
				}
				if (!_slotPropsResolved)
				{
					_slotPropsResolved = true;
					Type type = obj.GetType();
					_slotIsSome = type.GetProperty("IsSome");
					_slotValue = type.GetProperty("Value");
				}
				if (_slotIsSome != null && _slotValue != null && (bool)_slotIsSome.GetValue(obj, null))
				{
					return Convert.ToByte(_slotValue.GetValue(obj, null));
				}
			}
			catch
			{
			}
			return byte.MaxValue;
		}

		private static string GetItemName(ItemSlot slot)
		{
			try
			{
				if (slot != null && (Object)(object)slot.prefab != (Object)null)
				{
					return slot.prefab.GetName();
				}
			}
			catch
			{
			}
			return "?";
		}

		private static void DrawOutline(Rect rect, float border, Color color)
		{
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_005a: Unknown result type (might be due to invalid IL or missing references)
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_007d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0082: Unknown result type (might be due to invalid IL or missing references)
			Fill(new Rect(((Rect)(ref rect)).x, ((Rect)(ref rect)).y, ((Rect)(ref rect)).width, border), color);
			Fill(new Rect(((Rect)(ref rect)).x, ((Rect)(ref rect)).yMax - border, ((Rect)(ref rect)).width, border), color);
			Fill(new Rect(((Rect)(ref rect)).x, ((Rect)(ref rect)).y, border, ((Rect)(ref rect)).height), color);
			Fill(new Rect(((Rect)(ref rect)).xMax - border, ((Rect)(ref rect)).y, border, ((Rect)(ref rect)).height), color);
		}

		private static void Fill(Rect rect, Color color)
		{
			//IL_001d: 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_0028: Unknown result type (might be due to invalid IL or missing references)
			if (!(((Rect)(ref rect)).width <= 0f) && !(((Rect)(ref rect)).height <= 0f))
			{
				Color color2 = GUI.color;
				GUI.color = color;
				GUI.DrawTexture(rect, (Texture)(object)Texture2D.whiteTexture);
				GUI.color = color2;
			}
		}
	}
	internal static class NativeSpectatePatches
	{
		private static CharacterData _forcedData;

		[HarmonyPatch(typeof(MainCameraMovement), "LateUpdate")]
		[HarmonyPrefix]
		internal static void LateUpdateForcePrefix()
		{
			_forcedData = null;
			if (NativeSpectateController.Active)
			{
				Character localCharacter = Character.localCharacter;
				if (!((Object)(object)localCharacter == (Object)null) && !((Object)(object)localCharacter.data == (Object)null) && !localCharacter.data.fullyPassedOut)
				{
					_forcedData = localCharacter.data;
					localCharacter.data.fullyPassedOut = true;
				}
			}
		}

		[HarmonyPatch(typeof(MainCameraMovement), "LateUpdate")]
		[HarmonyPostfix]
		internal static void LateUpdateRestorePostfix()
		{
			if (!((Object)(object)_forcedData == (Object)null))
			{
				_forcedData.fullyPassedOut = false;
				_forcedData = null;
			}
		}

		[HarmonyPatch(typeof(MainCameraMovement), "HandleSpecSelection")]
		[HarmonyPrefix]
		internal static bool HandleSpecSelectionPrefix(ref bool __result)
		{
			if (!NativeSpectateController.Active)
			{
				return true;
			}
			NativeSpectateController.EnforceTarget();
			if ((Object)(object)MainCameraMovement.specCharacter == (Object)null)
			{
				ModConfig.Warn("原生观战:强制写入 specCharacter 后仍为 null,回退原版取目标逻辑。");
				return true;
			}
			__result = true;
			return false;
		}

		[HarmonyPatch(typeof(CharacterInput), "Sample")]
		[HarmonyPostfix]
		internal static void SamplePostfix(CharacterInput __instance)
		{
			//IL_0032: 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_0057: Unknown result type (might be due to invalid IL or missing references)
			//IL_005c: Unknown result type (might be due to invalid IL or missing references)
			//IL_011f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0120: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)__instance == (Object)null) && NativeSpectateController.Active && !NativeSpectateController.LocalPassedOut)
			{
				Character localCharacter = Character.localCharacter;
				if (!((Object)(object)localCharacter == (Object)null) && localCharacter.input == __instance)
				{
					Vector2 lookInput = __instance.lookInput;
					float scrollInput = __instance.scrollInput;
					bool pauseWasPressed = __instance.pauseWasPressed;
					bool pushToTalkPressed = __instance.pushToTalkPressed;
					bool pingWasPressed = __instance.pingWasPressed;
					__instance.movementInput = Vector2.zero;
					__instance.jumpWasPressed = false;
					__instance.jumpIsPressed = false;
					__instance.sprintWasPressed = false;
					__instance.sprintIsPressed = false;
					__instance.sprintToggleIsPressed = false;
					__instance.sprintToggleWasPressed = false;
					__instance.crouchWasPressed = false;
					__instance.crouchIsPressed = false;
					__instance.crouchToggleWasPressed = false;
					__instance.usePrimaryWasPressed = false;
					__instance.usePrimaryIsPressed = false;
					__instance.usePrimaryWasReleased = false;
					__instance.useSecondaryWasPressed = false;
					__instance.useSecondaryIsPressed = false;
					__instance.useSecondaryWasReleased = false;
					__instance.dropWasPressed = false;
					__instance.dropIsPressed = false;
					__instance.dropWasReleased = false;
					__instance.interactWasPressed = false;
					__instance.interactIsPressed = false;
					__instance.interactWasReleased = false;
					__instance.selectSlotForwardWasPressed = false;
					__instance.selectSlotBackwardWasPressed = false;
					__instance.unselectSlotWasPressed = false;
					__instance.selectBackpackWasPressed = false;
					__instance.spectateLeftWasPressed = false;
					__instance.spectateRightWasPressed = false;
					__instance.lookInput = lookInput;
					__instance.scrollInput = scrollInput;
					__instance.pauseWasPressed = pauseWasPressed;
					__instance.pushToTalkPressed = pushToTalkPressed;
					__instance.pingWasPressed = pingWasPressed;
				}
			}
		}

		[HarmonyPatch(typeof(GUIManager), "UpdateSpectate")]
		[HarmonyPostfix]
		internal static void UpdateSpectatePostfix(GUIManager __instance)
		{
			if (!((Object)(object)__instance == (Object)null) && !((Object)(object)__instance.spectatingObject == (Object)null) && NativeSpectateController.Active && !__instance.spectatingObject.activeSelf)
			{
				__instance.spectatingObject.SetActive(true);
			}
		}
	}
	internal static class PatchAudit
	{
		internal static void Run()
		{
			Report(typeof(MainCameraMovement), "LateUpdate");
			Report(typeof(MainCameraMovement), "HandleSpecSelection");
			Report(typeof(CharacterInput), "Sample");
			Report(typeof(GUIManager), "UpdateSpectate");
			Report(typeof(CharacterVoiceHandler), "Update");
			Report(typeof(VoiceObscuranceFilter), "Update");
		}

		private static void Report(Type type, string methodName)
		{
			MethodInfo methodInfo;
			try
			{
				methodInfo = AccessTools.Method(type, methodName, (Type[])null, (Type[])null);
			}
			catch (Exception ex)
			{
				ModConfig.Warn("补丁校验:" + type.Name + "." + methodName + " 解析异常:" + ex.Message);
				return;
			}
			if (methodInfo == null)
			{
				ModConfig.Warn("补丁校验:" + type.Name + "." + methodName + " 未找到,相关功能不可用。");
				return;
			}
			Patches patchInfo = Harmony.GetPatchInfo((MethodBase)methodInfo);
			List<string> list = new List<string>();
			if (patchInfo != null)
			{
				Collect(list, patchInfo.Prefixes);
				Collect(list, patchInfo.Postfixes);
				Collect(list, patchInfo.Transpilers);
			}
			bool flag = list.Contains("TeamSpectate");
			string text = ((list.Count == 0) ? "无" : string.Join("、", list));
			string message = "补丁校验:" + type.Name + "." + methodName + " -> " + (flag ? "已挂载" : "未挂载") + "(" + text + ")";
			if (flag)
			{
				ModConfig.Info(message);
			}
			else
			{
				ModConfig.Warn(message);
			}
		}

		private static void Collect(List<string> owners, IEnumerable<Patch> patches)
		{
			foreach (Patch patch in patches)
			{
				if (!owners.Contains(patch.owner))
				{
					owners.Add(patch.owner);
				}
			}
		}
	}
	internal static class VoiceCallPatches
	{
		private sealed class HandlerCache
		{
			public Character Character;

			public AudioSource Source;

			public Recorder Recorder;
		}

		private static readonly ConditionalWeakTable<CharacterVoiceHandler, HandlerCache> Cache = new ConditionalWeakTable<CharacterVoiceHandler, HandlerCache>();

		private static bool _forcedTransmit;

		private static Recorder _forcedRecorder;

		private static CharacterVoiceHandler _forcedHandler;

		private static FieldRef<CharacterVoiceHandler, bool> _transmittingRef;

		private static FieldRef<CharacterVoiceHandler, bool> _allowedRef;

		private static FieldRef<CharacterVoiceHandler, CharacterData> _charDataRef;

		private static FieldRef<VoiceObscuranceFilter, CharacterVoiceHandler> _filterHandlerRef;

		private static bool _refWarned;

		internal static void ResolveReflection()
		{
			try
			{
				_transmittingRef = AccessTools.FieldRefAccess<CharacterVoiceHandler, bool>("m_currentlyTransmitting");
			}
			catch (Exception e)
			{
				WarnRef("m_currentlyTransmitting", e);
			}
			try
			{
				_allowedRef = AccessTools.FieldRefAccess<CharacterVoiceHandler, bool>("m_allowedToCommunicate");
			}
			catch (Exception e2)
			{
				WarnRef("m_allowedToCommunicate", e2);
			}
			try
			{
				_charDataRef = AccessTools.FieldRefAccess<CharacterVoiceHandler, CharacterData>("m_characterData");
			}
			catch (Exception e3)
			{
				WarnRef("m_characterData", e3);
			}
			try
			{
				_filterHandlerRef = AccessTools.FieldRefAccess<VoiceObscuranceFilter, CharacterVoiceHandler>("_voiceHandler");
			}
			catch (Exception e4)
			{
				WarnRef("_voiceHandler", e4);
			}
		}

		private static void WarnRef(string field, Exception e)
		{
			if (!_refWarned)
			{
				_refWarned = true;
				ModConfig.Warn("通话字段访问器解析失败(" + field + "):" + e.Message);
			}
		}

		private static HandlerCache GetCache(CharacterVoiceHandler handler)
		{
			HandlerCache orCreateValue = Cache.GetOrCreateValue(handler);
			if ((Object)(object)orCreateValue.Character == (Object)null)
			{
				orCreateValue.Character = ((Component)handler).GetComponentInParent<Character>();
			}
			if ((Object)(object)orCreateValue.Source == (Object)null)
			{
				orCreateValue.Source = ((Component)handler).GetComponent<AudioSource>();
			}
			return orCreateValue;
		}

		[HarmonyPatch(typeof(CharacterVoiceHandler), "Update")]
		[HarmonyPostfix]
		private static void UpdatePostfix(CharacterVoiceHandler __instance)
		{
			if ((Object)(object)__instance == (Object)null)
			{
				return;
			}
			VoiceCall.Validate();
			if (!VoiceCall.Any)
			{
				if (_forcedTransmit)
				{
					RestoreLocalTransmit();
				}
				return;
			}
			try
			{
				HandlerCache cache = GetCache(__instance);
				Character character = cache.Character;
				if ((Object)(object)character == (Object)null)
				{
					return;
				}
				if (character.IsLocal)
				{
					if (AllowedToForce(__instance))
					{
						if ((Object)(object)cache.Recorder == (Object)null)
						{
							cache.Recorder = ((Component)__instance).GetComponent<Recorder>();
						}
						if ((Object)(object)cache.Recorder != (Object)null)
						{
							cache.Recorder.TransmitEnabled = true;
							__instance.transmitting = true;
							_forcedTransmit = true;
							_forcedRecorder = cache.Recorder;
							_forcedHandler = __instance;
						}
						if ((Object)(object)cache.Source != (Object)null)
						{
							cache.Source.mute = false;
						}
					}
				}
				else if (VoiceCall.IsCalling(character) && (Object)(object)cache.Source != (Object)null)
				{
					cache.Source.spatialBlend = 0f;
					cache.Source.volume = PlayerVolume(character);
					cache.Source.mute = false;
				}
			}
			catch (Exception ex)
			{
				ModConfig.Log("通话补丁异常:" + ex.Message);
			}
		}

		private static void RestoreLocalTransmit()
		{
			_forcedTransmit = false;
			try
			{
				if ((Object)(object)_forcedRecorder != (Object)null)
				{
					_forcedRecorder.TransmitEnabled = false;
				}
				if ((Object)(object)_forcedHandler != (Object)null && _transmittingRef != null)
				{
					_transmittingRef.Invoke(_forcedHandler) = false;
				}
			}
			catch (Exception ex)
			{
				ModConfig.Log("挂断还原异常:" + ex.Message);
			}
			finally
			{
				_forcedRecorder = null;
				_forcedHandler = null;
			}
		}

		private static bool AllowedToForce(CharacterVoiceHandler handler)
		{
			if (_allowedRef == null || _charDataRef == null)
			{
				return true;
			}
			try
			{
				if (!_allowedRef.Invoke(handler))
				{
					return false;
				}
				CharacterData val = _charDataRef.Invoke(handler);
				return (Object)(object)val == (Object)null || !val.isBlocked;
			}
			catch (Exception e)
			{
				WarnRef("m_allowedToCommunicate", e);
				return true;
			}
		}

		private static float PlayerVolume(Character c)
		{
			try
			{
				PhotonView photonView = ((MonoBehaviourPun)c).photonView;
				if ((Object)(object)photonView != (Object)null && photonView.Owner != null && AudioLevels.PlayerAudioLevels.TryGetValue(photonView.Owner.UserId, out var value))
				{
					return value;
				}
			}
			catch (Exception ex)
			{
				ModConfig.Log("读取音量设置失败:" + ex.Message);
			}
			return 0.5f;
		}

		[HarmonyPatch(typeof(VoiceObscuranceFilter), "Update")]
		[HarmonyPostfix]
		private static void ObscurancePostfix(VoiceObscuranceFilter __instance)
		{
			if (!VoiceCall.Any || (Object)(object)__instance == (Object)null || _filterHandlerRef == null)
			{
				return;
			}
			try
			{
				CharacterVoiceHandler val = _filterHandlerRef.Invoke(__instance);
				if ((Object)(object)val == (Object)null)
				{
					return;
				}
				HandlerCache cache = GetCache(val);
				if (!((Object)(object)cache.Character == (Object)null) && VoiceCall.IsCalling(cache.Character))
				{
					if ((Object)(object)__instance.lowPass != (Object)null)
					{
						__instance.lowPass.cutoffFrequency = 7500f;
						__instance.lowPass.lowpassResonanceQ = 1f;
					}
					if ((Object)(object)__instance.highPass != (Object)null)
					{
						__instance.highPass.cutoffFrequency = 10f;
					}
					if ((Object)(object)__instance.echo != (Object)null)
					{
						__instance.echo.wetMix = 0f;
						__instance.echo.dryMix = 1f;
						__instance.echo.decayRatio = 0f;
						__instance.echo.delay = 10f;
					}
				}
			}
			catch (Exception ex)
			{
				ModConfig.Log("通话滤镜补丁异常:" + ex.Message);
			}
		}
	}
	[BepInPlugin("TeamSpectate", "队友观战", "1.0.0")]
	public sealed class Plugin : BaseUnityPlugin
	{
		private GameObject _host;

		private Harmony _harmony;

		internal static ManualLogSource Logger { get; private set; }

		private void Awake()
		{
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: Expected O, but got Unknown
			//IL_0065: Unknown result type (might be due to invalid IL or missing references)
			//IL_006f: Expected O, but got Unknown
			//IL_00c4: Unknown result type (might be due to invalid IL or missing references)
			Logger = ((BaseUnityPlugin)this).Logger;
			ModConfig.Init(((BaseUnityPlugin)this).Config);
			_harmony = new Harmony("TeamSpectate");
			_harmony.PatchAll(typeof(NativeSpectatePatches));
			_harmony.PatchAll(typeof(VoiceCallPatches));
			NativeSpectateController.ResolveReflection();
			VoiceCallPatches.ResolveReflection();
			PatchAudit.Run();
			_host = new GameObject("TeamSpectate_Host");
			((Object)_host).hideFlags = (HideFlags)61;
			Object.DontDestroyOnLoad((Object)(object)_host);
			_host.AddComponent<SpectateGrid>();
			_host.AddComponent<SpectateMenu>();
			SpectateMenuWindow.Create(_host);
			Logger.LogInfo((object)string.Format("[队友观战] {0} v{1} 已加载,按 {2} 打开菜单。", "队友观战", "1.0.0", ModConfig.MenuKey.Value));
		}
	}
	internal static class PluginInfo
	{
		public const string PLUGIN_GUID = "TeamSpectate";

		public const string PLUGIN_NAME = "队友观战";

		public const string PLUGIN_VERSION = "1.0.0";
	}
	internal sealed class SpectateGrid : MonoBehaviour
	{
		private sealed class WatchSlot
		{
			public int SlotId;

			public int ViewId;
		}

		private sealed class Cell
		{
			public int Id;

			public Character Target;

			public string Label;

			public Rect Rect;

			public SpectateView View;

			public string LabelName;

			public string LabelId;

			public bool LabelLocal;
		}

		private const int SelfWindowId = 952702;

		private readonly List<WatchSlot> _watched = new List<WatchSlot>();

		private int _nextSlotId = 1;

		private readonly Dictionary<int, SpectateView> _views = new Dictionary<int, SpectateView>();

		private readonly List<Cell> _gridCells = new List<Cell>();

		private readonly List<Character> _charList = new List<Character>();

		private readonly Dictionary<int, Character> _charsById = new Dictionary<int, Character>();

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

		private readonly Dictionary<int, Cell> _cellPool = new Dictionary<int, Cell>();

		private readonly WindowLayout _layout = new WindowLayout();

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

		private readonly List<Rect> _inputRects = new List<Rect>();

		private SpectateView _selfView;

		private Rect _selfRect;

		private bool _selfVisible;

		private bool _selfRectInitialized;

		private bool _selfResizing;

		private Vector2 _resizeStartMouse;

		private Vector2 _resizeStartSize;

		public static SpectateGrid Instance { get; private set; }

		private static bool IsNativeMode => NativeSpectateController.ControlActive;

		public int WatchedCount
		{
			get
			{
				if (!IsNativeMode)
				{
					return _watched.Count;
				}
				return ((Object)(object)NativeSpectateController.Target != (Object)null) ? 1 : 0;
			}
		}

		public int SelfWindowCount
		{
			get
			{
				int viewId = SpectateTargets.GetViewId(Character.localCharacter);
				if (viewId == 0)
				{
					return 0;
				}
				int num = 0;
				for (int i = 0; i < _watched.Count; i++)
				{
					if (_watched[i].ViewId == viewId)
					{
						num++;
					}
				}
				return num;
			}
		}

		private void Awake()
		{
			Instance = this;
		}

		private void Update()
		{
			//IL_006a: Unknown result type (might be due to invalid IL or missing references)
			MonitorModeState.Active = ModConfig.MonitorOnly;
			if (MonitorModeState.Active && _gridCells.Count > 0)
			{
				_inputIds.Clear();
				_inputRects.Clear();
				for (int i = 0; i < _gridCells.Count; i++)
				{
					_inputIds.Add(_gridCells[i].Id);
					_inputRects.Add(_gridCells[i].Rect);
				}
				_layout.ProcessInput(_inputIds, _inputRects);
			}
			if (IsNativeMode)
			{
				NativeSpectateController.Validate();
			}
			NativeGhostVoice.Tick();
			bool active = NativeSpectateController.Active;
			if (active != ModConfig.NativeSpectateWasActive)
			{
				ModConfig.NativeSpectateWasActive = active;
				ModConfig.Info("原生观战:Active -> " + active + "(ControlActive=" + NativeSpectateController.ControlActive + ",目标=" + (((Object)(object)NativeSpectateController.Target != (Object)null) ? SpectateTargets.GetDisplayName(NativeSpectateController.Target) : "无") + ",昏死=" + NativeSpectateController.LocalPassedOut + ")");
			}
		}

		private void OnDestroy()
		{
			if ((Object)(object)Instance == (Object)(object)this)
			{
				Instance = null;
			}
			foreach (SpectateView value in _views.Values)
			{
				value.Dispose();
			}
			_views.Clear();
			if (_selfView != null)
			{
				_selfView.Dispose();
				_selfView = null;
			}
		}

		public bool IsWatched(int viewId)
		{
			if (IsNativeMode)
			{
				Character target = NativeSpectateController.Target;
				if ((Object)(object)target != (Object)null)
				{
					return SpectateTargets.GetViewId(target) == viewId;
				}
				return false;
			}
			return IndexOfView(viewId) >= 0;
		}

		public bool ToggleWatch(Character c)
		{
			int viewId = SpectateTargets.GetViewId(c);
			if (viewId == 0)
			{
				return false;
			}
			if (IsNativeMode)
			{
				NativeSpectateController.Toggle(c);
				return true;
			}
			int num = IndexOfView(viewId);
			if (num >= 0)
			{
				RemoveSlotAt(num, retile: true);
				ModConfig.Log("停止观战 " + SpectateTargets.GetDisplayName(c));
				return true;
			}
			AddSlot(viewId);
			ModConfig.Log($"开始观战 {SpectateTargets.GetDisplayName(c)} (id={viewId}, watchedCount={_watched.Count})");
			return true;
		}

		public bool AddSelfWindow()
		{
			if (IsNativeMode)
			{
				return false;
			}
			int viewId = SpectateTargets.GetViewId(Character.localCharacter);
			if (viewId == 0)
			{
				return false;
			}
			AddSlot(viewId);
			return true;
		}

		public bool RemoveSelfWindow()
		{
			int viewId = SpectateTargets.GetViewId(Character.localCharacter);
			if (viewId == 0)
			{
				return false;
			}
			for (int num = _watched.Count - 1; num >= 0; num--)
			{
				if (_watched[num].ViewId == viewId)
				{
					RemoveSlotAt(num, retile: true);
					return true;
				}
			}
			return false;
		}

		public void ClearAll()
		{
			_watched.Clear();
			_layout.Clear();
			NativeSpectateController.Stop();
		}

		public void ResetLayout()
		{
			_layout.Clear();
			_selfRectInitialized = false;
			if (ModConfig.SelfWindowX != null)
			{
				ModConfig.SelfWindowX.Value = -1f;
			}
			if (ModConfig.SelfWindowY != null)
			{
				ModConfig.SelfWindowY.Value = -1f;
			}
			ModConfig.Log("已重置所有窗口的位置与大小。");
		}

		public int WatchAll()
		{
			if (IsNativeMode)
			{
				return 0;
			}
			List<Character> characters = SpectateTargets.GetCharacters();
			int num = 0;
			for (int i = 0; i < characters.Count; i++)
			{
				Character val = characters[i];
				if (!((Object)(object)val == (Object)null) && !val.isBot)
				{
					int viewId = SpectateTargets.GetViewId(val);
					if (viewId != 0 && IndexOfView(viewId) < 0)
					{
						AddSlot(viewId);
						num++;
					}
				}
			}
			ModConfig.Log("观战全部队友,新增 " + num + " 人。");
			return num;
		}

		private int IndexOfView(int viewId)
		{
			for (int i = 0; i < _watched.Count; i++)
			{
				if (_watched[i].ViewId == viewId)
				{
					return i;
				}
			}
			return -1;
		}

		private void AddSlot(int viewId)
		{
			_watched.Add(new WatchSlot
			{
				SlotId = _nextSlotId++,
				ViewId = viewId
			});
			_layout.Clear();
		}

		private void RemoveSlotAt(int index, bool retile)
		{
			int slotId = _watched[index].SlotId;
			_watched.RemoveAt(index);
			ReleaseView(slotId);
			_layout.Remove(slotId);
			if (retile)
			{
				_layout.Clear();
			}
		}

		private void LateUpdate()
		{
			try
			{
				RebuildViews();
			}
			catch (Exception ex)
			{
				ModConfig.Log("更新观战画面失败:" + ex.Message);
			}
		}

		private void RebuildViews()
		{
			//IL_0404: Unknown result type (might be due to invalid IL or missing references)
			//IL_0406: Unknown result type (might be due to invalid IL or missing references)
			//IL_0279: Unknown result type (might be due to invalid IL or missing references)
			//IL_027b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0280: Unknown result type (might be due to invalid IL or missing references)
			//IL_0386: Unknown result type (might be due to invalid IL or missing references)
			//IL_0388: Unknown result type (might be due to invalid IL or missing references)
			List<Character> list = SpectateTargets.FillCharacters(_charList);
			Dictionary<int, Character> charsById = _charsById;
			charsById.Clear();
			for (int i = 0; i < list.Count; i++)
			{
				int viewId = SpectateTargets.GetViewId(list[i]);
				if (viewId != 0)
				{
					charsById[viewId] = list[i];
				}
			}
			if (IsNativeMode)
			{
				NativeSpectateController.Validate();
				foreach (SpectateView value6 in _views.Values)
				{
					value6.Hide();
				}
				_gridCells.Clear();
				UpdateSelfView(ModConfig.SpectateZoom.Value, ModConfig.FieldOfView.Value, ModConfig.ResolutionScale.Value);
				return;
			}
			NativeSpectateController.Stop();
			for (int num = _watched.Count - 1; num >= 0; num--)
			{
				if (!charsById.ContainsKey(_watched[num].ViewId))
				{
					RemoveSlotAt(num, retile: false);
				}
			}
			for (int j = 0; j < _gridCells.Count; j++)
			{
				_cellPool[_gridCells[j].Id] = _gridCells[j];
			}
			_gridCells.Clear();
			HashSet<int> usedSlots = _usedSlots;
			usedSlots.Clear();
			int count = _watched.Count;
			if (count > 0)
			{
				float num2 = 0f;
				float num3 = 0f;
				float num4 = Screen.width;
				float num5 = Screen.height;
				int num6 = Mathf.Clamp(Mathf.CeilToInt(Mathf.Sqrt((float)count)), 1, count);
				int num7 = Mathf.CeilToInt((float)count / (float)num6);
				float num8 = (num4 - 2f * num2 - (float)(num6 - 1) * num3) / (float)num6;
				float num9 = (num5 - 2f * num2 - (float)(num7 - 1) * num3) / (float)num7;
				Rect rect = default(Rect);
				for (int k = 0; k < count; k++)
				{
					WatchSlot watchSlot = _watched[k];
					if (charsById.TryGetValue(watchSlot.ViewId, out var value))
					{
						int num10 = k / num6;
						int num11 = k % num6;
						int num12 = Mathf.Min(num6, count - num10 * num6);
						float num13 = (float)(num6 - num12) * (num8 + num3) * 0.5f;
						((Rect)(ref rect))..ctor(num2 + num13 + (float)num11 * (num8 + num3), num2 + (float)num10 * (num9 + num3), num8, num9);
						rect = _layout.GetRect(watchSlot.SlotId, rect);
						SpectateView orCreateView = GetOrCreateView(watchSlot.SlotId);
						usedSlots.Add(watchSlot.SlotId);
						if (!_cellPool.TryGetValue(watchSlot.SlotId, out var value2))
						{
							value2 = new Cell();
							_cellPool[watchSlot.SlotId] = value2;
						}
						string displayName = SpectateTargets.GetDisplayName(value);
						string idLabel = SpectateTargets.GetIdLabel(value);
						bool flag = SpectateTargets.IsLocal(value);
						if (value2.Label == null || value2.LabelName != displayName || value2.LabelId != idLabel || value2.LabelLocal != flag)
						{
							string text = (flag ? L.T("(你)", " (You)") : string.Empty);
							value2.Label = displayName + "  " + idLabel + text;
							value2.LabelName = displayName;
							value2.LabelId = idLabel;
							value2.LabelLocal = flag;
						}
						value2.Id = watchSlot.SlotId;
						value2.Target = value;
						value2.Rect = rect;
						value2.View = orCreateView;
						_gridCells.Add(value2);
					}
				}
			}
			float value3 = ModConfig.SpectateZoom.Value;
			float value4 = ModConfig.FieldOfView.Value;
			float value5 = ModConfig.ResolutionScale.Value;
			for (int l = 0; l < _gridCells.Count; l++)
			{
				Cell cell = _gridCells[l];
				if (SpectateTargets.TryGetView(cell.Target, value3, out var position, out var forward))
				{
					cell.View.Render(position, forward, value4, value5, ((Rect)(ref cell.Rect)).width, ((Rect)(ref cell.Rect)).height, cell.Target);
				}
				else
				{
					cell.View.Hide();
				}
			}
			foreach (KeyValuePair<int, SpectateView> view in _views)
			{
				if (!usedSlots.Contains(view.Key))
				{
					view.Value.Hide();
				}
			}
			UpdateSelfView(value3, value4, value5);
		}

		private SpectateView GetOrCreateView(int viewId)
		{
			if (!_views.TryGetValue(viewId, out var value) || value == null)
			{
				value = new SpectateView(((Component)this).transform);
				_views[viewId] = value;
			}
			return value;
		}

		private void ReleaseView(int viewId)
		{
			if (_views.TryGetValue(viewId, out var value))
			{
				value?.Dispose();
				_views.Remove(viewId);
			}
		}

		private void OnGUI()
		{
			//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_004a: Unknown result type (might be due to invalid IL or missing references)
			//IL_004b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0050: Unknown result type (might be due to invalid IL or missing references)
			//IL_0052: Unknown result type (might be due to invalid IL or missing references)
			//IL_0053: Unknown result type (might be due to invalid IL or missing references)
			//IL_005e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0077: Unknown result type (might be due to invalid IL or missing references)
			//IL_009e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00aa: Unknown result type (might be due to invalid IL or missing references)
			//IL_00be: Expected O, but got Unknown
			//IL_00b9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00be: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ce: Invalid comparison between Unknown and I4
			try
			{
				if (_gridCells.Count == 0 && !_selfVisible)
				{
					return;
				}
				MenuTheme.EnsureBuilt();
				GUI.depth = 10;
				for (int i = 0; i < _gridCells.Count; i++)
				{
					Cell cell = _gridCells[i];
					Rect rect = cell.Rect;
					rect = (cell.Rect = _layout.GetRect(cell.Id, rect));
					DrawCell(cell.View, rect, cell.Label, cell.Target);
					if (MonitorModeState.Active)
					{
						DrawMonitorHandles(rect);
					}
				}
				if (_selfVisible)
				{
					_selfRect = GUI.Window(952702, _selfRect, new WindowFunction(DrawSelfWindow), GUIContent.none, MenuTheme.Window);
					if ((int)Event.current.type == 1 && !_selfResizing)
					{
						PersistSelfPosition();
					}
				}
			}
			catch (Exception ex)
			{
				ModConfig.Log("绘制观战画面异常:" + ex.Message);
			}
		}

		private static void DrawMonitorHandles(Rect rect)
		{
			//IL_0000: 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_0065: 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_00d9: Unknown result type (might be due to invalid IL or missing references)
			//IL_0107: Unknown result type (might be due to invalid IL or missing references)
			Color color = GUI.color;
			GUI.color = new Color(1f, 0.788f, 0.302f, 0.3f);
			GUI.DrawTexture(new Rect(((Rect)(ref rect)).x + ((Rect)(ref rect)).width * 0.3f, ((Rect)(ref rect)).y + ((Rect)(ref rect)).height * 0.5f - 1f, ((Rect)(ref rect)).width * 0.4f, 2f), (Texture)(object)Texture2D.whiteTexture);
			GUI.DrawTexture(new Rect(((Rect)(ref rect)).x + ((Rect)(ref rect)).width * 0.5f - 1f, ((Rect)(ref rect)).y + ((Rect)(ref rect)).height * 0.3f, 2f, ((Rect)(ref rect)).height * 0.4f), (Texture)(object)Texture2D.whiteTexture);
			GUI.color = new Color(1f, 0.788f, 0.302f, 0.9f);
			GUI.DrawTexture(new Rect(((Rect)(ref rect)).xMax - 20f, ((Rect)(ref rect)).yMax - 20f, 20f, 20f), (Texture)(object)Texture2D.whiteTexture);
			GUI.color = color;
		}

		private static void DrawCell(SpectateView view, Rect rect, string label, Character target)
		{
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_0070: 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)
			if (view != null && !((Object)(object)view.Texture == (Object)null))
			{
				GUI.DrawTexture(rect, view.Texture, (ScaleMode)0, false);
				if (ModConfig.ShowNameLabel.Value && !string.IsNullOrEmpty(label))
				{
					GUI.Label(new Rect(((Rect)(ref rect)).x + 4f, ((Rect)(ref rect)).y + 4f, ((Rect)(ref rect)).width - 8f, 22f), label, MenuTheme.CellLabel);
				}
				OverlayBars.Draw(rect, target, view);
			}
		}

		private void UpdateSelfView(float zoom, float fov, float scale)
		{
			//IL_0153: Unknown result type (might be due to invalid IL or missing references)
			//IL_0155: Unknown result type (might be due to invalid IL or missing references)
			_selfVisible = false;
			Character localCharacter = Character.localCharacter;
			if (!ModConfig.SelfWindowEnabled.Value || (Object)(object)localCharacter == (Object)null || (Object)(object)localCharacter.data == (Object)null)
			{
				if (_selfView != null)
				{
					_selfView.Hide();
				}
				return;
			}
			float num = Mathf.Max(120f, ModConfig.SelfWindowWidth.Value);
			float num2 = ((ModConfig.SelfWindowHeight != null) ? ModConfig.SelfWindowHeight.Value : 0f);
			float height = ((num2 > 1f) ? num2 : (num * 9f / 16f));
			if (!_selfRectInitialized)
			{
				InitSelfRect(num, height);
			}
			if (!_selfResizing)
			{
				((Rect)(ref _selfRect)).width = num;
				((Rect)(ref _selfRect)).height = height;
			}
			((Rect)(ref _selfRect)).x = Mathf.Clamp(((Rect)(ref _selfRect)).x, 0f, Mathf.Max(0f, (float)Screen.width - 40f));
			((Rect)(ref _selfRect)).y = Mathf.Clamp(((Rect)(ref _selfRect)).y, 0f, Mathf.Max(0f, (float)Screen.height - 40f));
			if (_selfView == null)
			{
				_selfView = new SpectateView(((Component)this).transform);
			}
			if (SpectateTargets.TryGetView(localCharacter, zoom, out var position, out var forward))
			{
				_selfView.Render(position, forward, fov, scale, ((Rect)(ref _selfRect)).width, ((Rect)(ref _selfRect)).height, localCharacter);
				_selfVisible = true;
			}
			else
			{
				_selfView.Hide();
			}
		}

		private void InitSelfRect(float width, float height)
		{
			//IL_00ad: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b2: Unknown result type (might be due to invalid IL or missing references)
			float num = ((ModConfig.SelfWindowX != null) ? ModConfig.SelfWindowX.Value : (-1f));
			float num2 = ((ModConfig.SelfWindowY != null) ? ModConfig.SelfWindowY.Value : (-1f));
			if (num < 0f || num2 < 0f)
			{
				float value = ModConfig.SelfWindowMargin.Value;
				switch (ModConfig.SelfWindowCorner.Value)
				{
				case 1:
					num = (float)Screen.width - value - width;
					num2 = value;
					break;
				case 2:
					num = value;
					num2 = (float)Screen.height - value - height;
					break;
				case 3:
					num = value;
					num2 = value;
					break;
				default:
					num = (float)Screen.width - value - width;
					num2 = (float)Screen.height - value - height;
					break;
				}
			}
			_selfRect = new Rect(num, num2, width, height);
			_selfRectInitialized = true;
		}

		private void DrawSelfWindow(int id)
		{
			//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_0089: Unknown result type (might be due to invalid IL or missing references)
			//IL_009d: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ef: Unknown result type (might be due to invalid IL or missing references)
			//IL_003b: Unknown result type (might be due to invalid IL or missing references)
			if (_selfView != null && (Object)(object)_selfView.Texture != (Object)null)
			{
				GUI.DrawTexture(new Rect(0f, 0f, ((Rect)(ref _selfRect)).width, ((Rect)(ref _selfRect)).height), _selfView.Texture, (ScaleMode)0, false);
			}
			Rect val = new Rect(((Rect)(ref _selfRect)).width - 16f, ((Rect)(ref _selfRect)).height - 16f, 16f, 16f);
			Color color = GUI.color;
			GUI.color = MenuTheme.Accent;
			GUI.DrawTexture(val, (Texture)(object)Texture2D.whiteTexture);
			GUI.color = color;
			HandleSelfResize(_selfRect);
			GUI.DragWindow(new Rect(0f, 0f, Mathf.Max(0f, ((Rect)(ref _selfRect)).width - 18f), Mathf.Max(0f, ((Rect)(ref _selfRect)).height - 18f)));
		}

		private void HandleSelfResize(Rect windowRect)
		{
			//IL_0032: 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_0095: Invalid comparison between Unknown and I4
			//IL_0044: Unknow