Decompiled source of LateJoinNow v1.0.1

Zichen-LateJoinNow-1.0.1.dll

Decompiled 18 hours ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Text;
using System.Text.RegularExpressions;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using ExitGames.Client.Photon;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using Photon.Pun;
using Photon.Realtime;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.SceneManagement;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: AssemblyCompany("Zichen-LateJoinNow-1.0.1")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0+91fe42e22f71e843e8fdae1615fbf0b1d6b512da")]
[assembly: AssemblyProduct("Zichen-LateJoinNow-1.0.1")]
[assembly: AssemblyTitle("Zichen-LateJoinNow-1.0.1")]
[assembly: AssemblyVersion("1.0.0.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace Zichen_LateJoinNow
{
	public enum DisplayLanguage
	{
		中文,
		English
	}
	[BepInPlugin("zichen.latejoinnow", "LateJoinNow", "1.0.1")]
	public class Plugin : BaseUnityPlugin
	{
		private sealed class StateSyncEntry
		{
			public string TypeName;

			public string FieldName;

			public string RpcName;

			public bool CastToInt;

			public Type ResolvedType;

			public FieldInfo ResolvedField;

			public bool ResolveAttempted;
		}

		[CompilerGenerated]
		private sealed class <BroadcastLoadingAnimationCompleted>d__124 : IEnumerator<object>, IDisposable, IEnumerator
		{
			private int <>1__state;

			private object <>2__current;

			public Player target;

			private int <retry>5__2;

			object IEnumerator<object>.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			object IEnumerator.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			[DebuggerHidden]
			public <BroadcastLoadingAnimationCompleted>d__124(int <>1__state)
			{
				this.<>1__state = <>1__state;
			}

			[DebuggerHidden]
			void IDisposable.Dispose()
			{
				<>1__state = -2;
			}

			private bool MoveNext()
			{
				//IL_0131: Unknown result type (might be due to invalid IL or missing references)
				//IL_013b: Expected O, but got Unknown
				switch (<>1__state)
				{
				default:
					return false;
				case 0:
					<>1__state = -1;
					<retry>5__2 = 0;
					break;
				case 1:
					<>1__state = -1;
					<retry>5__2++;
					break;
				}
				if (<retry>5__2 < 3)
				{
					if (!IsTargetStillOnline(target))
					{
						return false;
					}
					int num = 0;
					try
					{
						IEnumerable<PlayerAvatar> enumerable2;
						if (!((Object)(object)GameDirector.instance != (Object)null) || GameDirector.instance.PlayerList == null)
						{
							IEnumerable<PlayerAvatar> enumerable = Object.FindObjectsOfType<PlayerAvatar>();
							enumerable2 = enumerable;
						}
						else
						{
							IEnumerable<PlayerAvatar> enumerable = GameDirector.instance.PlayerList;
							enumerable2 = enumerable;
						}
						foreach (PlayerAvatar item in enumerable2)
						{
							if (!((Object)(object)item == (Object)null) && !((Object)(object)item.photonView == (Object)null))
							{
								try
								{
									item.photonView.RPC("LoadingLevelAnimationCompletedRPC", (RpcTarget)0, Array.Empty<object>());
									num++;
								}
								catch
								{
								}
							}
						}
					}
					catch (Exception ex)
					{
						LogWarning("[LateJoin] 发 LoadingLevelAnimationCompletedRPC 失败:" + ex.Message);
					}
					if (<retry>5__2 == 0)
					{
						LogInfo($"[LateJoin] 阶段 3/3 → {target.NickName}: LoadingLevelAnimationCompletedRPC 已对 {num} 个 PlayerAvatar 首发(RpcTarget.All)。");
					}
					else
					{
						Verbose($"[LateJoin] LoadingLevelAnimationCompletedRPC 第 {<retry>5__2 + 1} 次重发 → {num} 个 PlayerAvatar。");
					}
					<>2__current = (object)new WaitForSecondsRealtime(0.5f);
					<>1__state = 1;
					return true;
				}
				return false;
			}

			bool IEnumerator.MoveNext()
			{
				//ILSpy generated this explicit interface implementation from .override directive in MoveNext
				return this.MoveNext();
			}

			[DebuggerHidden]
			void IEnumerator.Reset()
			{
				throw new NotSupportedException();
			}
		}

		[CompilerGenerated]
		private sealed class <EnsurePlayerCorpseObjectsAndSnapshot>d__113 : IEnumerator<object>, IDisposable, IEnumerator
		{
			private int <>1__state;

			private object <>2__current;

			public Player target;

			object IEnumerator<object>.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			object IEnumerator.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			[DebuggerHidden]
			public <EnsurePlayerCorpseObjectsAndSnapshot>d__113(int <>1__state)
			{
				this.<>1__state = <>1__state;
			}

			[DebuggerHidden]
			void IDisposable.Dispose()
			{
				<>1__state = -2;
			}

			private bool MoveNext()
			{
				switch (<>1__state)
				{
				default:
					return false;
				case 0:
					<>1__state = -1;
					<>2__current = null;
					<>1__state = 1;
					return true;
				case 1:
					<>1__state = -1;
					EnsurePlayerCorpseObjects(target);
					<>2__current = ((MonoBehaviour)Instance).StartCoroutine(SendCatchupSnapshotStaged(target));
					<>1__state = 2;
					return true;
				case 2:
					<>1__state = -1;
					return false;
				}
			}

			bool IEnumerator.MoveNext()
			{
				//ILSpy generated this explicit interface implementation from .override directive in MoveNext
				return this.MoveNext();
			}

			[DebuggerHidden]
			void IEnumerator.Reset()
			{
				throw new NotSupportedException();
			}
		}

		[CompilerGenerated]
		private sealed class <SendCatchupSnapshotStaged>d__125 : IEnumerator<object>, IDisposable, IEnumerator
		{
			private int <>1__state;

			private object <>2__current;

			public Player target;

			private string <startScene>5__2;

			object IEnumerator<object>.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			object IEnumerator.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			[DebuggerHidden]
			public <SendCatchupSnapshotStaged>d__125(int <>1__state)
			{
				this.<>1__state = <>1__state;
			}

			[DebuggerHidden]
			void IDisposable.Dispose()
			{
				<startScene>5__2 = null;
				<>1__state = -2;
			}

			private bool MoveNext()
			{
				//IL_022f: Unknown result type (might be due to invalid IL or missing references)
				//IL_0239: Expected O, but got Unknown
				//IL_0185: Unknown result type (might be due to invalid IL or missing references)
				//IL_018f: Expected O, but got Unknown
				//IL_028f: Unknown result type (might be due to invalid IL or missing references)
				//IL_0299: Expected O, but got Unknown
				//IL_02f1: Unknown result type (might be due to invalid IL or missing references)
				//IL_02fb: Expected O, but got Unknown
				//IL_0353: Unknown result type (might be due to invalid IL or missing references)
				//IL_035d: Expected O, but got Unknown
				//IL_00d3: Unknown result type (might be due to invalid IL or missing references)
				//IL_00dd: Expected O, but got Unknown
				switch (<>1__state)
				{
				default:
					return false;
				case 0:
					<>1__state = -1;
					<startScene>5__2 = CurrentSceneName();
					if (VerboseLogEnabled)
					{
						int num = 0;
						try
						{
							num = Object.FindObjectsOfType<PhotonView>().Length;
						}
						catch
						{
						}
						LogInfo($"[LateJoin] 启动快照协程 → {target.NickName} | 关卡#{LateJoinNowHooks.ChangeLevelCounter} startScene={<startScene>5__2} 当前PhotonView总数={num}");
					}
					else
					{
						LogInfo($"[LateJoin] 启动快照协程 → {target.NickName} | 关卡#{LateJoinNowHooks.ChangeLevelCounter} startScene={<startScene>5__2}");
					}
					<>2__current = (object)new WaitForSecondsRealtime(0.5f);
					<>1__state = 1;
					return true;
				case 1:
					<>1__state = -1;
					if (ShouldAbortSnapshot(target, <startScene>5__2, "阶段 2 前"))
					{
						return false;
					}
					try
					{
						if ((Object)(object)NetworkManager.instance != (Object)null && (Object)(object)((MonoBehaviourPun)NetworkManager.instance).photonView != (Object)null)
						{
							((MonoBehaviourPun)NetworkManager.instance).photonView.RPC("AllPlayerSpawnedRPC", target, Array.Empty<object>());
							LogInfo("[LateJoin] 阶段 1/3 → " + target.NickName + ": AllPlayerSpawnedRPC 已发送。");
						}
					}
					catch (Exception ex2)
					{
						LogWarning("[LateJoin] 发 AllPlayerSpawnedRPC 失败:" + ex2.Message);
					}
					<>2__current = (object)new WaitForSecondsRealtime(0.6f);
					<>1__state = 2;
					return true;
				case 2:
					<>1__state = -1;
					if (ShouldAbortSnapshot(target, <startScene>5__2, "阶段 3.5 前"))
					{
						return false;
					}
					<>2__current = ((MonoBehaviour)Instance).StartCoroutine(WaitHostGenerated(target));
					<>1__state = 3;
					return true;
				case 3:
					<>1__state = -1;
					if (ShouldAbortSnapshot(target, <startScene>5__2, "阶段 4 前"))
					{
						return false;
					}
					<>2__current = ((MonoBehaviour)Instance).StartCoroutine(SendGenerateDoneRetried(target));
					<>1__state = 4;
					return true;
				case 4:
					<>1__state = -1;
					<>2__current = (object)new WaitForSecondsRealtime(0.3f);
					<>1__state = 5;
					return true;
				case 5:
					<>1__state = -1;
					if (ShouldAbortSnapshot(target, <startScene>5__2, "阶段 5.5 前"))
					{
						return false;
					}
					try
					{
						SendModuleSyncToLateJoiner(target);
					}
					catch (Exception ex4)
					{
						LogWarning("[LateJoin] 重发 Module 状态整体失败:" + ex4.Message);
					}
					<>2__current = (object)new WaitForSecondsRealtime(0.2f);
					<>1__state = 6;
					return true;
				case 6:
					<>1__state = -1;
					if (ShouldAbortSnapshot(target, <startScene>5__2, "阶段 5.7 前"))
					{
						return false;
					}
					try
					{
						SendValuableObjectSyncToLateJoiner(target);
					}
					catch (Exception ex3)
					{
						LogWarning("[LateJoin] 重发 ValuableObject 状态整体失败:" + ex3.Message);
					}
					<>2__current = (object)new WaitForSecondsRealtime(0.1f);
					<>1__state = 7;
					return true;
				case 7:
					<>1__state = -1;
					if (ShouldAbortSnapshot(target, <startScene>5__2, "阶段 5.9 前"))
					{
						return false;
					}
					try
					{
						SendStateSyncToLateJoiner(target);
					}
					catch (Exception ex)
					{
						LogWarning("[LateJoin] SendStateSyncToLateJoiner 整体失败:" + ex.Message);
					}
					<>2__current = (object)new WaitForSecondsRealtime(0.1f);
					<>1__state = 8;
					return true;
				case 8:
					<>1__state = -1;
					<>2__current = ((MonoBehaviour)Instance).StartCoroutine(BroadcastLoadingAnimationCompleted(target));
					<>1__state = 9;
					return true;
				case 9:
					<>1__state = -1;
					return false;
				}
			}

			bool IEnumerator.MoveNext()
			{
				//ILSpy generated this explicit interface implementation from .override directive in MoveNext
				return this.MoveNext();
			}

			[DebuggerHidden]
			void IEnumerator.Reset()
			{
				throw new NotSupportedException();
			}
		}

		[CompilerGenerated]
		private sealed class <SendGenerateDoneRetried>d__121 : IEnumerator<object>, IDisposable, IEnumerator
		{
			private int <>1__state;

			private object <>2__current;

			public Player target;

			private int <retry>5__2;

			object IEnumerator<object>.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			object IEnumerator.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			[DebuggerHidden]
			public <SendGenerateDoneRetried>d__121(int <>1__state)
			{
				this.<>1__state = <>1__state;
			}

			[DebuggerHidden]
			void IDisposable.Dispose()
			{
				<>1__state = -2;
			}

			private bool MoveNext()
			{
				//IL_011e: Unknown result type (might be due to invalid IL or missing references)
				//IL_0128: Expected O, but got Unknown
				int num = <>1__state;
				if (num != 0)
				{
					if (num != 1)
					{
						return false;
					}
					<>1__state = -1;
					goto IL_0138;
				}
				<>1__state = -1;
				<retry>5__2 = 0;
				goto IL_0148;
				IL_0138:
				<retry>5__2++;
				goto IL_0148;
				IL_0148:
				if (<retry>5__2 < 3)
				{
					if (!IsTargetStillOnline(target))
					{
						LogInfo("[LateJoin] 玩家 " + target.NickName + " 已离线,取消 GenerateDone 重发。");
						return false;
					}
					bool flag = false;
					try
					{
						if ((Object)(object)LevelGenerator.Instance != (Object)null && (Object)(object)LevelGenerator.Instance.PhotonView != (Object)null)
						{
							LevelGenerator.Instance.PhotonView.RPC("GenerateDone", target, Array.Empty<object>());
							flag = true;
						}
					}
					catch (Exception ex)
					{
						LogWarning("[LateJoin] 发 GenerateDone 失败:" + ex.Message);
					}
					if (!flag)
					{
						LogWarning("[LateJoin] LevelGenerator.Instance 不可用,跳过 GenerateDone。");
						return false;
					}
					if (<retry>5__2 == 0)
					{
						LogInfo("[LateJoin] 阶段 2/3 → " + target.NickName + ": GenerateDone 首发。");
					}
					else
					{
						Verbose($"[LateJoin] GenerateDone 第 {<retry>5__2 + 1} 次重发 → {target.NickName}");
					}
					if (<retry>5__2 < 2)
					{
						<>2__current = (object)new WaitForSecondsRealtime(1f);
						<>1__state = 1;
						return true;
					}
					goto IL_0138;
				}
				return false;
			}

			bool IEnumerator.MoveNext()
			{
				//ILSpy generated this explicit interface implementation from .override directive in MoveNext
				return this.MoveNext();
			}

			[DebuggerHidden]
			void IEnumerator.Reset()
			{
				throw new NotSupportedException();
			}
		}

		[CompilerGenerated]
		private sealed class <WaitAndShowCompatPopup>d__162 : IEnumerator<object>, IDisposable, IEnumerator
		{
			private int <>1__state;

			private object <>2__current;

			public Plugin <>4__this;

			object IEnumerator<object>.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			object IEnumerator.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			[DebuggerHidden]
			public <WaitAndShowCompatPopup>d__162(int <>1__state)
			{
				this.<>1__state = <>1__state;
			}

			[DebuggerHidden]
			void IDisposable.Dispose()
			{
				<>1__state = -2;
			}

			private bool MoveNext()
			{
				int num = <>1__state;
				Plugin plugin = <>4__this;
				switch (num)
				{
				default:
					return false;
				case 0:
					<>1__state = -1;
					<>2__current = plugin.WaitForMenuReady(15f, delegate(MenuManager mm)
					{
						//IL_0015: Unknown result type (might be due to invalid IL or missing references)
						TryShowMenuPopup(mm, BuildCompatTitle(), new Color(1f, 0.78f, 0.2f), BuildCompatBody(), "兼容提示");
					});
					<>1__state = 1;
					return true;
				case 1:
					<>1__state = -1;
					return false;
				}
			}

			bool IEnumerator.MoveNext()
			{
				//ILSpy generated this explicit interface implementation from .override directive in MoveNext
				return this.MoveNext();
			}

			[DebuggerHidden]
			void IEnumerator.Reset()
			{
				throw new NotSupportedException();
			}
		}

		[CompilerGenerated]
		private sealed class <WaitAndShowConflictPopup>d__165 : IEnumerator<object>, IDisposable, IEnumerator
		{
			private int <>1__state;

			private object <>2__current;

			public Plugin <>4__this;

			object IEnumerator<object>.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			object IEnumerator.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			[DebuggerHidden]
			public <WaitAndShowConflictPopup>d__165(int <>1__state)
			{
				this.<>1__state = <>1__state;
			}

			[DebuggerHidden]
			void IDisposable.Dispose()
			{
				<>1__state = -2;
			}

			private bool MoveNext()
			{
				int num = <>1__state;
				Plugin plugin = <>4__this;
				switch (num)
				{
				default:
					return false;
				case 0:
					<>1__state = -1;
					<>2__current = plugin.WaitForMenuReady(15f, delegate(MenuManager mm)
					{
						//IL_0015: Unknown result type (might be due to invalid IL or missing references)
						TryShowMenuPopup(mm, BuildConflictTitle(), new Color(1f, 0.35f, 0.35f), BuildConflictBody(), "冲突警告");
					});
					<>1__state = 1;
					return true;
				case 1:
					<>1__state = -1;
					return false;
				}
			}

			bool IEnumerator.MoveNext()
			{
				//ILSpy generated this explicit interface implementation from .override directive in MoveNext
				return this.MoveNext();
			}

			[DebuggerHidden]
			void IEnumerator.Reset()
			{
				throw new NotSupportedException();
			}
		}

		[CompilerGenerated]
		private sealed class <WaitAndShowJoinNotifyPopup>d__168 : IEnumerator<object>, IDisposable, IEnumerator
		{
			private int <>1__state;

			private object <>2__current;

			public string playerName;

			private float <deadline>5__2;

			object IEnumerator<object>.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			object IEnumerator.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			[DebuggerHidden]
			public <WaitAndShowJoinNotifyPopup>d__168(int <>1__state)
			{
				this.<>1__state = <>1__state;
			}

			[DebuggerHidden]
			void IDisposable.Dispose()
			{
				<>1__state = -2;
			}

			private bool MoveNext()
			{
				//IL_0101: Unknown result type (might be due to invalid IL or missing references)
				switch (<>1__state)
				{
				default:
					return false;
				case 0:
					<>1__state = -1;
					if (!PhotonNetwork.IsMasterClient)
					{
						return false;
					}
					if (string.IsNullOrEmpty(playerName))
					{
						playerName = (UseChinese() ? "未知玩家" : "Unknown");
					}
					<>2__current = null;
					<>1__state = 1;
					return true;
				case 1:
					<>1__state = -1;
					if (TryShowInGameJoinMessage(playerName))
					{
						return false;
					}
					<deadline>5__2 = Time.unscaledTime + 8f;
					goto IL_0134;
				case 2:
				{
					<>1__state = -1;
					MenuManager instance = MenuManager.instance;
					if ((Object)(object)instance != (Object)null && !IsPopupSlotBusy(instance))
					{
						TryShowMenuPopup(instance, BuildJoinNotifyTitle(), new Color(0.4f, 1f, 0.55f), BuildJoinNotifyBody(playerName), "玩家加入提示");
						return false;
					}
					goto IL_011d;
				}
				case 3:
					{
						<>1__state = -1;
						goto IL_0134;
					}
					IL_0134:
					if (Time.unscaledTime < <deadline>5__2)
					{
						if (TryShowInGameJoinMessage(playerName))
						{
							return false;
						}
						MenuManager instance = MenuManager.instance;
						if ((Object)(object)instance != (Object)null && !IsPopupSlotBusy(instance) && CompatibilityReport.CanShowMenuPopup)
						{
							<>2__current = null;
							<>1__state = 2;
							return true;
						}
						goto IL_011d;
					}
					return false;
					IL_011d:
					<>2__current = null;
					<>1__state = 3;
					return true;
				}
			}

			bool IEnumerator.MoveNext()
			{
				//ILSpy generated this explicit interface implementation from .override directive in MoveNext
				return this.MoveNext();
			}

			[DebuggerHidden]
			void IEnumerator.Reset()
			{
				throw new NotSupportedException();
			}
		}

		[CompilerGenerated]
		private sealed class <WaitForHostGeneratedThenCooldownCoroutine>d__140 : IEnumerator<object>, IDisposable, IEnumerator
		{
			private int <>1__state;

			private object <>2__current;

			private float <startedAt>5__2;

			private bool <generatedSeen>5__3;

			object IEnumerator<object>.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			object IEnumerator.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			[DebuggerHidden]
			public <WaitForHostGeneratedThenCooldownCoroutine>d__140(int <>1__state)
			{
				this.<>1__state = <>1__state;
			}

			[DebuggerHidden]
			void IDisposable.Dispose()
			{
				int num = <>1__state;
				if (num == -3 || num == 1)
				{
					try
					{
					}
					finally
					{
						<>m__Finally1();
					}
				}
				<>1__state = -2;
			}

			private bool MoveNext()
			{
				//IL_007b: Unknown result type (might be due to invalid IL or missing references)
				//IL_0085: Expected O, but got Unknown
				bool result;
				try
				{
					switch (<>1__state)
					{
					default:
						result = false;
						goto end_IL_0000;
					case 0:
						<>1__state = -1;
						<>1__state = -3;
						<startedAt>5__2 = Time.unscaledTime;
						<generatedSeen>5__3 = false;
						break;
					case 1:
						<>1__state = -3;
						break;
					}
					if (!(Time.unscaledTime - <startedAt>5__2 < 60f))
					{
						goto IL_00ae;
					}
					if (!IsCooldownStillRelevant())
					{
						Verbose("[Enforce] 等 Generated 期间主机身份/房间已变化,放弃等待。");
						result = false;
						goto IL_0134;
					}
					if ((Object)(object)LevelGenerator.Instance != (Object)null && LevelGenerator.Instance.Generated)
					{
						<generatedSeen>5__3 = true;
						goto IL_00ae;
					}
					<>2__current = (object)new WaitForSecondsRealtime(0.2f);
					<>1__state = 1;
					result = true;
					goto end_IL_0000;
					IL_00ae:
					if (!IsCooldownStillRelevant())
					{
						Verbose("[Enforce] 进入固定冷却前主机身份/房间已变化,放弃。");
						result = false;
						goto IL_0134;
					}
					float num = Time.unscaledTime - <startedAt>5__2;
					if (<generatedSeen>5__3)
					{
						LogInfo($"[Enforce] 主机 Generated=true(等了 {num:F1}s),进入 {5f:F0}s 固定冷却。");
					}
					else
					{
						LogWarning($"[Enforce] 等待主机 Generated=true 超时({60f:F0}s),跳过等待直接进入 {5f:F0}s 固定冷却。");
					}
					_changeLevelCooldownUntil = Time.unscaledTime + 5f;
					<>m__Finally1();
					result = false;
					goto end_IL_0000;
					IL_0134:
					<>m__Finally1();
					end_IL_0000:;
				}
				catch
				{
					//try-fault
					((IDisposable)this).Dispose();
					throw;
				}
				return result;
			}

			bool IEnumerator.MoveNext()
			{
				//ILSpy generated this explicit interface implementation from .override directive in MoveNext
				return this.MoveNext();
			}

			private void <>m__Finally1()
			{
				<>1__state = -1;
				_changeLevelCooldownCoroutineRunning = false;
			}

			[DebuggerHidden]
			void IEnumerator.Reset()
			{
				throw new NotSupportedException();
			}
		}

		[CompilerGenerated]
		private sealed class <WaitForMenuReady>d__160 : IEnumerator<object>, IDisposable, IEnumerator
		{
			private int <>1__state;

			private object <>2__current;

			public float deadlineSeconds;

			public Action<MenuManager> onReady;

			private float <deadline>5__2;

			object IEnumerator<object>.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			object IEnumerator.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			[DebuggerHidden]
			public <WaitForMenuReady>d__160(int <>1__state)
			{
				this.<>1__state = <>1__state;
			}

			[DebuggerHidden]
			void IDisposable.Dispose()
			{
				<>1__state = -2;
			}

			private bool MoveNext()
			{
				switch (<>1__state)
				{
				default:
					return false;
				case 0:
					<>1__state = -1;
					<deadline>5__2 = Time.unscaledTime + deadlineSeconds;
					goto IL_00ad;
				case 1:
				{
					<>1__state = -1;
					MenuManager instance = MenuManager.instance;
					if ((Object)(object)instance != (Object)null && !IsPopupSlotBusy(instance))
					{
						onReady?.Invoke(instance);
						return false;
					}
					goto IL_0096;
				}
				case 2:
					{
						<>1__state = -1;
						goto IL_00ad;
					}
					IL_00ad:
					if (Time.unscaledTime < <deadline>5__2)
					{
						MenuManager instance = MenuManager.instance;
						if ((Object)(object)instance != (Object)null && !IsPopupSlotBusy(instance) && CompatibilityReport.CanShowMenuPopup)
						{
							<>2__current = null;
							<>1__state = 1;
							return true;
						}
						goto IL_0096;
					}
					return false;
					IL_0096:
					<>2__current = null;
					<>1__state = 2;
					return true;
				}
			}

			bool IEnumerator.MoveNext()
			{
				//ILSpy generated this explicit interface implementation from .override directive in MoveNext
				return this.MoveNext();
			}

			[DebuggerHidden]
			void IEnumerator.Reset()
			{
				throw new NotSupportedException();
			}
		}

		[CompilerGenerated]
		private sealed class <WaitHostGenerated>d__120 : IEnumerator<object>, IDisposable, IEnumerator
		{
			private int <>1__state;

			private object <>2__current;

			public Player target;

			private float <deadline>5__2;

			object IEnumerator<object>.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			object IEnumerator.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			[DebuggerHidden]
			public <WaitHostGenerated>d__120(int <>1__state)
			{
				this.<>1__state = <>1__state;
			}

			[DebuggerHidden]
			void IDisposable.Dispose()
			{
				<>1__state = -2;
			}

			private bool MoveNext()
			{
				//IL_0086: Unknown result type (might be due to invalid IL or missing references)
				//IL_0090: Expected O, but got Unknown
				switch (<>1__state)
				{
				default:
					return false;
				case 0:
					<>1__state = -1;
					<deadline>5__2 = Time.unscaledTime + 30f;
					break;
				case 1:
					<>1__state = -1;
					break;
				}
				if (Time.unscaledTime < <deadline>5__2)
				{
					if (!IsTargetStillOnline(target))
					{
						LogInfo("[LateJoin] 玩家 " + target.NickName + " 已离线,取消等待 Generated。");
						return false;
					}
					if ((Object)(object)LevelGenerator.Instance != (Object)null && LevelGenerator.Instance.Generated)
					{
						Verbose("[LateJoin] 主机已 Generated=true,开始发 GenerateDone 兜底。");
						return false;
					}
					<>2__current = (object)new WaitForSecondsRealtime(0.2f);
					<>1__state = 1;
					return true;
				}
				LogWarning("[LateJoin] 等待主机 Generated=true 超时(30s),仍按当前状态发送 GenerateDone。");
				return false;
			}

			bool IEnumerator.MoveNext()
			{
				//ILSpy generated this explicit interface implementation from .override directive in MoveNext
				return this.MoveNext();
			}

			[DebuggerHidden]
			void IEnumerator.Reset()
			{
				throw new NotSupportedException();
			}
		}

		public const string PluginGuid = "zichen.latejoinnow";

		public const string PluginName = "LateJoinNow";

		public const string PluginVersion = "1.0.1";

		internal static Plugin Instance;

		internal static Harmony harmony;

		private static ConfigEntry<bool> _cfgModEnabled;

		private static ConfigEntry<DisplayLanguage> _cfgLanguage;

		private static ConfigEntry<bool> _cfgJoinNotify;

		private static ConfigEntry<bool> _cfgPublicRoomPrefix;

		private static ConfigEntry<bool> _cfgHudEnabled;

		private static ConfigEntry<bool> _cfgHudShowRoomType;

		private static ConfigEntry<bool> _cfgHudShowRoomName;

		private static ConfigEntry<bool> _cfgHudShowPlayerCount;

		private static ConfigEntry<int> _cfgHudFontSize;

		private static ConfigEntry<int> _cfgHudOpacity;

		private static ConfigEntry<bool> _cfgVerboseLog;

		private static ConfigEntry<bool> _cfgShowConflictWarning;

		private static ConfigEntry<bool> _cfgAllowLobby;

		private static ConfigEntry<bool> _cfgAllowShop;

		private static ConfigEntry<bool> _cfgAllowLevel;

		private static ConfigEntry<bool> _cfgPublicVisible;

		private float _enforceTimer;

		private const float EnforceInterval = 1f;

		private static GUIStyle _hudLabelStyle;

		private static GUIStyle _hudShadowStyle;

		private static int _cachedFontSize = -1;

		private static int _cachedOpacity = -1;

		private static readonly List<string> _hudLines = new List<string>(3);

		private const float HudRefreshInterval = 0.5f;

		private static float _hudNextRefreshAt;

		private static bool _hudCacheUseChinese;

		private static bool _hudCacheShowPlayerCount;

		private static bool _hudCacheShowRoomType;

		private static bool _hudCacheShowRoomName;

		private static int _hudCachePlayerCount;

		private static int _hudCacheMaxPlayers;

		private static LobbyTypes _hudCacheLobbyType;

		private static bool _hudCacheLobbyTypeKnown;

		private static string _hudCacheServerName;

		private static readonly StateSyncEntry[] _stateSyncEntries = new StateSyncEntry[22]
		{
			S("ExtractionPoint", "StateSetRPC", castToInt: false),
			S("ShopKeycardDoor", "StateSetRPC"),
			S("UpgradeStand", "StateSetRPC"),
			S("ItemValuableBox", "StateSetRPC"),
			S("ItemMine", "StateSetRPC", castToInt: true, "state"),
			S("ItemMelee", "StateSetRPC"),
			S("ItemGun", "StateSetRPC", castToInt: true, "stateCurrent"),
			S("ItemDrone", "StateSetRPC"),
			S("ItemVehicle", "SetStateRPC"),
			S("ItemCartCannonMain", "StateSetRPC", castToInt: true, "stateCurrent"),
			S("FanTrap", "SetStateRPC", castToInt: false),
			S("CrystalBallValuable", "SetStateRPC", castToInt: false),
			S("BlenderValuable", "SetStateRPC", castToInt: false),
			S("FlamethrowerValuable", "SetStateRPC", castToInt: false),
			S("IceSawValuable", "SetStateRPC", castToInt: false),
			S("FireExtinguisherValuable", "SetStateRPC", castToInt: false),
			S("ScreamDollValuable", "SetStateRPC", castToInt: false),
			S("JackhammerValuable", "SetStateRPC", castToInt: false),
			S("TrafficLightValuable", "SetStateRPC", castToInt: false),
			S("ValuableWizardTimeGlass", "SetStateRPC", castToInt: false),
			S("ValuableArcticSnowBike", "SetStateRPC"),
			S("ValuableEgg", "SetStateRPC", castToInt: false)
		};

		private static readonly HashSet<int> _pendingLateJoiners = new HashSet<int>();

		private static readonly FieldRef<PlayerAvatar, PlayerDeathHead> _playerDeathHeadRef = AccessTools.FieldRefAccess<PlayerAvatar, PlayerDeathHead>("playerDeathHead");

		private static readonly FieldRef<PlayerAvatar, PlayerTumble> _playerTumbleRef = AccessTools.FieldRefAccess<PlayerAvatar, PlayerTumble>("tumble");

		private static readonly FieldRef<Module, bool> _moduleConnectingTopRef = AccessTools.FieldRefAccess<Module, bool>("ConnectingTop");

		private static readonly FieldRef<Module, bool> _moduleConnectingBottomRef = AccessTools.FieldRefAccess<Module, bool>("ConnectingBottom");

		private static readonly FieldRef<Module, bool> _moduleConnectingRightRef = AccessTools.FieldRefAccess<Module, bool>("ConnectingRight");

		private static readonly FieldRef<Module, bool> _moduleConnectingLeftRef = AccessTools.FieldRefAccess<Module, bool>("ConnectingLeft");

		private static readonly FieldRef<Module, bool> _moduleFirstRef = AccessTools.FieldRefAccess<Module, bool>("First");

		private static readonly FieldRef<Module, bool> _moduleSetupDoneRef = AccessTools.FieldRefAccess<Module, bool>("SetupDone");

		private static readonly FieldRef<ValuableObject, bool> _valuableDollarValueSetRef = AccessTools.FieldRefAccess<ValuableObject, bool>("dollarValueSet");

		private static readonly FieldRef<ValuableObject, float> _valuableDollarValueCurrentRef = AccessTools.FieldRefAccess<ValuableObject, float>("dollarValueCurrent");

		private static readonly FieldRef<ValuableObject, bool> _valuableDiscoveredRef = AccessTools.FieldRefAccess<ValuableObject, bool>("discovered");

		private static readonly FieldRef<ValuableObject, bool> _valuableInStartRoomRef = AccessTools.FieldRefAccess<ValuableObject, bool>("inStartRoom");

		private const float ChangeLevelCooldownSeconds = 5f;

		private const float WaitGeneratedTimeoutSeconds = 60f;

		private const float WaitGeneratedPollInterval = 0.2f;

		private const float CooldownLockedSentinelSeconds = 600f;

		private const string RoomNamePrefixCN = "[游戏中] ";

		private const string RoomNamePrefixEN = "[In Game] ";

		private static readonly FieldInfo _networkServerNameField = AccessTools.Field(typeof(DataDirector), "networkServerName");

		private static float _changeLevelCooldownUntil;

		private static bool _changeLevelCooldownCoroutineRunning;

		private static bool? _lastSceneAllowed;

		public static bool JoinNotifyEnabled
		{
			get
			{
				if (_cfgJoinNotify != null)
				{
					return _cfgJoinNotify.Value;
				}
				return true;
			}
		}

		public static bool PublicRoomPrefixEnabled
		{
			get
			{
				if (_cfgPublicRoomPrefix != null)
				{
					return _cfgPublicRoomPrefix.Value;
				}
				return true;
			}
		}

		public static bool HudEnabled
		{
			get
			{
				if (_cfgHudEnabled != null)
				{
					return _cfgHudEnabled.Value;
				}
				return true;
			}
		}

		public static bool HudShowRoomType
		{
			get
			{
				if (_cfgHudShowRoomType != null)
				{
					return _cfgHudShowRoomType.Value;
				}
				return true;
			}
		}

		public static bool HudShowRoomName
		{
			get
			{
				if (_cfgHudShowRoomName != null)
				{
					return _cfgHudShowRoomName.Value;
				}
				return true;
			}
		}

		public static bool HudShowPlayerCount
		{
			get
			{
				if (_cfgHudShowPlayerCount != null)
				{
					return _cfgHudShowPlayerCount.Value;
				}
				return true;
			}
		}

		public static int HudFontSize
		{
			get
			{
				if (_cfgHudFontSize != null)
				{
					return _cfgHudFontSize.Value;
				}
				return 16;
			}
		}

		public static int HudOpacityPercent
		{
			get
			{
				if (_cfgHudOpacity != null)
				{
					return _cfgHudOpacity.Value;
				}
				return 80;
			}
		}

		public static bool VerboseLogEnabled
		{
			get
			{
				if (_cfgVerboseLog != null)
				{
					return _cfgVerboseLog.Value;
				}
				return true;
			}
		}

		public static bool ShowConflictWarningEnabled
		{
			get
			{
				if (_cfgShowConflictWarning != null)
				{
					return _cfgShowConflictWarning.Value;
				}
				return true;
			}
		}

		public static bool AllowLobby
		{
			get
			{
				if (_cfgAllowLobby != null)
				{
					return _cfgAllowLobby.Value;
				}
				return true;
			}
		}

		public static bool AllowShop
		{
			get
			{
				if (_cfgAllowShop != null)
				{
					return _cfgAllowShop.Value;
				}
				return true;
			}
		}

		public static bool AllowLevel
		{
			get
			{
				if (_cfgAllowLevel != null)
				{
					return _cfgAllowLevel.Value;
				}
				return true;
			}
		}

		public static bool PublicVisibleSync
		{
			get
			{
				if (_cfgPublicVisible != null)
				{
					return _cfgPublicVisible.Value;
				}
				return true;
			}
		}

		internal static int PendingLateJoinerCount => _pendingLateJoiners.Count;

		internal static bool IsInChangeLevelCooldown => Time.unscaledTime < _changeLevelCooldownUntil;

		private static float CooldownSecondsLeft => Mathf.Max(0f, _changeLevelCooldownUntil - Time.unscaledTime);

		public static bool IsStaticModEnabled()
		{
			if (_cfgModEnabled != null)
			{
				return _cfgModEnabled.Value;
			}
			return false;
		}

		public static bool UseChinese()
		{
			if (_cfgLanguage != null)
			{
				return _cfgLanguage.Value == DisplayLanguage.中文;
			}
			return true;
		}

		internal static void Verbose(string msg)
		{
			if (VerboseLogEnabled)
			{
				Plugin instance = Instance;
				if (instance != null)
				{
					((BaseUnityPlugin)instance).Logger.LogInfo((object)("[Verbose] " + msg));
				}
			}
		}

		public static bool IsCurrentSceneAllowed()
		{
			if (!IsStaticModEnabled())
			{
				return false;
			}
			if (!PhotonNetwork.IsMasterClient)
			{
				return false;
			}
			if ((Object)(object)RunManager.instance == (Object)null)
			{
				return false;
			}
			try
			{
				if (SemiFunc.RunIsLobby())
				{
					return AllowLobby;
				}
				if (SemiFunc.RunIsShop())
				{
					return AllowShop;
				}
				if (SemiFunc.RunIsArena())
				{
					return false;
				}
				if (SemiFunc.RunIsLevel())
				{
					return AllowLevel;
				}
			}
			catch (Exception ex)
			{
				Plugin instance = Instance;
				if (instance != null)
				{
					((BaseUnityPlugin)instance).Logger.LogWarning((object)("判定当前场景类型失败:" + ex.Message));
				}
				return false;
			}
			return false;
		}

		private void Awake()
		{
			//IL_003a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0044: Expected O, but got Unknown
			DetachFromManager();
			Instance = this;
			ResetConfigIfVersionChanged();
			BindConfig();
			if (!IsStaticModEnabled())
			{
				((BaseUnityPlugin)this).Logger.LogInfo((object)"LateJoinNow v1.0.1 已禁用,跳过 Harmony 安装。");
				return;
			}
			CompatibilityReport.Build();
			try
			{
				harmony = new Harmony("zichen.latejoinnow");
				InstallPatchesSafely();
				((BaseUnityPlugin)this).Logger.LogInfo((object)"LateJoinNow v1.0.1 loaded.");
			}
			catch (Exception ex)
			{
				((BaseUnityPlugin)this).Logger.LogError((object)("LateJoinNow 启动失败:" + ex.Message));
			}
			if (CompatibilityReport.HasIssues)
			{
				((MonoBehaviour)this).StartCoroutine(WaitAndShowCompatPopup());
			}
			if (ShowConflictWarningEnabled)
			{
				ConflictDetect.Detect();
				if (ConflictDetect.HasConflict)
				{
					((MonoBehaviour)this).StartCoroutine(WaitAndShowConflictPopup());
				}
			}
		}

		private void Update()
		{
			if (IsHookActive() && PhotonNetwork.IsMasterClient)
			{
				_enforceTimer -= Time.unscaledDeltaTime;
				if (!(_enforceTimer > 0f))
				{
					_enforceTimer = 1f;
					EnforceLobbyState();
				}
			}
		}

		private void BindConfig()
		{
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			//IL_004b: Expected O, but got Unknown
			//IL_008d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0097: Expected O, but got Unknown
			//IL_00d9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e3: Expected O, but got Unknown
			//IL_0289: Unknown result type (might be due to invalid IL or missing references)
			//IL_0293: Expected O, but got Unknown
			//IL_02bd: Unknown result type (might be due to invalid IL or missing references)
			//IL_02c7: Expected O, but got Unknown
			((BaseUnityPlugin)this).Config.Bind<string>("模组信息", "模组名称", "中途随时加入", new ConfigDescription("当前模组的中文名称。此处只是提示,不影响功能。", (AcceptableValueBase)null, new object[1]
			{
				new ConfigurationManagerAttributes
				{
					ReadOnly = true,
					HideDefaultButton = true
				}
			}));
			((BaseUnityPlugin)this).Config.Bind<string>("模组信息", "模组版本号", "1.0.1", new ConfigDescription("当前模组版本号。此处只是提示,不影响功能。", (AcceptableValueBase)null, new object[1]
			{
				new ConfigurationManagerAttributes
				{
					ReadOnly = true,
					HideDefaultButton = true
				}
			}));
			((BaseUnityPlugin)this).Config.Bind<string>("模组信息", "REPO交流QQ群", "824639225", new ConfigDescription("REPO 游戏交流、BUG 反馈、优化建议、功能请求请加 QQ 群。此处只是提示,不影响功能。", (AcceptableValueBase)null, new object[1]
			{
				new ConfigurationManagerAttributes
				{
					ReadOnly = true,
					HideDefaultButton = true
				}
			}));
			_cfgLanguage = ((BaseUnityPlugin)this).Config.Bind<DisplayLanguage>("模组信息", "语言/Language", DisplayLanguage.中文, "公开文档和配置说明语言切换。仅该项保留中英并列格式。");
			_cfgModEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("A.全局设置", "模组启用", true, "关闭后整个模组全部功能彻底失效,零性能开销。");
			_cfgPublicRoomPrefix = ((BaseUnityPlugin)this).Config.Bind<bool>("A.全局设置", "公开房名加前缀", true, "开启后,创建自定义名字的公开房时,服务器列表里的房间名会自动加上\"[游戏中]\"前缀,让其他玩家知道这个房间支持中途加入。前缀只在房间创建时一次性写入,房间存在期间无法修改。");
			_cfgPublicVisible = ((BaseUnityPlugin)this).Config.Bind<bool>("A.全局设置", "游戏中房间在公开服务器", true, "若你的房间是公共房,开启后允许中途加入时房间也会出现在公共列表,可被陌生人随机加入;关闭则只接受邀请加入。");
			_cfgJoinNotify = ((BaseUnityPlugin)this).Config.Bind<bool>("A.全局设置", "新玩家加入弹窗通知", true, "开启后,每次有玩家中途加入房间,主机会收到一次菜单弹窗提示。");
			_cfgAllowLobby = ((BaseUnityPlugin)this).Config.Bind<bool>("B.场景白名单", "允许在卡车阶段加入", true, "卡车阶段(游戏内 Lobby,玩家在卡车里休整)允许中途加入。");
			_cfgAllowShop = ((BaseUnityPlugin)this).Config.Bind<bool>("B.场景白名单", "允许在商店阶段加入", true, "商店阶段允许中途加入。");
			_cfgAllowLevel = ((BaseUnityPlugin)this).Config.Bind<bool>("B.场景白名单", "允许在关卡进行中加入", true, "普通运行关卡(搜刮、跑路过程中)允许中途加入。");
			_cfgHudEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("C.房间信息显示", "启用", true, "开启后,当前场景允许中途加入时,屏幕左下角显示一个小信息框。关闭则任何场景都不显示。");
			_cfgHudShowPlayerCount = ((BaseUnityPlugin)this).Config.Bind<bool>("C.房间信息显示", "显示房间人数", true, "在 HUD 上显示当前人数 / 最大人数(例如 3/6)。");
			_cfgHudShowRoomType = ((BaseUnityPlugin)this).Config.Bind<bool>("C.房间信息显示", "显示房间类型", true, "在 HUD 上显示当前房间类型:公开服务器 / 私人服务器 / 单人模式。");
			_cfgHudShowRoomName = ((BaseUnityPlugin)this).Config.Bind<bool>("C.房间信息显示", "显示房间名称", true, "在 HUD 上显示当前房间名称:公开房显示房间名,私人房显示\"仅限好友加入\"。");
			_cfgHudFontSize = ((BaseUnityPlugin)this).Config.Bind<int>("C.房间信息显示", "字体大小", 16, new ConfigDescription("HUD 文字大小,默认 16。", (AcceptableValueBase)(object)new AcceptableValueRange<int>(10, 28), Array.Empty<object>()));
			_cfgHudOpacity = ((BaseUnityPlugin)this).Config.Bind<int>("C.房间信息显示", "文字透明度/%", 80, new ConfigDescription("HUD 文字整体透明度,默认 80%。", (AcceptableValueBase)(object)new AcceptableValueRange<int>(20, 100), Array.Empty<object>()));
			_cfgVerboseLog = ((BaseUnityPlugin)this).Config.Bind<bool>("D.调试", "详细日志", false, "开启后会在控制台输出更多关键路径日志(关卡切换、玩家加入、缓存清理、触发等),便于排查问题。");
			_cfgShowConflictWarning = ((BaseUnityPlugin)this).Config.Bind<bool>("D.调试", "同类模组冲突警告", true, "开启后,启动时若检测到本地还安装了其他「中途加入/晚加入」类同类 mod,会在主菜单弹一次红色警告。强烈建议保持开启。");
		}

		private void ResetConfigIfVersionChanged()
		{
			try
			{
				string configFilePath = ((BaseUnityPlugin)this).Config.ConfigFilePath;
				string text = ReadConfigPluginVersion(configFilePath);
				if (!string.IsNullOrWhiteSpace(text) && !(text == "1.0.1"))
				{
					((BaseUnityPlugin)this).Config.Clear();
					if (File.Exists(configFilePath))
					{
						File.Delete(configFilePath);
					}
					((BaseUnityPlugin)this).Config.Reload();
					((BaseUnityPlugin)this).Logger.LogWarning((object)"配置文件版本不一致,已重置为当前版本默认值。");
				}
			}
			catch (Exception ex)
			{
				((BaseUnityPlugin)this).Logger.LogWarning((object)("按版本重置配置失败:" + ex.Message));
			}
		}

		private static string ReadConfigPluginVersion(string configPath)
		{
			if (!File.Exists(configPath))
			{
				return null;
			}
			Match match = Regex.Match(File.ReadAllText(configPath), "(?m)^模组版本号\\s*=\\s*(.+?)\\s*$");
			if (!match.Success)
			{
				return null;
			}
			return match.Groups[1].Value.Trim();
		}

		private void DetachFromManager()
		{
			((Component)this).gameObject.transform.parent = null;
			((Object)((Component)this).gameObject).hideFlags = (HideFlags)52;
			Object.DontDestroyOnLoad((Object)(object)((Component)this).gameObject);
		}

		internal static void LogInfo(string msg)
		{
			Plugin instance = Instance;
			if (instance != null)
			{
				((BaseUnityPlugin)instance).Logger.LogInfo((object)msg);
			}
		}

		internal static void LogWarning(string msg)
		{
			Plugin instance = Instance;
			if (instance != null)
			{
				((BaseUnityPlugin)instance).Logger.LogWarning((object)msg);
			}
		}

		internal static void LogError(string msg)
		{
			Plugin instance = Instance;
			if (instance != null)
			{
				((BaseUnityPlugin)instance).Logger.LogError((object)msg);
			}
		}

		internal static bool IsHookActive()
		{
			if (IsStaticModEnabled())
			{
				return CompatibilityReport.RuntimeReady;
			}
			return false;
		}

		private void OnGUI()
		{
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0032: Invalid comparison between Unknown and I4
			if (IsHookActive() && PhotonNetwork.IsMasterClient && HudEnabled && IsCurrentSceneAllowed() && (Event.current == null || (int)Event.current.type == 7))
			{
				EnsureHudStyles();
				RefreshHudLinesIfNeeded();
				DrawHud();
			}
		}

		private static void EnsureHudStyles()
		{
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			//IL_004b: Expected O, but got Unknown
			//IL_007b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0085: Unknown result type (might be due to invalid IL or missing references)
			//IL_008f: Expected O, but got Unknown
			//IL_00c5: Unknown result type (might be due to invalid IL or missing references)
			int num = Mathf.Clamp(HudFontSize, 10, 28);
			int num2 = Mathf.Clamp(HudOpacityPercent, 20, 100);
			if (_hudLabelStyle == null || _cachedFontSize != num || _cachedOpacity != num2)
			{
				float num3 = (float)num2 / 100f;
				_hudLabelStyle = new GUIStyle();
				_hudLabelStyle.fontSize = num;
				_hudLabelStyle.richText = true;
				_hudLabelStyle.normal.textColor = new Color(1f, 1f, 1f, num3);
				_hudShadowStyle = new GUIStyle();
				_hudShadowStyle.fontSize = num;
				_hudShadowStyle.richText = true;
				_hudShadowStyle.normal.textColor = new Color(0f, 0f, 0f, num3 * 0.7f);
				_cachedFontSize = num;
				_cachedOpacity = num2;
			}
		}

		private static void RefreshHudLinesIfNeeded()
		{
			//IL_00f9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fe: Unknown result type (might be due to invalid IL or missing references)
			//IL_009b: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a0: Unknown result type (might be due to invalid IL or missing references)
			bool flag = UseChinese();
			bool hudShowPlayerCount = HudShowPlayerCount;
			bool hudShowRoomType = HudShowRoomType;
			bool hudShowRoomName = HudShowRoomName;
			int num = 0;
			int num2 = 0;
			try
			{
				if (PhotonNetwork.CurrentRoom != null)
				{
					num = PhotonNetwork.CurrentRoom.PlayerCount;
					num2 = PhotonNetwork.CurrentRoom.MaxPlayers;
				}
			}
			catch
			{
			}
			LobbyTypes? lobbyTypeOrNull = GetLobbyTypeOrNull();
			string text = ReadServerName();
			if (flag != _hudCacheUseChinese || hudShowPlayerCount != _hudCacheShowPlayerCount || hudShowRoomType != _hudCacheShowRoomType || hudShowRoomName != _hudCacheShowRoomName || num != _hudCachePlayerCount || num2 != _hudCacheMaxPlayers || lobbyTypeOrNull.HasValue != _hudCacheLobbyTypeKnown || (lobbyTypeOrNull.HasValue && lobbyTypeOrNull.Value != _hudCacheLobbyType) || text != _hudCacheServerName || !(Time.unscaledTime < _hudNextRefreshAt))
			{
				_hudCacheUseChinese = flag;
				_hudCacheShowPlayerCount = hudShowPlayerCount;
				_hudCacheShowRoomType = hudShowRoomType;
				_hudCacheShowRoomName = hudShowRoomName;
				_hudCachePlayerCount = num;
				_hudCacheMaxPlayers = num2;
				_hudCacheLobbyTypeKnown = lobbyTypeOrNull.HasValue;
				_hudCacheLobbyType = lobbyTypeOrNull.GetValueOrDefault();
				_hudCacheServerName = text;
				_hudNextRefreshAt = Time.unscaledTime + 0.5f;
				_hudLines.Clear();
				if (hudShowPlayerCount)
				{
					_hudLines.Add((flag ? "房间人数:" : "Players: ") + GetPlayerCountText(num, num2, flag));
				}
				if (hudShowRoomType)
				{
					_hudLines.Add((flag ? "房间类型:" : "Room: ") + GetRoomTypeText(lobbyTypeOrNull, flag));
				}
				if (hudShowRoomName)
				{
					_hudLines.Add((flag ? "房间名称:" : "Name: ") + GetRoomNameText(lobbyTypeOrNull, text, flag));
				}
			}
		}

		private static void DrawHud()
		{
			//IL_006c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0090: Unknown result type (might be due to invalid IL or missing references)
			if (_hudLines.Count != 0)
			{
				float num = (float)((_cachedFontSize > 0) ? _cachedFontSize : 16) * 1.35f;
				float num2 = num * (float)_hudLines.Count;
				float num3 = 12f;
				float num4 = (float)Screen.height - num2 - 12f;
				for (int i = 0; i < _hudLines.Count; i++)
				{
					float num5 = num4 + (float)i * num;
					GUI.Label(new Rect(num3 + 1f, num5 + 1f, 480f, num), _hudLines[i], _hudShadowStyle);
					GUI.Label(new Rect(num3, num5, 480f, num), _hudLines[i], _hudLabelStyle);
				}
			}
		}

		private static LobbyTypes? GetLobbyTypeOrNull()
		{
			//IL_005d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0062: Unknown result type (might be due to invalid IL or missing references)
			//IL_0063: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)GameManager.instance == (Object)null)
			{
				return null;
			}
			try
			{
				if (CompatibilityReport.GameManagerLobbyTypeRef != null)
				{
					return CompatibilityReport.GameManagerLobbyTypeRef.Invoke(GameManager.instance);
				}
				if (CompatibilityReport.GameManagerLobbyTypeField != null)
				{
					object value = CompatibilityReport.GameManagerLobbyTypeField.GetValue(GameManager.instance);
					if (value is LobbyTypes)
					{
						return (LobbyTypes)value;
					}
				}
			}
			catch
			{
			}
			return null;
		}

		private static string ReadServerName()
		{
			try
			{
				if (PhotonNetwork.CurrentRoom == null)
				{
					return null;
				}
				Hashtable customProperties = ((RoomInfo)PhotonNetwork.CurrentRoom).CustomProperties;
				string text = null;
				if (customProperties != null && ((Dictionary<object, object>)(object)customProperties).ContainsKey((object)"server_name"))
				{
					text = customProperties[(object)"server_name"] as string;
				}
				if (string.IsNullOrWhiteSpace(text))
				{
					text = PhotonNetwork.CurrentRoom.Name;
				}
				return string.IsNullOrEmpty(text) ? null : text;
			}
			catch
			{
				return null;
			}
		}

		private static string GetRoomTypeText(LobbyTypes? lobbyType, bool useChinese)
		{
			//IL_002c: 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_0044: Expected I4, but got Unknown
			try
			{
				if (!SemiFunc.IsMultiplayer())
				{
					return useChinese ? "单人模式" : "Singleplayer";
				}
			}
			catch
			{
			}
			if (lobbyType.HasValue)
			{
				LobbyTypes value = lobbyType.Value;
				switch ((int)value)
				{
				case 1:
					if (!useChinese)
					{
						return "Public";
					}
					return "公开服务器";
				case 0:
					if (!useChinese)
					{
						return "Private";
					}
					return "私人服务器";
				case 2:
					if (!useChinese)
					{
						return "Matchmaking";
					}
					return "匹配房间";
				}
			}
			try
			{
				if (PhotonNetwork.CurrentRoom != null)
				{
					return (!PhotonNetwork.CurrentRoom.IsVisible) ? (useChinese ? "私人服务器" : "Private") : (useChinese ? "公开服务器" : "Public");
				}
			}
			catch
			{
			}
			if (!useChinese)
			{
				return "Unknown";
			}
			return "未知";
		}

		private static string GetRoomNameText(LobbyTypes? lobbyType, string serverName, bool useChinese)
		{
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: Invalid comparison between Unknown and I4
			try
			{
				if (!SemiFunc.IsMultiplayer())
				{
					return useChinese ? "无" : "N/A";
				}
			}
			catch
			{
			}
			bool flag = false;
			if (lobbyType.HasValue)
			{
				flag = (int)lobbyType.Value == 0;
			}
			else
			{
				try
				{
					if (PhotonNetwork.CurrentRoom != null && !PhotonNetwork.CurrentRoom.IsVisible)
					{
						flag = true;
					}
				}
				catch
				{
				}
			}
			if (flag)
			{
				if (!useChinese)
				{
					return "Friends Only";
				}
				return "仅限好友加入";
			}
			if (string.IsNullOrEmpty(serverName))
			{
				if (!useChinese)
				{
					return "Unknown";
				}
				return "未知";
			}
			return serverName;
		}

		private static string GetPlayerCountText(int playerCount, int maxPlayers, bool useChinese)
		{
			try
			{
				if (!SemiFunc.IsMultiplayer())
				{
					return "1/1";
				}
			}
			catch
			{
			}
			if (playerCount > 0)
			{
				int num = ((maxPlayers > 0) ? maxPlayers : playerCount);
				return playerCount + "/" + num;
			}
			if (!useChinese)
			{
				return "Unknown";
			}
			return "未知";
		}

		private static StateSyncEntry S(string type, string rpc, bool castToInt = true, string field = "currentState")
		{
			return new StateSyncEntry
			{
				TypeName = type,
				FieldName = field,
				RpcName = rpc,
				CastToInt = castToInt
			};
		}

		internal static void SendStateSyncToLateJoiner(Player target)
		{
			if (target == null)
			{
				return;
			}
			int num = 0;
			int num2 = 0;
			int num3 = 0;
			int num4 = 0;
			StateSyncEntry[] stateSyncEntries = _stateSyncEntries;
			foreach (StateSyncEntry stateSyncEntry in stateSyncEntries)
			{
				ResolveEntryReflection(stateSyncEntry);
				if (stateSyncEntry.ResolvedType == null || stateSyncEntry.ResolvedField == null)
				{
					continue;
				}
				num++;
				int num5 = 0;
				int num6 = 0;
				try
				{
					Object[] array = Object.FindObjectsOfType(stateSyncEntry.ResolvedType);
					if (array == null || array.Length == 0)
					{
						continue;
					}
					Object[] array2 = array;
					foreach (Object obj in array2)
					{
						MonoBehaviour val = (MonoBehaviour)(object)((obj is MonoBehaviour) ? obj : null);
						if ((Object)(object)val == (Object)null)
						{
							continue;
						}
						PhotonView component = ((Component)val).GetComponent<PhotonView>();
						if ((Object)(object)component == (Object)null || component.ViewID == 0)
						{
							num6++;
							num3++;
							continue;
						}
						try
						{
							object value = stateSyncEntry.ResolvedField.GetValue(val);
							if (value == null)
							{
								num6++;
								num3++;
								continue;
							}
							object obj2 = (stateSyncEntry.CastToInt ? ((object)Convert.ToInt32(value)) : value);
							component.RPC(stateSyncEntry.RpcName, target, new object[1] { obj2 });
							num5++;
							num2++;
						}
						catch (Exception ex)
						{
							num4++;
							Verbose($"[StateSync] {stateSyncEntry.TypeName} 实例重发 {stateSyncEntry.RpcName} 失败 viewID={component.ViewID}: {ex.Message}");
						}
					}
					if (num5 > 0 || num6 > 0)
					{
						Verbose($"[StateSync] {stateSyncEntry.TypeName} → {target.NickName}: 已发 {num5}(跳过 {num6})");
					}
				}
				catch (Exception ex2)
				{
					num4++;
					LogWarning("[StateSync] 处理 " + stateSyncEntry.TypeName + " 整体失败:" + ex2.Message);
				}
			}
			LogInfo($"[StateSync] → {target.NickName}: 共处理 {num} 类组件,发 RPC {num2} 次,跳过 {num3},错误 {num4}。");
		}

		private static void ResolveEntryReflection(StateSyncEntry entry)
		{
			if (entry.ResolveAttempted)
			{
				return;
			}
			entry.ResolveAttempted = true;
			try
			{
				Type type = typeof(PlayerAvatar).Assembly.GetType(entry.TypeName, throwOnError: false);
				if (type == null)
				{
					Verbose("[StateSync] 未找到类型 " + entry.TypeName + ",跳过该项配置(游戏版本可能已变化)。");
					return;
				}
				FieldInfo fieldInfo = AccessTools.Field(type, entry.FieldName);
				if (fieldInfo == null)
				{
					Verbose("[StateSync] " + entry.TypeName + " 上没有字段 " + entry.FieldName + ",跳过该项配置。");
				}
				else
				{
					entry.ResolvedType = type;
					entry.ResolvedField = fieldInfo;
				}
			}
			catch (Exception ex)
			{
				LogWarning("[StateSync] 解析 " + entry.TypeName + "." + entry.FieldName + " 反射失败:" + ex.Message);
			}
		}

		internal static void NetworkManagerOnPlayerEnteredRoomPostfix(Player newPlayer)
		{
			if (!IsHookActive())
			{
				return;
			}
			Verbose(string.Format("[Photon] NetworkManager.OnPlayerEnteredRoom Postfix | name={0} actor={1} isMaster={2}", ((newPlayer != null) ? newPlayer.NickName : null) ?? "<null>", (newPlayer != null) ? new int?(newPlayer.ActorNumber) : null, PhotonNetwork.IsMasterClient));
			if (PhotonNetwork.IsMasterClient && newPlayer != null && PhotonNetwork.CurrentRoom != null)
			{
				bool flag = IsSnapshotNeededForCurrentScene();
				string currentSceneTag = GetCurrentSceneTag();
				Verbose($"[LateJoin] 当前场景标签={currentSceneTag} 需要快照={flag} 弹窗通知开关={JoinNotifyEnabled}");
				if (JoinNotifyEnabled && (Object)(object)Instance != (Object)null)
				{
					((MonoBehaviour)Instance).StartCoroutine(WaitAndShowJoinNotifyPopup(newPlayer.NickName));
				}
				if (flag)
				{
					_pendingLateJoiners.Add(newPlayer.ActorNumber);
					LogInfo($"[LateJoin] 玩家 {newPlayer.NickName} (Actor={newPlayer.ActorNumber}) 中途加入到 {currentSceneTag},等待他发 PlayerSpawnedRPC 后再发送快照。已登记为待发快照(pending {_pendingLateJoiners.Count} 人)。");
				}
			}
		}

		internal static void NetworkManagerOnPlayerLeftRoomPostfix(Player otherPlayer)
		{
			if (otherPlayer != null && _pendingLateJoiners.Remove(otherPlayer.ActorNumber))
			{
				Verbose($"[LateJoin] 玩家 {otherPlayer.NickName} (Actor={otherPlayer.ActorNumber}) 离开房间,从待发快照集合中移除。");
			}
		}

		internal static void NetworkManagerPlayerSpawnedRPCPostfix(PhotonMessageInfo _info)
		{
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			if (!IsHookActive() || !PhotonNetwork.IsMasterClient || PhotonNetwork.CurrentRoom == null)
			{
				return;
			}
			Player sender = _info.Sender;
			if (sender == null)
			{
				Verbose("[LateJoin] PlayerSpawnedRPC postfix: sender 为 null,跳过。");
				return;
			}
			if (sender.ActorNumber == PhotonNetwork.LocalPlayer.ActorNumber)
			{
				Verbose("[LateJoin] PlayerSpawnedRPC postfix: sender 是主机自己(" + sender.NickName + "),跳过。");
				return;
			}
			if (!_pendingLateJoiners.Contains(sender.ActorNumber))
			{
				Verbose($"[LateJoin] PlayerSpawnedRPC postfix: {sender.NickName} (Actor={sender.ActorNumber}) 不在待发快照集合中,跳过(多半是切关卡后的重新 spawn)。");
				return;
			}
			if (!IsSnapshotNeededForCurrentScene())
			{
				Verbose("[LateJoin] PlayerSpawnedRPC postfix: 当前场景不需要补快照,跳过 sender=" + sender.NickName + "。");
				return;
			}
			_pendingLateJoiners.Remove(sender.ActorNumber);
			LogInfo($"[LateJoin] 收到 {sender.NickName} (Actor={sender.ActorNumber}) 的 PlayerSpawnedRPC,启动延迟分阶段快照(保证客户端原版协程有时间设 Level)。");
			if ((Object)(object)Instance != (Object)null)
			{
				((MonoBehaviour)Instance).StartCoroutine(EnsurePlayerCorpseObjectsAndSnapshot(sender));
			}
		}

		[IteratorStateMachine(typeof(<EnsurePlayerCorpseObjectsAndSnapshot>d__113))]
		private static IEnumerator EnsurePlayerCorpseObjectsAndSnapshot(Player target)
		{
			//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
			return new <EnsurePlayerCorpseObjectsAndSnapshot>d__113(0)
			{
				target = target
			};
		}

		private static bool IsTargetStillOnline(Player target)
		{
			if (target == null)
			{
				return false;
			}
			if (PhotonNetwork.CurrentRoom == null)
			{
				return false;
			}
			return PhotonNetwork.CurrentRoom.Players.ContainsKey(target.ActorNumber);
		}

		private static string CurrentSceneName()
		{
			RunManager instance = RunManager.instance;
			object obj;
			if (instance == null)
			{
				obj = null;
			}
			else
			{
				Level levelCurrent = instance.levelCurrent;
				obj = ((levelCurrent != null) ? ((Object)levelCurrent).name : null);
			}
			if (obj == null)
			{
				obj = "<null>";
			}
			return (string)obj;
		}

		private static bool ShouldAbortSnapshot(Player target, string startScene, string stageHint)
		{
			if (!IsStaticModEnabled())
			{
				return true;
			}
			if (!PhotonNetwork.IsMasterClient)
			{
				return true;
			}
			if (!IsTargetStillOnline(target))
			{
				LogInfo("[LateJoin] 玩家 " + target.NickName + " 在 " + stageHint + " 已离线,取消快照。");
				return true;
			}
			string text = CurrentSceneName();
			if (text != startScene)
			{
				LogInfo("[LateJoin] " + stageHint + " 场景已切换(" + startScene + " → " + text + "),取消 " + target.NickName + " 的快照。");
				return true;
			}
			return false;
		}

		private static bool IsSnapshotNeededForCurrentScene()
		{
			try
			{
				if ((Object)(object)RunManager.instance == (Object)null)
				{
					return false;
				}
				return SemiFunc.RunIsLobby() || SemiFunc.RunIsShop() || SemiFunc.RunIsLevel();
			}
			catch
			{
				return false;
			}
		}

		private static string GetCurrentSceneTag()
		{
			try
			{
				if ((Object)(object)RunManager.instance == (Object)null)
				{
					return "<null>";
				}
				if (SemiFunc.RunIsLobby())
				{
					return "Lobby";
				}
				if (SemiFunc.RunIsLobbyMenu())
				{
					return "LobbyMenu";
				}
				if (SemiFunc.IsMainMenu())
				{
					return "MainMenu";
				}
				if (SemiFunc.RunIsShop())
				{
					return "Shop";
				}
				if (SemiFunc.RunIsArena())
				{
					return "Arena";
				}
				if (SemiFunc.RunIsLevel())
				{
					return "Level";
				}
				return "<unknown>";
			}
			catch
			{
				return "<error>";
			}
		}

		private static void EnsurePlayerCorpseObjects(Player target)
		{
			//IL_018d: Unknown result type (might be due to invalid IL or missing references)
			//IL_018e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0235: Unknown result type (might be due to invalid IL or missing references)
			//IL_0236: Unknown result type (might be due to invalid IL or missing references)
			if (!PhotonNetwork.IsMasterClient || target == null)
			{
				return;
			}
			try
			{
				if ((Object)(object)LevelGenerator.Instance == (Object)null)
				{
					Verbose("[EnsureCorpse] LevelGenerator.Instance 为 null,跳过补创。");
					return;
				}
				if ((Object)(object)LevelGenerator.Instance.PlayerDeathHeadPrefab == (Object)null || (Object)(object)LevelGenerator.Instance.PlayerTumblePrefab == (Object)null)
				{
					Verbose("[EnsureCorpse] PlayerDeathHeadPrefab 或 PlayerTumblePrefab 为 null,跳过补创。");
					return;
				}
				if ((Object)(object)GameDirector.instance == (Object)null || GameDirector.instance.PlayerList == null)
				{
					Verbose("[EnsureCorpse] GameDirector.instance.PlayerList 为 null,跳过补创。");
					return;
				}
				if (SemiFunc.RunIsLobby())
				{
					Verbose("[EnsureCorpse] 当前在 Lobby,跳过补创(关卡才需要)。");
					return;
				}
				Vector3 val = default(Vector3);
				((Vector3)(ref val))..ctor(0f, 3000f, 0f);
				PlayerAvatar val2 = null;
				foreach (PlayerAvatar player in GameDirector.instance.PlayerList)
				{
					if (!((Object)(object)player == (Object)null) && !((Object)(object)player.photonView == (Object)null) && player.photonView.Owner != null && player.photonView.Owner.ActorNumber == target.ActorNumber)
					{
						val2 = player;
						break;
					}
				}
				if ((Object)(object)val2 == (Object)null)
				{
					LogWarning("[EnsureCorpse] 在 GameDirector.PlayerList 里找不到 " + target.NickName + " 的 PlayerAvatar,跳过补创。");
					return;
				}
				if (_playerDeathHeadRef == null || _playerTumbleRef == null)
				{
					LogWarning("[EnsureCorpse] FieldRef PlayerAvatar.playerDeathHead/tumble 缓存失败,跳过补创。");
					return;
				}
				if ((Object)(object)_playerDeathHeadRef.Invoke(val2) == (Object)null)
				{
					GameObject val3 = PhotonNetwork.Instantiate(((Object)LevelGenerator.Instance.PlayerDeathHeadPrefab).name, val, Quaternion.identity, (byte)0, (object[])null);
					PlayerDeathHead component = val3.GetComponent<PlayerDeathHead>();
					component.playerAvatar = val2;
					_playerDeathHeadRef.Invoke(val2) = component;
					string nickName = target.NickName;
					PhotonView component2 = val3.GetComponent<PhotonView>();
					LogInfo($"[EnsureCorpse] 已为 {nickName} 补创 PlayerDeathHead | viewID={((component2 != null) ? new int?(component2.ViewID) : null)}");
				}
				else
				{
					Verbose("[EnsureCorpse] " + target.NickName + " 已经有 PlayerDeathHead,跳过。");
				}
				if ((Object)(object)_playerTumbleRef.Invoke(val2) == (Object)null)
				{
					GameObject val4 = PhotonNetwork.Instantiate(((Object)LevelGenerator.Instance.PlayerTumblePrefab).name, val, Quaternion.identity, (byte)0, (object[])null);
					PlayerTumble component3 = val4.GetComponent<PlayerTumble>();
					component3.playerAvatar = val2;
					_playerTumbleRef.Invoke(val2) = component3;
					string nickName2 = target.NickName;
					PhotonView component4 = val4.GetComponent<PhotonView>();
					LogInfo($"[EnsureCorpse] 已为 {nickName2} 补创 PlayerTumble | viewID={((component4 != null) ? new int?(component4.ViewID) : null)}");
				}
				else
				{
					Verbose("[EnsureCorpse] " + target.NickName + " 已经有 PlayerTumble,跳过。");
				}
			}
			catch (Exception ex)
			{
				LogWarning("[EnsureCorpse] 补创 PlayerDeathHead/PlayerTumble 失败:" + ex.Message + "\n" + ex.StackTrace);
			}
		}

		[IteratorStateMachine(typeof(<WaitHostGenerated>d__120))]
		private static IEnumerator WaitHostGenerated(Player target)
		{
			//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
			return new <WaitHostGenerated>d__120(0)
			{
				target = target
			};
		}

		[IteratorStateMachine(typeof(<SendGenerateDoneRetried>d__121))]
		private static IEnumerator SendGenerateDoneRetried(Player target)
		{
			//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
			return new <SendGenerateDoneRetried>d__121(0)
			{
				target = target
			};
		}

		private static void SendModuleSyncToLateJoiner(Player target)
		{
			if (_moduleConnectingTopRef == null || _moduleConnectingBottomRef == null || _moduleConnectingRightRef == null || _moduleConnectingLeftRef == null || _moduleFirstRef == null || _moduleSetupDoneRef == null)
			{
				LogWarning("[LateJoin] Module 内部字段反射缓存失败,跳过 ModuleConnectionSetRPC 重发。");
				return;
			}
			int num = 0;
			int num2 = 0;
			Module[] array = Object.FindObjectsOfType<Module>();
			foreach (Module val in array)
			{
				if ((Object)(object)val == (Object)null)
				{
					continue;
				}
				PhotonView component = ((Component)val).GetComponent<PhotonView>();
				if ((Object)(object)component == (Object)null)
				{
					num2++;
					continue;
				}
				if (!_moduleSetupDoneRef.Invoke(val))
				{
					num2++;
					continue;
				}
				try
				{
					component.RPC("ModuleConnectionSetRPC", target, new object[5]
					{
						_moduleConnectingTopRef.Invoke(val),
						_moduleConnectingBottomRef.Invoke(val),
						_moduleConnectingRightRef.Invoke(val),
						_moduleConnectingLeftRef.Invoke(val),
						_moduleFirstRef.Invoke(val)
					});
					num++;
				}
				catch (Exception ex)
				{
					Verbose($"[LateJoin] 重发 ModuleConnectionSetRPC 单个失败 viewID={component.ViewID}: {ex.Message}");
				}
			}
			LogInfo($"[LateJoin] 阶段 2.5/3 → {target.NickName}: 已重发 {num} 个 Module 的 ModuleConnectionSetRPC(跳过 {num2} 个未 SetupDone)。");
		}

		private static void SendValuableObjectSyncToLateJoiner(Player target)
		{
			if (_valuableDollarValueSetRef == null || _valuableDollarValueCurrentRef == null || _valuableDiscoveredRef == null || _valuableInStartRoomRef == null)
			{
				LogWarning("[LateJoin] ValuableObject 内部字段反射缓存失败,跳过 ValuableObject 状态重发。");
				return;
			}
			if ((Object)(object)ValuableDirector.instance == (Object)null || ValuableDirector.instance.valuableList == null)
			{
				Verbose("[LateJoin] ValuableDirector 未就绪,跳过 ValuableObject 状态重发。");
				return;
			}
			int num = 0;
			int num2 = 0;
			int num3 = 0;
			int num4 = 0;
			int num5 = 0;
			foreach (ValuableObject valuable in ValuableDirector.instance.valuableList)
			{
				if ((Object)(object)valuable == (Object)null)
				{
					continue;
				}
				num4++;
				PhotonView component = ((Component)valuable).GetComponent<PhotonView>();
				if ((Object)(object)component == (Object)null || component.ViewID == 0)
				{
					num5++;
					continue;
				}
				try
				{
					if (_valuableDollarValueSetRef.Invoke(valuable))
					{
						component.RPC("DollarValueSetRPC", target, new object[1] { _valuableDollarValueCurrentRef.Invoke(valuable) });
						num++;
					}
					if (_valuableDiscoveredRef.Invoke(valuable))
					{
						component.RPC("DiscoverRPC", target, Array.Empty<object>());
						num2++;
					}
					if (_valuableInStartRoomRef.Invoke(valuable))
					{
						component.RPC("AddToDollarHaulListRPC", target, Array.Empty<object>());
						num3++;
					}
				}
				catch (Exception ex)
				{
					Verbose($"[LateJoin] 重发 ValuableObject RPC 单个失败 viewID={component.ViewID}: {ex.Message}");
				}
			}
			LogInfo($"[LateJoin] 阶段 2.7/3 → {target.NickName}: ValuableObject 状态重发 总计={num4} value={num} discover={num2} haul={num3} 无ViewID={num5}。");
		}

		[IteratorStateMachine(typeof(<BroadcastLoadingAnimationCompleted>d__124))]
		private static IEnumerator BroadcastLoadingAnimationCompleted(Player target)
		{
			//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
			return new <BroadcastLoadingAnimationCompleted>d__124(0)
			{
				target = target
			};
		}

		[IteratorStateMachine(typeof(<SendCatchupSnapshotStaged>d__125))]
		private static IEnumerator SendCatchupSnapshotStaged(Player target)
		{
			//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
			return new <SendCatchupSnapshotStaged>d__125(0)
			{
				target = target
			};
		}

		internal static void HideRoomForChangeLevelCooldown()
		{
			if (PhotonNetwork.IsMasterClient && PhotonNetwork.CurrentRoom != null && !((Object)(object)Instance == (Object)null))
			{
				bool isOpen = PhotonNetwork.CurrentRoom.IsOpen;
				bool isVisible = PhotonNetwork.CurrentRoom.IsVisible;
				LockRoomNow();
				_changeLevelCooldownUntil = Time.unscaledTime + 600f;
				LogInfo($"[Enforce] 切关锁住中途加入 | IsOpen {isOpen}→false IsVisible {isVisible}→false | 等待主机 Generated=true 后再延迟 {5f:F0}s 解锁");
				if (!_changeLevelCooldownCoroutineRunning)
				{
					_changeLevelCooldownCoroutineRunning = true;
					((MonoBehaviour)Instance).StartCoroutine(WaitForHostGeneratedThenCooldownCoroutine());
				}
			}
		}

		[IteratorStateMachine(typeof(<WaitForHostGeneratedThenCooldownCoroutine>d__140))]
		private static IEnumerator WaitForHostGeneratedThenCooldownCoroutine()
		{
			//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
			return new <WaitForHostGeneratedThenCooldownCoroutine>d__140(0);
		}

		private static bool IsCooldownStillRelevant()
		{
			if (PhotonNetwork.IsMasterClient)
			{
				return PhotonNetwork.CurrentRoom != null;
			}
			return false;
		}

		private static bool LockRoomNow()
		{
			if (PhotonNetwork.CurrentRoom == null)
			{
				return false;
			}
			bool flag = false;
			if (PhotonNetwork.CurrentRoom.IsOpen)
			{
				PhotonNetwork.CurrentRoom.IsOpen = false;
				flag = true;
			}
			if (PhotonNetwork.CurrentRoom.IsVisible)
			{
				PhotonNetwork.CurrentRoom.IsVisible = false;
				flag = true;
			}
			if (flag)
			{
				try
				{
					SteamManager instance = SteamManager.instance;
					if (instance != null)
					{
						instance.LockLobby();
					}
				}
				catch (Exception ex)
				{
					Verbose("[Enforce] LockLobby 失败:" + ex.Message);
				}
			}
			return flag;
		}

		internal static void EnforceLobbyState()
		{
			if (!PhotonNetwork.IsMasterClient || PhotonNetwork.CurrentRoom == null || (Object)(object)SteamManager.instance == (Object)null)
			{
				return;
			}
			try
			{
				if (IsInChangeLevelCooldown)
				{
					EnforceCooldownState();
				}
				else if (IsCurrentSceneAllowed())
				{
					EnforceAllowedSceneState();
					_lastSceneAllowed = true;
				}
				else if (_lastSceneAllowed != false)
				{
					Verbose($"[Enforce] 当前场景不允许加入,保持原版行为 | IsOpen={PhotonNetwork.CurrentRoom.IsOpen} IsVisible={PhotonNetwork.CurrentRoom.IsVisible}");
					_lastSceneAllowed = false;
				}
			}
			catch (Exception ex)
			{
				LogWarning("维护房间开放状态失败:" + ex.Message + "\n" + ex.StackTrace);
			}
		}

		private static void EnforceCooldownState()
		{
			if (LockRoomNow())
			{
				Verbose($"[Enforce] 冷却期强制锁房 | 剩 {CooldownSecondsLeft:F1}s");
			}
		}

		private static void EnforceAllowedSceneState()
		{
			bool isOpen = PhotonNetwork.CurrentRoom.IsOpen;
			bool isVisible = PhotonNetwork.CurrentRoom.IsVisible;
			bool flag = false;
			if (!PhotonNetwork.CurrentRoom.IsOpen)
			{
				PhotonNetwork.CurrentRoom.IsOpen = true;
				flag = true;
				SteamManager.instance.UnlockLobby(true);
			}
			if (PublicVisibleSync && IsPublicGame())
			{
				if (!PhotonNetwork.CurrentRoom.IsVisible)
				{
					PhotonNetwork.CurrentRoom.IsVisible = true;
					flag = true;
				}
				if ((Object)(object)GameManager.instance != (Object)null)
				{
					GameManager.instance.SetConnectRandom(true);
				}
			}
			if (flag)
			{
				Verbose($"[Enforce] 房间状态已更新 | IsOpen {isOpen}→{PhotonNetwork.CurrentRoom.IsOpen} IsVisible {isVisible}→{PhotonNetwork.CurrentRoom.IsVisible} sceneAllowed=true");
			}
		}

		internal static void NetworkConnectOnConnectedToMasterPrefix()
		{
			if (ShouldAddRoomNamePrefix())
			{
				string text = _networkServerNameField.GetValue(DataDirector.instance) as string;
				if (!string.IsNullOrEmpty(text) && !HasRoomNamePrefix(text))
				{
					string text2 = (UseChinese() ? "[游戏中] " : "[In Game] ") + text;
					_networkServerNameField.SetValue(DataDirector.instance, text2);
					LogInfo("[Enforce] 公开房创建时加前缀 | '" + text + "' → '" + text2 + "'");
				}
			}
		}

		private static bool ShouldAddRoomNamePrefix()
		{
			if (!IsStaticModEnabled())
			{
				return false;
			}
			if (!CompatibilityReport.RuntimeReady)
			{
				return false;
			}
			if (!PublicRoomPrefixEnabled)
			{
				return false;
			}
			if ((Object)(object)DataDirector.instance == (Object)null || (Object)(object)GameManager.instance == (Object)null)
			{
				return false;
			}
			if (_networkServerNameField == null)
			{
				return false;
			}
			if (!IsPublicGame())
			{
				return false;
			}
			return true;
		}

		private static bool HasRoomNamePrefix(string name)
		{
			if (name != null)
			{
				if (!name.StartsWith("[游戏中] ", StringComparison.Ordinal))
				{
					return name.StartsWith("[In Game] ", StringComparison.Ordinal);
				}
				return true;
			}
			return false;
		}

		private static bool IsPublicGame()
		{
			if ((Object)(object)GameManager.instance == (Object)null)
			{
				return false;
			}
			try
			{
				if (CompatibilityReport.GameManagerConnectRandomRef != null)
				{
					return CompatibilityReport.GameManagerConnectRandomRef.Invoke(GameManager.instance);
				}
				if (CompatibilityReport.GameManagerConnectRandomField != null)
				{
					object value = CompatibilityReport.GameManagerConnectRandomField.GetValue(GameManager.instance);
					bool flag = default(bool);
					int num;
					if (value is bool)
					{
						flag = (bool)value;
						num = 1;
					}
					else
					{
						num = 0;
					}
					return (byte)((uint)num & (flag ? 1u : 0u)) != 0;
				}
			}
			catch
			{
			}
			return false;
		}

		internal static bool ClearInstantiationCacheById(int instantiationId)
		{
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Expected O, but got Unknown
			//IL_0037: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: Expected O, but got Unknown
			//IL_004c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0074: Unknown result type (might be due to invalid IL or missing references)
			if (instantiationId == 0)
			{
				return false;
			}
			if (!CompatibilityReport.CanCleanPhotonCache)
			{
				return false;
			}
			try
			{
				Hashtable val = (Hashtable)CompatibilityReport.PhotonRemoveFilter.GetValue(null);
				object value = CompatibilityReport.PhotonKeyByteSeven.GetValue(null);
				RaiseEventOptions val2 = (RaiseEventOptions)CompatibilityReport.PhotonServerCleanOptions.GetValue(null);
				val[value] = instantiationId;
				val2.CachingOption = (EventCaching)6;
				CompatibilityReport.PhotonRaiseEventInternal.Invoke(null, new object[4]
				{
					(byte)202,
					val,
					val2,
					SendOptions.SendReliable
				});
				return true;
			}
			catch (Exception ex)
			{
				Plugin instance = Instance;
				if (instance != null)
				{
					((BaseUnityPlugin)instance).Logger.LogWarning((object)$"清理 Photon 实例化缓存失败 (id={instantiationId}): {ex.Message}");
				}
				return false;
			}
		}

		internal static void ClearPhotonInstantiationCache(PhotonView photonView)
		{
			if (!((Object)(object)photonView == (Object)null))
			{
				ClearInstantiationCacheById(photonView.InstantiationId);
			}
		}

		internal static void ClearAllScenePhotonCache()
		{
			//IL_003f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				HashSet<int> hashSet = BuildPlayerPersistentViewIdSet();
				PhotonView[] array = Object.FindObjectsOfType<PhotonView>();
				int num = 0;
				int num2 = 0;
				int num3 = 0;
				int num4 = 0;
				PhotonView[] array2 = array;
				foreach (PhotonView val in array2)
				{
					if ((Object)(object)val == (Object)null)
					{
						num2++;
						continue;
					}
					Scene scene = ((Component)val).gameObject.scene;
					if (((Scene)(ref scene)).buildIndex == -1)
					{
						num2++;
					}
					else if (hashSet.Contains(val.ViewID) || IsPlayerPersistentByName(val))
					{
						num3++;
						Verbose(string.Format("[ClearCache] 跳过玩家持久组件 | viewID={0} name={1} owner={2}", val.ViewID, ((Object)((Component)val).gameObject).name, (val.Owner != null) ? val.Owner.NickName : "<null>"));
					}
					else if (val.InstantiationId == 0)
					{
						num4++;
					}
					else
					{
						ClearPhotonInstantiationCache(val);
						num++;
					}
				}
				Verbose($"[ClearCache] 已清理 {num} 个 PhotonView 缓存 | 跳过:玩家持久组件 {num3} / SceneView {num4} / 无效对象 {num2}");
			}
			catch (Exception ex)
			{
				LogWarning("批量清理 PhotonView 缓存失败:" + ex.Message + "\n" + ex.StackTrace);
			}
		}

		private static HashSet<int> BuildPlayerPersistentViewIdSet()
		{
			HashSet<int> hashSet = new HashSet<int>();
			if ((Object)(object)GameDirector.instance == (Object)null || GameDirector.instance.PlayerList == null)
			{
				return hashSet;
			}
			try
			{
				foreach (PlayerAvatar player in GameDirector.instance.PlayerList)
				{
					if ((Object)(object)player == (Object)null)
					{
						continue;
					}
					if ((Object)(object)player.photonView != (Object)null)
					{
						hashSet.Add(player.photonView.ViewID);
					}
					if (_playerTumbleRef == null)
					{
						continue;
					}
					try
					{
						PlayerTumble val = _playerTumbleRef.Invoke(player);
						if ((Object)(object)val != (Object)null)
						{
							PhotonView component = ((Component)val).GetComponent<PhotonView>();
							if ((Object)(object)component != (Object)null)
							{
								hashSet.Add(component.ViewID);
							}
						}
					}
					catch
					{
					}
				}
			}
			catch (Exception ex)
			{
				Verbose("[ClearCache] 构建玩家持久 ViewID 集合时异常:" + ex.Message);
			}
			return hashSet;
		}

		private static bool IsPlayerPersistentByName(PhotonView view)
		{
			if ((Object)(object)view == (Object)null || (Object)(object)((Component)view).gameObject == (Object)null)
			{
				return false;
			}
			string name = ((Object)((Component)view).gameObject).name;
			if (string.IsNullOrEmpty(name))
			{
				return false;
			}
			if (name.StartsWith("Voice", StringComparison.OrdinalIgnoreCase))
			{
				return true;
			}
			if (name.StartsWith("Player Avatar", StringComparison.OrdinalIgnoreCase))
			{
				return true;
			}
			if (name.StartsWith("Player Tumble", StringComparison.OrdinalIgnoreCase))
			{
				return true;
			}
			return false;
		}

		internal static void ClearRunManagerPunBufferedRpcs()
		{
			if (!CompatibilityReport.CanReadRunManagerPun)
			{
				Verbose("[ClearCache] CanReadRunManagerPun=false,跳过 RunManagerPUN 清理。");
				return;
			}
			if ((Object)(object)RunManager.instance == (Object)null)
			{
				Verbose("[ClearCache] RunManager.instance 为 null,跳过 RunManagerPUN 清理。");
				return;
			}
			try
			{
				RunManagerPUN val = CompatibilityReport.RunManagerPunRef.Invoke(RunManager.instance);
				if ((Object)(object)val == (Object)null)
				{
					Verbose("[ClearCache] RunManagerPUN 引用为 null,跳过。");
					return;
				}
				PhotonView val2 = CompatibilityReport.RunManagerPunPhotonViewRef.Invoke(val);
				if ((Object)(object)val2 == (Object)null)
				{
					Verbose("[ClearCache] RunManagerPUN.photonView 为 null,跳过。");
					return;
				}
				PhotonNetwork.RemoveBufferedRPCs(val2.ViewID, (string)null, (int[])null);
				Verbose($"[ClearCache] RunManagerPUN buffered RPC 已清理 | viewID={val2.ViewID}");
			}
			catch (Exception ex)
			{
				LogWarning("清理 RunManagerPUN buffered RPC 失败:" + ex.Message + "\n" + ex.StackTrace);
			}
		}

		private void InstallPatchesSafely()
		{
			PatchPrefix("RunManager.ChangeLevel Prefix", typeof(RunManager), "ChangeLevel", "RunManagerChangeLevelPrefix");
			PatchPostfix("RunManager.ChangeLevel Postfix", typeof(RunManager), "ChangeLevel", "RunManagerChangeLevelPostfix");
			PatchPrefix("LevelGenerator.Start Prefix", typeof(LevelGenerator), "Start", "LevelGeneratorStartPrefix");
			PatchPostfix("PlayerAvatar.Start Postfix", typeof(PlayerAvatar), "Start", "PlayerAvatarStartPostfix");
			PatchPrefix("PlayerAvatar.Spawn Prefix", typeof(PlayerAvatar), "Spawn", "PlayerAvatarSpawnPrefix");
			PatchPrefix("LoadingUI.LevelAnimationStart Prefix", typeof(LoadingUI), "LevelAnimationStart", "LoadingUILevelAnimationStartPrefix");
			PatchPrefix("PlayerAvatar.LoadingLevelAnimationCompletedRPC Prefix", typeof(PlayerAvatar), "LoadingLevelAnimationCompletedRPC", "PlayerAvatarLoadingLevelAnimationCompletedRPCPrefix");
			PatchPrefix("SemiFunc.OwnerOnlyRPC Prefix", typeof(SemiFunc), "OwnerOnlyRPC", "SemiFuncOwnerOnlyRPCPrefix");
			PatchPostfix("NetworkManager.OnPlayerEnteredRoom Postfix", typeof(NetworkManager), "OnPlayerEnteredRoom", "NetworkManagerOnPlayerEnteredRoomPostfix");
			PatchPostfix("NetworkManager.OnPlayerLeftRoom Postfix", typeof(NetworkManager), "OnPlayerLeftRoom", "NetworkManagerOnPlayerLeftRoomPostfix");
			PatchPrefix("NetworkConnect.OnConnectedToMaster Prefix", typeof(NetworkConnect), "OnConnectedToMaster", "NetworkConnectOnConnectedToMasterPrefix");
			PatchPostfix("NetworkManager.PlayerSpawnedRPC Postfix", typeof(NetworkManager), "PlayerSpawnedRPC", "NetworkManagerPlayerSpawnedRPCPostfix");
			PatchPrefix("GumballValuable.UpdateHypnosisLinesList Prefix", typeof(GumballValuable), "UpdateHypnosisLinesList", "GumballValuableUpdateHypnosisLinesListPrefix");
			PatchPostfix("ItemAttributes.Awake Postfix", typeof(ItemAttributes), "Awake", "ItemAttributesAwakePostfix");
			void PatchPostfix(string label, Type targetType, string methodName, string hookMethod)
			{
				TryPatch(label, delegate
				{
					//IL_002a: Unknown result type (might be due to invalid IL or missing references)
					//IL_0037: Expected O, but got Unknown
					harmony.Patch((MethodBase)AccessTools.Method(targetType, methodName, (Type[])null, (Type[])null), (HarmonyMethod)null, new HarmonyMethod(typeof(LateJoinNowHooks), hookMethod, (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
				});
			}
			void PatchPrefix(string label, Type targetType, string methodName, string hookMethod)
			{
				TryPatch(label, delegate
				{
					//IL_0029: Unknown result type (might be due to invalid IL or missing references)
					//IL_0037: Expected O, but got Unknown
					harmony.Patch((MethodBase)AccessTools.Method(targetType, methodName, (Type[])null, (Type[])null), new HarmonyMethod(typeof(LateJoinNowHooks), hookMethod, (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
				});
			}
		}

		private void TryPatch(string label, Action action)
		{
			try
			{
				action();
				((BaseUnityPlugin)this).Logger.LogInfo((object)("补丁安装:" + label + " ✅"));
			}
			catch (Exception ex)
			{
				CompatibilityReport.AffectedFeatures.Add(UseChinese() ? ("补丁失败:" + label) : ("Patch failed: " + label));
				CompatibilityReport.Details.Add(label + " → " + ex.Message);
				((BaseUnityPlugin)this).Logger.LogWarning((object)("补丁安装失败:" + label + " → " + ex.Message));
			}
		}

		private static void TryShowMenuPopup(MenuManager menuManager, string title, Color color, string body, string warnLabel)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				menuManager.PagePopUp(title, color, body, "OK", true);
				return;
			}
			catch
			{
			}
			try
			{
				menuManager.PagePopUpScheduled(title, color, body, "OK", true);
			}
			catch
			{
				Plugin instance = Instance;
				if (instance != null)
				{
					((BaseUnityPlugin)instance).Logger.LogWarning((object)("无法显示" + warnLabel + "弹窗。"));
				}
			}
		}

		[IteratorStateMachine(typeof(<WaitForMenuReady>d__160))]
		private IEnumerator WaitForMenuReady(float deadlineSeconds, Action<MenuManager> onReady)
		{
			//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
			return new <WaitForMenuReady>d__160(0)
			{
				deadlineSeconds = deadlineSeconds,
				onReady = onReady
			};
		}

		private static bool IsPopupSlotBusy(MenuManager menuManager)
		{
			//IL_004b: Unknown result type (might be due to invalid IL or missing references)
			//IL_004c: Unknown result type (might be due to invalid IL or missing references)
			//IL_004f: Invalid comparison between Unknown and I4
			//IL_0051: Unknown result type (might be due to invalid IL or missing references)
			//IL_0053: Invalid comparison between Unknown and I4
			if ((Object)(object)menuManager == (Object)null)
			{
				return true;
			}
			if (!CompatibilityReport.CanShowMenuPopup)
			{
				return true;
			}
			try
			{
				if ((Object)(object)CompatibilityReport.MenuCurrentMenuPageRef.Invoke(menuManager) == (Object)null)
				{
					return true;
				}
				if (CompatibilityReport.MenuPagePopUpScheduledRef.Invoke(menuManager))
				{
					return true;
				}
				MenuPageIndex val = CompatibilityReport.MenuCurrentMenuPageIndexRef.Invoke(menuManager);
				return (int)val == 9 || (int)val == 7;
			}
			catch
			{
				return true;
			}
		}

		[IteratorStateMachine(typeof(<WaitAndShowCompatPopup>d__162))]
		private IEnumerator WaitAndShowCompatPopup()
		{
			//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
			return new <WaitAndShowCompatPopup>d__162(0)
			{
				<>4__this = this
			};
		}

		private static string BuildCompatTitle()
		{
			if (!UseChinese())
			{
				return "LateJoinNow Compatibility";
			}
			return "LateJoinNow 兼容模式";
		}

		private static string BuildCompatBody()
		{
			StringBuilder stringBuilder = new StringBuilder();
			if (UseChinese())
			{
				stringBuilder.AppendLine("检测到游戏接口可能已变化,以下功能进入兼容模式:");
			}
			else
			{
				stringBuilder.AppendLine("Some game APIs may have changed. The following features may be unavailable:");
			}
			stringBuilder.AppendLine();
			stringBuilder.AppendLine("<size=85%>");
			foreach (string affectedFeature in CompatibilityReport.AffectedFeatures)
			{
				stringBuilder.Append("  • ").AppendLine(affectedFeature);
			}
			stringBuilder.AppendLine("</size>");
			stringBuilder.AppendLine();
			stringBuilder.Append("<size=90%><i>");
			stringBuilder.Append(UseChinese() ? "如需使用这些功能,请等待作者适配最新版本。" : "Please wait for the mod to be updated for the latest game version.");
			stringBuilder.Append("</i></size>");
			return stringBuilder.ToString();
		}

		[IteratorStateMachine(typeof(<WaitAndShowConflictPopup>d__165))]
		private IEnumerator WaitAndShowConflictPopup()
		{
			//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
			return new <WaitAndShowConflictPopup>d__165(0)
			{
				<>4__this = this
			};
		}

		private static string BuildConflictTitle()
		{
			if (!UseChinese())
			{
				return "LateJoinNow Conflict Warning";
			}
			return "LateJoinNow 冲突警告";
		}

		private static string BuildConflictBody()
		{
			StringBuilder stringBuilder = new StringBuilder();
			if (UseChinese())
			{
				stringBuilder.AppendLine("检测到本地启用了其他「中途加入」类模组:");
			}
			else
			{
				stringBuilder.AppendLine("Detected other late-join style mods alongside LateJoinNow:");
			}
			stringBuilder.AppendLine();
			stringBuilder.AppendLine("<size=85%>");
			foreach (string detectedConflictMod in ConflictDetect.DetectedConflictMods)
			{
				stringBuilder.Append("  • ").AppendLine(detectedConflictMod);
			}
			stringBuilder.AppendLine("</size>");
			stringBuilder.AppendLine();
			stringBuilder.Append("<b>");
			if (UseChinese())
			{
				stringBuilder.Append("建议在模组管理器中禁用上述模组,仅保留 LateJoinNow。");
			}
			else
			{
				stringBuilder.Append("Please disable those mods and keep only LateJoinNow.");
			}
			stringBuilder.AppendLine("</b>");
			stringBuilder.AppendLine();
			stringBuilder.Append("<size=85%><i>");
			stringBuilder.Append(UseChinese() ? "同时启用会出现状态污染、卡加载等问题。" : "Running them together causes state corruption and loading hangs.");
			stringBuilder.Append("</i></size>");
			return stringBuilder.ToString();
		}

		[IteratorStateMachine(typeof(<WaitAndShowJoinNotifyPopup>d__168))]
		internal static IEnumerator WaitAndShowJoinNotifyPopup(string playerName)
		{
			//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
			return new <WaitAndShowJoinNotifyPopup>d__168(0)
			{
				playerName = playerName
			};
		}

		private static bool TryShowInGameJoinMessage(string playerName)
		{
			//IL_0086: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				if ((Object)(object)RunManager.instance == (Object)null)
				{
					return false;
				}
				if (!SemiFunc.RunIsLobby() && !SemiFunc.RunIsShop() && !SemiFunc.RunIsLevel())
				{
					return false;
				}
				if ((Object)(object)ChatManager.instance == (Object)null)
				{
					return false;
				}
				string text = (UseChinese() ? ("[LateJoinNow] " + playerName + " 已加入房间") : ("[LateJoinNow] " + playerName + " joined the room"));
				ChatManager.instance.PossessChat((PossessChatID)0, text, 0.05f, new Color(0.4f, 1f, 0.55f), 0f, false, 0, (UnityEvent)null);
				return true;
			}
			catch
			{
				return false;
			}
		}

		private static string BuildJoinNotifyTitle()
		{
			if (!UseChinese())
			{
				return "Player Joined";
			}
			return "新玩家加入";
		}

		private static string BuildJoinNotifyBody(string playerName)
		{
			if (!UseChinese())
			{
				return "<b>" + playerName + "</b> has joined your room.";
			}
			return "玩家 <b>" + playerName + "</b> 已加入你的房间。";
		}
	}
	internal sealed class ConfigurationManagerAttributes
	{
		public int? Order;

		public bool? ReadOnly;

		public bool? Browsable;

		public bool? HideDefaultButton;
	}
	internal static class CompatibilityReport
	{
		public static FieldInfo PhotonRemoveFilter;

		public static FieldInfo PhotonKeyByteSeven;

		public static FieldInfo PhotonServerCleanOptions;

		public static MethodInfo PhotonRaiseEventInternal;

		public static FieldInfo GameManagerConnectRandomField;

		public static FieldInfo GameManagerLobbyTypeField;

		public static FieldRef<GameManager, LobbyTypes> GameManagerLobbyTypeRef;

		public static FieldRef<GameManager, bool> GameManagerConnectRandomRef;

		public static FieldRef<RunManager, RunManagerPUN> RunManagerPunRef;

		public static FieldRef<RunManagerPUN, PhotonView> RunManagerPunPhotonViewRef;

		public static FieldRef<PlayerAvatar, bool> PlayerAvatarSpawnedRef;

		public static FieldRef<MenuManager, bool> MenuPagePopUpScheduledRef;

		public static FieldRef<MenuManager, MenuPageIndex> MenuCurrentMenuPageIndexRef;

		public static FieldRef<MenuManager, MenuPage> MenuCurrentMenuPageRef;

		public static bool CanCleanPhotonCache;

		public static bool CanRefreshLevelGenerator;

		public static bool CanCatchupLateJoiner;

		public static bool CanShowMenuPopup;

		public static bool CanReadRunManagerPun;

		public static bool CanReadGameManagerLobbyState;

		public static bool CanAddRoomNamePrefix;

		public static bool CanFixGumballOverflow;

		public static bool CanGuardLoadingAnimation;

		public static bool CanEnsurePlayerCorpse;

		public static bool CanSyncModuleState;

		public static bool CanSyncValuableObjectState;

		public static bool HasIssues { get; private set; }

		public static bool RuntimeReady { get; private set; }

		public static List<string> AffectedFeatures { get; } = new List<string>();


		public static List<string> Details { get; } = new List<string>();


		public static void Build()
		{
			HasIssues = false;
			RuntimeReady = false;
			AffectedFeatures.Clear();
			Details.Clear();
			CanCleanPhotonCache = TryAll(() => RequireField(typeof(PhotonNetwork), "removeFilter", BindingFlags.Static | BindingFlags.NonPublic, ref PhotonRemoveFilter), () => RequireField(typeof(PhotonNetwork), "keyByteSeven", BindingFlags.Static | BindingFlags.NonPublic, ref PhotonKeyByteSeven), () => RequireField(typeof(PhotonNetwork), "ServerCleanOptions", BindingFlags.Static | BindingFlags.NonPublic, ref PhotonServerCleanOptions), () => RequireMethod(typeof(PhotonNetwork), "RaiseEventInternal", new Type[4]
			{
				typeof(byte),
				typeof(object),
				typeof(RaiseEventOptions),
				typeof(SendOptions)
			}, BindingFlags.Static | BindingFlags.NonPublic, ref PhotonRaiseEventInternal));
			if (!CanCleanPhotonCache)
			{
				AffectedFeatures.Add(Plugin.UseChinese() ? "清理 Photon 实例化缓存(晚加入者会看到陈旧物体)" : "Photon instantiation cache cleanup (late joiners may see stale objects)");
			}
			RequireField(typeof(GameManager), "connectRandom", BindingFlags.Instance | BindingFlags.NonPublic, ref GameManagerConnectRandomField);
			RequireField(typeof(GameManager), "lobbyType", BindingFlags.Instance | BindingFlags.NonPublic, ref GameManagerLobbyTypeField);
			try
			{
				if (GameManagerLobbyTypeField != null)
				{
					GameManagerLobbyTypeRef = AccessTools.FieldRefAccess<GameManager, LobbyTypes>("lobbyType");
				}
				if (GameManagerConnectRandomField != null)
				{
					GameManagerConnectRandomRef = AccessTools.FieldRefAccess<GameManager, bool>("connectRandom");
				}
			}
			catch (Exception ex)
			{
				Details.Add("GameManager FieldRef 缓存失败:" + ex.Message);
			}
			CanReadRunManagerPun = TryAll(() => RequireFieldRef<RunManager, RunManagerPUN>("runManagerPUN", out RunManagerPunRef), () => RequireFieldRef<RunManagerPUN, PhotonView>("photonView", out RunManagerPunPhotonViewRef));
			if (!CanReadRunManagerPun)
			{
				AffectedFeatures.Add(Plugin.UseChinese() ? "清理 RunManager 缓存" : "RunManager buffered RPC cleanup");
			}
			CanRefreshLevelGenerator = typeof(LevelGenerator) != null;
			if (!CanRefreshLevelGenerator)
			{
				AffectedFeatures.Add(Plugin.UseChinese() ? "Lobby 阶段刷新关卡生成器缓存" : "LevelGenerator buffered RPC refresh in Lobby");
			}
			CanCatchupLateJoiner = TryAll(() => RequireFieldRef<PlayerAvatar, bool>("spawned", out PlayerAvatarSpawnedRef), () => RequireMethodExists(typeof(PlayerAvatar), "LoadingLevelAnimationCompletedRPC"));
			if (!CanCatchupLateJoiner)
			{
				AffectedFeatures.Add(Plugin.UseChinese() ? "晚加入玩家自动跳过加载动画" : "Late joiner load-animation catch-up");
			}
			CanShowMenuPopup = TryAll(() => RequireFieldRef<MenuManager, bool>("pagePopUpScheduled", out MenuPagePopUpScheduledRef), () => RequireFieldRef<MenuManager, MenuPageIndex>("currentMenuPageIndex", out MenuCurrentMenuPageIndexRef), () => RequireFieldRef<MenuManager, MenuPage>("currentMenuPage", out MenuCurrentMenuPageRef));
			if (!CanShowMenuPopup)
			{
				AffectedFeatures.Add(Plugin.UseChinese() ? "菜单弹窗提示" : "Menu popup notifications");
			}
			CanReadGameManagerLobbyState = GameManagerConnectRandomField != null && GameManagerLobbyTypeField != null;
			if (!CanReadGameManagerLobbyState)
			{
				AffectedFeatures.Add(Plugin.UseChinese() ? "房间类型判定(HUD / 公开房名前缀可能失效)" : "Room type detection (HUD / public room prefix may not work)");
			}
			CanAddRoomNamePrefix = AccessTools.Field(typeof(DataDirector), "networkServerName") != null;
			if (!CanAddRoomNamePrefix)
			{
				Details.Add("缺失字段:DataDirector.networkServerName");
				AffectedFeatures.Add(Plugin.UseChinese() ? "公开房名加[游戏中]前缀" : "Public room name [In Game] prefix");
			}
			CanFixGumballOverflow = AccessTools.Field(typeof(GumballValuable), "hypnosisLines") != null && AccessTools.Field(typeof(GumballValuable), "hypnosisLine") != null;
			if (!CanFixGumballOverflow)
			{
				Details.Add("缺失字段:GumballValuable.hypnosisLines / hypnosisLine");
				AffectedFeatures.Add(Plugin.UseChinese() ? "修复 GumballValuable 玩家增加时越界崩溃" : "GumballValuable hypnosis lines overflow fix");
			}
			CanGuardLoadingAnimation = AccessTools.Field(typeof(LoadingUI), "levelAnimationStarted") != null && AccessTools.Field(typeof(LoadingUI), "levelAnimationCompleted") != null && AccessTools.Field(typeof(PlayerAvatar), "levelAnimationCompleted") != null;
			if (!CanGuardLoadingAnimation)
			{
				Details.Add("缺失字段:LoadingUI/PlayerAvatar.levelAnimationStarted/Completed");
				AffectedFeatures.Add(Plugin.UseChinese() ? "晚加入加载界面守门(避免卡黑屏)" : "Late join loading screen guard");
			}
			CanEnsurePlayerCorpse = AccessTools.Field(typeof(PlayerAvatar), "playerDeathHead") != null && AccessTools.Field(typeof(PlayerAvatar), "tumble") != null;
			if (!CanEnsurePlayerCorpse)
			{
				Details.Add("缺失字段:PlayerAvatar.playerDeathHead / tumble");
				AffectedFeatures.Add(Plugin.UseChinese() ? "晚加入者尸体/翻滚组件补创(避免出口区 NullRef)" : "Late joiner death head / tumble fallback");
			}
			CanSyncModuleState = AccessTools.Field(typeof(Module), "ConnectingTop") != null && AccessTools.Field(typeof(Module), "ConnectingBottom") != null && AccessTools.Field(typeof(Module), "ConnectingRight") != null && AccessTools.Field(typeof(Module), "ConnectingLeft") != null && AccessTools.Field(typeof(Module), "First") != null && AccessTools.Field(typeof(Module), "SetupDone") != null;
			if (!CanSyncModuleState)
			{
				Details.Add("缺失字段:Module.ConnectingTop/Bottom/Right/Left/First/SetupDone");
				AffectedFeatures.Add(Plugin.UseChinese() ? "晚加入者墙体/房间内饰同步" : "Late joiner walls / room interior sync");
			}
			CanSyncValuableObjectState = AccessTools.Field(typeof(ValuableObject), "dollarValueSet") != null && AccessTools.Field(typeof(ValuableObject), "dollarValueCurrent") != null && AccessTools.Field(typeof(ValuableObject), "discovered") != null && AccessTools.Field(typeof(ValuableObject), "inStartRoom") != null;
			if (!CanSyncValuableObjectState)
			{
				Details.Add("缺失字段:ValuableObject.dollarValueSet/dollarValueCurrent/discovered/inStartRoom");
				AffectedFeatures.Add(Plugin.UseChinese() ? "晚加入者宝物数值/地图标记/出口区清单同步" : "Late joiner valuable value / map marker / haul list sync");
			}
			HasIssues = AffectedFeatures.Count > 0;
			RuntimeReady = true;
		}

		private static bool TryAll(params Func<bool>[] checks)
		{
			bool