Decompiled source of TeamSpectate v1.0.0
plugins/TeamSpectate.dll
Decompiled 3 days ago
The result has been truncated due to the large size, download it to view full contents!
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