Decompiled source of PEAKAntiCheat v1.4.7

PEAKAntiCheat.dll

Decompiled a month ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using System.Text;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using BepInEx.Logging;
using ExitGames.Client.Photon;
using HarmonyLib;
using Photon.Pun;
using Photon.Realtime;
using Steamworks;
using UnityEngine;
using UnityEngine.SceneManagement;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyTitle("NoiseSuppression")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("NoiseSuppression")]
[assembly: AssemblyCopyright("Copyright ©  2025")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("c99807f0-dbec-4945-968a-6be06a6d91f2")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[assembly: AssemblyVersion("1.0.0.0")]
namespace AntiCheatMod;

public static class InviteLinkGenerator
{
	[CompilerGenerated]
	private sealed class <GenerateInviteLinkDelayed>d__2 : IEnumerator<object>, IDisposable, IEnumerator
	{
		private int <>1__state;

		private object <>2__current;

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

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

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

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

		private bool MoveNext()
		{
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: Expected O, but got Unknown
			//IL_00be: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bf: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ed: Unknown result type (might be due to invalid IL or missing references)
			switch (<>1__state)
			{
			default:
				return false;
			case 0:
				<>1__state = -1;
				<>2__current = (object)new WaitForSeconds(2f);
				<>1__state = 1;
				return true;
			case 1:
				<>1__state = -1;
				if (!PhotonNetwork.InRoom)
				{
					Debug.LogWarning((object)"[PEAK AntiCheat] No longer in room, skipping invite link generation");
					return false;
				}
				if (!PhotonNetwork.IsMasterClient)
				{
					Debug.Log((object)"[PEAK AntiCheat] Not master client, skipping invite link generation");
					return false;
				}
				if (_linkGenerated)
				{
					Debug.Log((object)"[PEAK AntiCheat] Invite link already generated for this room");
					return false;
				}
				try
				{
					if (!SteamManager.Initialized)
					{
						Debug.LogWarning((object)"[PEAK AntiCheat] Steam not initialized, cannot create invite link");
						return false;
					}
					SteamLobbyHandler service = GameHandler.GetService<SteamLobbyHandler>();
					if (service == null)
					{
						Debug.LogWarning((object)"[PEAK AntiCheat] SteamLobbyHandler not found");
						return false;
					}
					CSteamID val = default(CSteamID);
					if (!service.InSteamLobby(ref val))
					{
						Debug.LogWarning((object)"[PEAK AntiCheat] Not in a Steam lobby");
						return false;
					}
					CSteamID lobbyOwner = SteamMatchmaking.GetLobbyOwner(val);
					if (lobbyOwner == CSteamID.Nil)
					{
						Debug.LogWarning((object)"[PEAK AntiCheat] Could not get lobby owner");
						return false;
					}
					string text2 = (GUIUtility.systemCopyBuffer = $"steam://joinlobby/3527290/{val}/{lobbyOwner}");
					_linkGenerated = true;
					Debug.Log((object)("[PEAK AntiCheat] Invite link copied to clipboard: " + text2));
					AntiCheatPlugin.LogVisually("Invite link copied to clipboard!");
				}
				catch (Exception ex)
				{
					Debug.LogError((object)("[PEAK AntiCheat] Error creating invite link: " + ex.Message));
				}
				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();
		}
	}

	private static bool _linkGenerated;

	public static void OnJoinedRoom()
	{
		_linkGenerated = false;
		if ((Object)(object)AntiCheatPlugin.Instance != (Object)null)
		{
			((MonoBehaviour)AntiCheatPlugin.Instance).StartCoroutine(GenerateInviteLinkDelayed());
		}
	}

	[IteratorStateMachine(typeof(<GenerateInviteLinkDelayed>d__2))]
	private static IEnumerator GenerateInviteLinkDelayed()
	{
		//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
		return new <GenerateInviteLinkDelayed>d__2(0);
	}
}
public enum AntiCheatNetEvent : byte
{
	DetectionReport = 100,
	BlockListUpdate,
	DetectionSettingsUpdate,
	WhitelistUpdate,
	SyncRequest,
	SyncResponse,
	CheatModDetected,
	KickPlayer
}
public static class AntiCheatEvents
{
	public static event Action<Player, string, CSteamID, string> OnCheaterDetected;

	public static event Action<DetectionType, Player, string> OnDetectionTriggered;

	public static event Action<Player, bool> OnPlayerBlockStatusChanged;

	public static event Action<Player> OnPlayerKicked;

	public static void NotifyCheaterDetected(Player player, string reason, CSteamID steamID)
	{
		//IL_001f: Unknown result type (might be due to invalid IL or missing references)
		string arg = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
		AntiCheatEvents.OnCheaterDetected?.Invoke(player, reason, steamID, arg);
	}

	public static void NotifyDetectionTriggered(DetectionType type, Player player, string reason)
	{
		AntiCheatEvents.OnDetectionTriggered?.Invoke(type, player, reason);
	}

	public static void NotifyPlayerBlockStatusChanged(Player player, bool isBlocked)
	{
		AntiCheatEvents.OnPlayerBlockStatusChanged?.Invoke(player, isBlocked);
	}

	public static void NotifyPlayerKicked(Player player)
	{
		AntiCheatEvents.OnPlayerKicked?.Invoke(player);
	}
}
[BepInPlugin("com.hiccup444.anticheat", "PEAK Anticheat", "1.4.7")]
public class AntiCheatPlugin : BaseUnityPlugin, IConnectionCallbacks, IMatchmakingCallbacks, IInRoomCallbacks, IOnEventCallback
{
	[CompilerGenerated]
	private sealed class <>c__DisplayClass89_0
	{
		public CSteamID steamId;

		public bool receivedUpdate;

		internal void <WaitForPersonaStateChange>b__0(PersonaStateChange_t param)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			if (param.m_ulSteamID == steamId.m_SteamID && (param.m_nChangeFlags & 1) != 0)
			{
				receivedUpdate = true;
				Logger.LogInfo((object)$"Received PersonaStateChange for {steamId} - name was updated");
			}
		}
	}

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

		private object <>2__current;

		public AntiCheatPlugin <>4__this;

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

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

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

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

		private bool MoveNext()
		{
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Expected O, but got Unknown
			int num = <>1__state;
			AntiCheatPlugin antiCheatPlugin = <>4__this;
			switch (num)
			{
			default:
				return false;
			case 0:
				<>1__state = -1;
				<>2__current = (object)new WaitForSeconds(3f);
				<>1__state = 1;
				return true;
			case 1:
			{
				<>1__state = -1;
				Player[] playerList = PhotonNetwork.PlayerList;
				foreach (Player val in playerList)
				{
					if (val.ActorNumber != PhotonNetwork.LocalPlayer.ActorNumber)
					{
						antiCheatPlugin.CheckPlayerForCheatMods(val);
					}
				}
				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 <CheckNewPlayerDelayed>d__105 : IEnumerator<object>, IDisposable, IEnumerator
	{
		private int <>1__state;

		private object <>2__current;

		public AntiCheatPlugin <>4__this;

		public Player player;

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

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

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

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

		private bool MoveNext()
		{
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Expected O, but got Unknown
			int num = <>1__state;
			AntiCheatPlugin antiCheatPlugin = <>4__this;
			switch (num)
			{
			default:
				return false;
			case 0:
				<>1__state = -1;
				<>2__current = (object)new WaitForSeconds(2f);
				<>1__state = 1;
				return true;
			case 1:
				<>1__state = -1;
				antiCheatPlugin.CheckPlayerForCheatMods(player);
				((MonoBehaviour)antiCheatPlugin).StartCoroutine(antiCheatPlugin.SecondaryCheatModCheck(player));
				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 <CheckPlayersForCheats>d__85 : IEnumerator<object>, IDisposable, IEnumerator
	{
		private int <>1__state;

		private object <>2__current;

		public AntiCheatPlugin <>4__this;

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

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

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

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

		private bool MoveNext()
		{
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Expected O, but got Unknown
			int num = <>1__state;
			AntiCheatPlugin antiCheatPlugin = <>4__this;
			if (num != 0)
			{
				if (num != 1)
				{
					return false;
				}
				<>1__state = -1;
				if (PhotonNetwork.InRoom)
				{
					Player[] playerList = PhotonNetwork.PlayerList;
					foreach (Player player in playerList)
					{
						antiCheatPlugin.CheckPlayerForCheatMods(player);
					}
				}
			}
			else
			{
				<>1__state = -1;
			}
			<>2__current = (object)new WaitForSeconds(5f);
			<>1__state = 1;
			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 <CheckPlayersWithoutAnticheat>d__125 : IEnumerator<object>, IDisposable, IEnumerator
	{
		private int <>1__state;

		private object <>2__current;

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

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

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

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

		private bool MoveNext()
		{
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: Expected O, but got Unknown
			//IL_00bc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d1: Unknown result type (might be due to invalid IL or missing references)
			int num = <>1__state;
			if (num != 0)
			{
				if (num != 1)
				{
					return false;
				}
				<>1__state = -1;
				if (PhotonNetwork.InRoom && PhotonNetwork.IsMasterClient && AutoBlockNoAnticheat)
				{
					DateTime now = DateTime.Now;
					List<int> list = new List<int>();
					Player[] playerList = PhotonNetwork.PlayerList;
					foreach (Player val in playerList)
					{
						if (val.ActorNumber == PhotonNetwork.LocalPlayer.ActorNumber || val.IsMasterClient)
						{
							continue;
						}
						DateTime value;
						if (!_anticheatUsers.ContainsKey(val.ActorNumber) && !_playersWithoutAnticheat.ContainsKey(val.ActorNumber))
						{
							CSteamID playerSteamID = GetPlayerSteamID(val);
							if (playerSteamID != CSteamID.Nil && BlockingManager.IsWhitelisted(playerSteamID.m_SteamID))
							{
								Logger.LogInfo((object)("[AntiCheat] Player " + val.NickName + " is whitelisted - not tracking for anticheat timeout"));
								BlockingManager.GrantImmunity(val.ActorNumber);
							}
							else if (BlockingManager.IsBlocked(val.ActorNumber))
							{
								Logger.LogInfo((object)("[AntiCheat] Player " + val.NickName + " is already blocked - not tracking for anticheat timeout"));
							}
						}
						else if (!_anticheatUsers.ContainsKey(val.ActorNumber) && _playersWithoutAnticheat.TryGetValue(val.ActorNumber, out value) && (now - value).TotalSeconds >= 10.0 && !BlockingManager.IsBlocked(val.ActorNumber))
						{
							list.Add(val.ActorNumber);
						}
						else if (BlockingManager.IsBlocked(val.ActorNumber) && _playersWithoutAnticheat.ContainsKey(val.ActorNumber))
						{
							Logger.LogInfo((object)("[AntiCheat] Player " + val.NickName + " is already blocked - removing from anticheat timeout tracking"));
							_playersWithoutAnticheat.Remove(val.ActorNumber);
						}
					}
					foreach (int item in list)
					{
						Room currentRoom = PhotonNetwork.CurrentRoom;
						Player val2 = ((currentRoom != null) ? currentRoom.GetPlayer(item, false) : null);
						if (val2 != null)
						{
							if (!BlockingManager.HasImmunity(item))
							{
								Logger.LogWarning((object)("[AUTO BLOCK] Player " + val2.NickName + " has no anticheat - auto-blocking"));
								LogVisually("{userColor}" + val2.NickName + "</color> {leftColor}has no anticheat - auto-blocked</color>", onlySendOnce: false, sfxJoin: false, sfxLeave: true);
								BlockPlayer(val2, "No anticheat installed", DetectionType.SteamIDSpoofing);
							}
							else
							{
								Logger.LogInfo((object)$"[AUTO BLOCK] Skipping auto-block for immune player {val2.NickName} (Actor #{item})");
							}
							_playersWithoutAnticheat.Remove(item);
						}
					}
				}
			}
			else
			{
				<>1__state = -1;
			}
			<>2__current = (object)new WaitForSeconds(2f);
			<>1__state = 1;
			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 <RemoveDetectionFromRecent>d__55 : IEnumerator<object>, IDisposable, IEnumerator
	{
		private int <>1__state;

		private object <>2__current;

		public float delay;

		public string detectionKey;

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

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

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

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

		private bool MoveNext()
		{
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: Expected O, but got Unknown
			switch (<>1__state)
			{
			default:
				return false;
			case 0:
				<>1__state = -1;
				<>2__current = (object)new WaitForSeconds(delay);
				<>1__state = 1;
				return true;
			case 1:
				<>1__state = -1;
				_recentDetections.Remove(detectionKey);
				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 <SecondaryCheatModCheck>d__108 : IEnumerator<object>, IDisposable, IEnumerator
	{
		private int <>1__state;

		private object <>2__current;

		public Player player;

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

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

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

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

		private bool MoveNext()
		{
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: Expected O, but got Unknown
			//IL_0072: Unknown result type (might be due to invalid IL or missing references)
			//IL_0078: Expected O, but got Unknown
			//IL_0093: Unknown result type (might be due to invalid IL or missing references)
			switch (<>1__state)
			{
			default:
				return false;
			case 0:
				<>1__state = -1;
				<>2__current = (object)new WaitForSeconds(5f);
				<>1__state = 1;
				return true;
			case 1:
				<>1__state = -1;
				if (PhotonNetwork.IsMasterClient && player.ActorNumber != PhotonNetwork.LocalPlayer.ActorNumber)
				{
					object[] array = new object[1] { player.ActorNumber };
					RaiseEventOptions val = new RaiseEventOptions();
					val.TargetActors = new int[1] { player.ActorNumber };
					PhotonNetwork.RaiseEvent((byte)70, (object)array, val, SendOptions.SendReliable);
					Logger.LogInfo((object)("[SECONDARY CHECK] Sent secondary cheat mod check to " + player.NickName));
				}
				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 <SendAntiCheatPingDelayed>d__122 : IEnumerator<object>, IDisposable, IEnumerator
	{
		private int <>1__state;

		private object <>2__current;

		public AntiCheatPlugin <>4__this;

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

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

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

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

		private bool MoveNext()
		{
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: Expected O, but got Unknown
			int num = <>1__state;
			AntiCheatPlugin antiCheatPlugin = <>4__this;
			switch (num)
			{
			default:
				return false;
			case 0:
				<>1__state = -1;
				Logger.LogInfo((object)"[AntiCheat] SendAntiCheatPingDelayed started - waiting 1 second...");
				<>2__current = (object)new WaitForSeconds(1f);
				<>1__state = 1;
				return true;
			case 1:
				<>1__state = -1;
				Logger.LogInfo((object)"[AntiCheat] SendAntiCheatPingDelayed finished waiting - calling SendAntiCheatPing");
				antiCheatPlugin.SendAntiCheatPing();
				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 <SendAntiCheatPingToAllExistingPlayers>d__107 : IEnumerator<object>, IDisposable, IEnumerator
	{
		private int <>1__state;

		private object <>2__current;

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

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

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

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

		private bool MoveNext()
		{
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: Expected O, but got Unknown
			//IL_00c3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ca: Expected O, but got Unknown
			//IL_00ea: Unknown result type (might be due to invalid IL or missing references)
			switch (<>1__state)
			{
			default:
				return false;
			case 0:
				<>1__state = -1;
				<>2__current = (object)new WaitForSeconds(1f);
				<>1__state = 1;
				return true;
			case 1:
			{
				<>1__state = -1;
				if (!PhotonNetwork.IsConnected || !PhotonNetwork.InRoom || PhotonNetwork.LocalPlayer == null)
				{
					return false;
				}
				Player[] array = PhotonNetwork.CurrentRoom.Players.Values.Where((Player p) => p.ActorNumber != PhotonNetwork.LocalPlayer.ActorNumber).ToArray();
				if (array.Length == 0)
				{
					return false;
				}
				object[] array2 = new object[3]
				{
					PhotonNetwork.LocalPlayer.NickName,
					PhotonNetwork.LocalPlayer.UserId,
					"1.4.7"
				};
				Player[] array3 = array;
				foreach (Player val in array3)
				{
					RaiseEventOptions val2 = new RaiseEventOptions();
					val2.TargetActors = new int[1] { val.ActorNumber };
					RaiseEventOptions val3 = val2;
					PhotonNetwork.RaiseEvent((byte)69, (object)array2, val3, SendOptions.SendReliable);
					Logger.LogInfo((object)("[AntiCheat] Sent anticheat ping to existing player " + val.NickName));
				}
				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 <SendAntiCheatPingToNewPlayer>d__106 : IEnumerator<object>, IDisposable, IEnumerator
	{
		private int <>1__state;

		private object <>2__current;

		public Player newPlayer;

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

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

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

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

		private bool MoveNext()
		{
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: Expected O, but got Unknown
			//IL_0098: Unknown result type (might be due to invalid IL or missing references)
			//IL_009e: Expected O, but got Unknown
			//IL_00be: Unknown result type (might be due to invalid IL or missing references)
			switch (<>1__state)
			{
			default:
				return false;
			case 0:
				<>1__state = -1;
				<>2__current = (object)new WaitForSeconds(1f);
				<>1__state = 1;
				return true;
			case 1:
			{
				<>1__state = -1;
				if (!PhotonNetwork.IsConnected || !PhotonNetwork.InRoom || PhotonNetwork.LocalPlayer == null)
				{
					return false;
				}
				Room currentRoom = PhotonNetwork.CurrentRoom;
				if (((currentRoom != null) ? currentRoom.GetPlayer(newPlayer.ActorNumber, false) : null) == null)
				{
					return false;
				}
				object[] array = new object[3]
				{
					PhotonNetwork.LocalPlayer.NickName,
					PhotonNetwork.LocalPlayer.UserId,
					"1.4.7"
				};
				RaiseEventOptions val = new RaiseEventOptions();
				val.TargetActors = new int[1] { newPlayer.ActorNumber };
				RaiseEventOptions val2 = val;
				PhotonNetwork.RaiseEvent((byte)69, (object)array, val2, SendOptions.SendReliable);
				Logger.LogInfo((object)("[AntiCheat] Sent anticheat ping to new player " + newPlayer.NickName));
				if (AutoBlockNoAnticheat && !_anticheatUsers.ContainsKey(newPlayer.ActorNumber))
				{
					_playersWithoutAnticheat[newPlayer.ActorNumber] = DateTime.Now;
					Logger.LogInfo((object)("[AntiCheat] Started tracking " + newPlayer.NickName + " for anticheat timeout (10s from ping)"));
				}
				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 <SendSyncToAllClients>d__91 : IEnumerator<object>, IDisposable, IEnumerator
	{
		private int <>1__state;

		private object <>2__current;

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

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

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

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

		private bool MoveNext()
		{
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: Expected O, but got Unknown
			//IL_00c8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cf: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d6: Expected O, but got Unknown
			//IL_00dc: Unknown result type (might be due to invalid IL or missing references)
			switch (<>1__state)
			{
			default:
				return false;
			case 0:
				<>1__state = -1;
				<>2__current = (object)new WaitForSeconds(1f);
				<>1__state = 1;
				return true;
			case 1:
				<>1__state = -1;
				if (PhotonNetwork.IsMasterClient)
				{
					Logger.LogInfo((object)"[MASTER CLIENT] Sending sync data to all clients");
					int[] array = (from b in BlockingManager.GetAllBlockedPlayers()
						select b.ActorNumber).ToArray();
					object[] array2 = DetectionManager.SerializeSettings();
					long[] array3 = (from id in BlockingManager.GetWhitelistedSteamIDs()
						select (long)id).ToArray();
					object[] array4 = new object[3] { array, array2, array3 };
					RaiseEventOptions val = new RaiseEventOptions
					{
						Receivers = (ReceiverGroup)0
					};
					PhotonNetwork.RaiseEvent((byte)105, (object)array4, val, SendOptions.SendReliable);
				}
				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 <SendUnauthorizedBananaSlipToMaster>d__119 : IEnumerator<object>, IDisposable, IEnumerator
	{
		private int <>1__state;

		private object <>2__current;

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

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

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

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

		private bool MoveNext()
		{
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: Expected O, but got Unknown
			//IL_00d9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00de: Unknown result type (might be due to invalid IL or missing references)
			switch (<>1__state)
			{
			default:
				return false;
			case 0:
				<>1__state = -1;
				<>2__current = (object)new WaitForSeconds(3f);
				<>1__state = 1;
				return true;
			case 1:
			{
				<>1__state = -1;
				Character val = null;
				Character[] array = Object.FindObjectsOfType<Character>();
				foreach (Character val2 in array)
				{
					PhotonView component = ((Component)val2).GetComponent<PhotonView>();
					if ((Object)(object)component != (Object)null && component.Owner != null && component.Owner.IsMasterClient)
					{
						val = val2;
						break;
					}
				}
				if ((Object)(object)val == (Object)null)
				{
					Logger.LogWarning((object)"[AntiCheat] Could not find master client's character for cheat mod detection");
					return false;
				}
				PhotonView component2 = ((Component)val).GetComponent<PhotonView>();
				if ((Object)(object)component2 == (Object)null)
				{
					Logger.LogWarning((object)"[AntiCheat] Master client's character has no PhotonView");
					return false;
				}
				BananaPeel val3 = Object.FindFirstObjectByType<BananaPeel>();
				if ((Object)(object)val3 == (Object)null)
				{
					val3 = PhotonNetwork.Instantiate("0_Items/Berrynana Peel Pink Variant", val.Head, Quaternion.identity, (byte)0, (object[])null).GetComponent<BananaPeel>();
					Logger.LogWarning((object)"[AntiCheat] Spawned banana peel for cheat detection");
				}
				Logger.LogWarning((object)$"[AntiCheat] Cheat mod detected - sending unauthorized banana slip RPC to banana peel (ViewID: {((Component)val3).GetComponent<PhotonView>().ViewID})");
				((Component)val3).GetComponent<PhotonView>().RPC("RPCA_TriggerBanana", (RpcTarget)0, new object[1] { component2.ViewID });
				Logger.LogWarning((object)"[AntiCheat] Unauthorized banana slip RPC sent - should trigger detection on master client");
				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 <SendUnauthorizedBananaSlipToMasterDelayed>d__121 : IEnumerator<object>, IDisposable, IEnumerator
	{
		private int <>1__state;

		private object <>2__current;

		public AntiCheatPlugin <>4__this;

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

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

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

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

		private bool MoveNext()
		{
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: Expected O, but got Unknown
			int num = <>1__state;
			AntiCheatPlugin antiCheatPlugin = <>4__this;
			switch (num)
			{
			default:
				return false;
			case 0:
				<>1__state = -1;
				<>2__current = (object)new WaitForSeconds(5f);
				<>1__state = 1;
				return true;
			case 1:
				<>1__state = -1;
				<>2__current = ((MonoBehaviour)antiCheatPlugin).StartCoroutine(antiCheatPlugin.SendUnauthorizedBananaSlipToMaster());
				<>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 <ShowAnticheatLoadedMessage>d__49 : IEnumerator<object>, IDisposable, IEnumerator
	{
		private int <>1__state;

		private object <>2__current;

		private float <roomTimeout>5__2;

		private float <roomElapsed>5__3;

		private float <timeout>5__4;

		private float <elapsed>5__5;

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

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

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

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

		private bool MoveNext()
		{
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_003c: Expected O, but got Unknown
			//IL_006a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0074: Expected O, but got Unknown
			//IL_00f9: Unknown result type (might be due to invalid IL or missing references)
			//IL_0103: Expected O, but got Unknown
			switch (<>1__state)
			{
			default:
				return false;
			case 0:
				<>1__state = -1;
				_startupMessageShown = true;
				<>2__current = (object)new WaitForSeconds(0.25f);
				<>1__state = 1;
				return true;
			case 1:
				<>1__state = -1;
				<roomTimeout>5__2 = 10f;
				<roomElapsed>5__3 = 0f;
				goto IL_0096;
			case 2:
				<>1__state = -1;
				<roomElapsed>5__3 += 0.25f;
				goto IL_0096;
			case 3:
				{
					<>1__state = -1;
					<elapsed>5__5 += 0.25f;
					_connectionLog = Object.FindObjectOfType<PlayerConnectionLog>();
					if ((Object)(object)_connectionLog != (Object)null)
					{
						Logger.LogInfo((object)"[PEAKAntiCheat] Found PlayerConnectionLog, initializing reflection cache");
						InitializeReflectionCache();
					}
					break;
				}
				IL_0096:
				if (!PhotonNetwork.InRoom && <roomElapsed>5__3 < <roomTimeout>5__2)
				{
					<>2__current = (object)new WaitForSeconds(0.25f);
					<>1__state = 2;
					return true;
				}
				if (!PhotonNetwork.InRoom)
				{
					Logger.LogWarning((object)"[PEAKAntiCheat] Not in room after timeout, skipping anticheat loaded message");
					return false;
				}
				if (!PhotonNetwork.IsMasterClient)
				{
					Logger.LogInfo((object)"[PEAKAntiCheat] Not master client, skipping anticheat loaded message");
					return false;
				}
				<timeout>5__4 = 5f;
				<elapsed>5__5 = 0f;
				break;
			}
			if ((Object)(object)_connectionLog == (Object)null && <elapsed>5__5 < <timeout>5__4)
			{
				<>2__current = (object)new WaitForSeconds(0.25f);
				<>1__state = 3;
				return true;
			}
			if ((Object)(object)_connectionLog != (Object)null)
			{
				Logger.LogInfo((object)"[PEAKAntiCheat] Showing anticheat loaded message");
				LogVisually("{joinedColor}Anticheat loaded! Press F2 to open manager.</color>", onlySendOnce: false, sfxJoin: true);
			}
			else
			{
				Logger.LogWarning((object)"[PEAKAntiCheat] PlayerConnectionLog not found after timeout, message will be queued");
				LogVisually("{joinedColor}Anticheat loaded! Press F2 to open manager.</color>", onlySendOnce: false, sfxJoin: 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 <TestUIGameObject>d__48 : IEnumerator<object>, IDisposable, IEnumerator
	{
		private int <>1__state;

		private object <>2__current;

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

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

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

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

		private bool MoveNext()
		{
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: Expected O, but got Unknown
			switch (<>1__state)
			{
			default:
				return false;
			case 0:
				<>1__state = -1;
				<>2__current = (object)new WaitForSeconds(2f);
				<>1__state = 1;
				return true;
			case 1:
			{
				<>1__state = -1;
				GameObject val = GameObject.Find("AntiCheatUI");
				if ((Object)(object)val != (Object)null)
				{
					Logger.LogInfo((object)$"[PEAKAntiCheat] Found UI GameObject: {((Object)val).name}, Active: {val.activeInHierarchy}");
					AntiCheatUI component = val.GetComponent<AntiCheatUI>();
					if ((Object)(object)component != (Object)null)
					{
						Logger.LogInfo((object)$"[PEAKAntiCheat] Found UI component: {((Behaviour)component).enabled}");
					}
					else
					{
						Logger.LogWarning((object)"[PEAKAntiCheat] UI component not found!");
					}
				}
				else
				{
					Logger.LogWarning((object)"[PEAKAntiCheat] UI GameObject not found!");
				}
				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 <TrackModListOptOut>d__145 : IEnumerator<object>, IDisposable, IEnumerator
	{
		private int <>1__state;

		private object <>2__current;

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

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

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

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

		private bool MoveNext()
		{
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: Expected O, but got Unknown
			switch (<>1__state)
			{
			default:
				return false;
			case 0:
				<>1__state = -1;
				<>2__current = (object)new WaitForSeconds(3f);
				<>1__state = 1;
				return true;
			case 1:
				<>1__state = -1;
				foreach (Player value in PhotonNetwork.CurrentRoom.Players.Values)
				{
					if (value.ActorNumber != PhotonNetwork.LocalPlayer.ActorNumber && !_playerModLists.ContainsKey(value.ActorNumber))
					{
						_playersOptedOutOfModSharing.Add(value.ActorNumber);
						Logger.LogInfo((object)("[PEAKAntiCheat] Player " + value.NickName + " has opted out of mod sharing"));
					}
				}
				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 <TrackPlayerCoordinates>d__110 : IEnumerator<object>, IDisposable, IEnumerator
	{
		private int <>1__state;

		private object <>2__current;

		public AntiCheatPlugin <>4__this;

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

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

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

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

		private bool MoveNext()
		{
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Expected O, but got Unknown
			//IL_008d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0092: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a5: Unknown result type (might be due to invalid IL or missing references)
			int num = <>1__state;
			AntiCheatPlugin antiCheatPlugin = <>4__this;
			if (num != 0)
			{
				if (num != 1)
				{
					return false;
				}
				<>1__state = -1;
				if (PhotonNetwork.InRoom)
				{
					Character[] array = Object.FindObjectsOfType<Character>();
					foreach (Character val in array)
					{
						PhotonView component = ((Component)val).GetComponent<PhotonView>();
						if (!((Object)(object)component == (Object)null) && component.Owner != null && !IsBlocked(component.Owner.ActorNumber))
						{
							Vector3 position = ((Component)val).transform.position;
							_playerLastKnownCoordinates[component.Owner.ActorNumber] = position;
							_playerCoordinateTimestamps[component.Owner.ActorNumber] = DateTime.Now;
							if (PhotonNetwork.IsMasterClient)
							{
								antiCheatPlugin.CheckAndRescuePlayerFromInfinity(val, component.Owner);
							}
						}
					}
				}
			}
			else
			{
				<>1__state = -1;
			}
			<>2__current = (object)new WaitForSeconds(10f);
			<>1__state = 1;
			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 <TrackPlayerItems>d__109 : IEnumerator<object>, IDisposable, IEnumerator
	{
		private int <>1__state;

		private object <>2__current;

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

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

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

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

		private bool MoveNext()
		{
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: Expected O, but got Unknown
			int num = <>1__state;
			if (num != 0)
			{
				if (num != 1)
				{
					return false;
				}
				<>1__state = -1;
				if (PhotonNetwork.InRoom)
				{
					Character[] array = Object.FindObjectsOfType<Character>();
					foreach (Character val in array)
					{
						PhotonView component = ((Component)val).GetComponent<PhotonView>();
						if (!((Object)(object)component == (Object)null) && component.Owner != null && !IsBlocked(component.Owner.ActorNumber))
						{
							CharacterData component2 = ((Component)val).GetComponent<CharacterData>();
							if ((Object)(object)component2 != (Object)null && (Object)(object)component2.currentItem != (Object)null)
							{
								bool wasCookable = (Object)(object)component2.currentItem.cooking != (Object)null && component2.currentItem.cooking.canBeCooked;
								UpdatePlayerHeldItem(component.Owner.ActorNumber, ((Object)component2.currentItem).name, wasCookable);
							}
						}
					}
				}
			}
			else
			{
				<>1__state = -1;
			}
			<>2__current = (object)new WaitForSeconds(2f);
			<>1__state = 1;
			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 <WaitForPersonaStateChange>d__89 : IEnumerator<object>, IDisposable, IEnumerator
	{
		private int <>1__state;

		private object <>2__current;

		public CSteamID steamId;

		public Player player;

		private <>c__DisplayClass89_0 <>8__1;

		public float timeout;

		public bool blockOnMismatch;

		private float <startTime>5__2;

		private Callback<PersonaStateChange_t> <personaCallback>5__3;

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

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

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

		[DebuggerHidden]
		void IDisposable.Dispose()
		{
			<>8__1 = null;
			<personaCallback>5__3 = null;
			<>1__state = -2;
		}

		private bool MoveNext()
		{
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0075: Unknown result type (might be due to invalid IL or missing references)
			//IL_007f: Expected O, but got Unknown
			//IL_0120: Unknown result type (might be due to invalid IL or missing references)
			//IL_02da: Unknown result type (might be due to invalid IL or missing references)
			//IL_02e0: Unknown result type (might be due to invalid IL or missing references)
			//IL_020d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0213: Unknown result type (might be due to invalid IL or missing references)
			switch (<>1__state)
			{
			default:
				return false;
			case 0:
				<>1__state = -1;
				<>8__1 = new <>c__DisplayClass89_0();
				<>8__1.steamId = steamId;
				<startTime>5__2 = Time.time;
				<>8__1.receivedUpdate = false;
				<personaCallback>5__3 = null;
				<personaCallback>5__3 = Callback<PersonaStateChange_t>.Create((DispatchDelegate<PersonaStateChange_t>)delegate(PersonaStateChange_t param)
				{
					//IL_0000: Unknown result type (might be due to invalid IL or missing references)
					//IL_0013: Unknown result type (might be due to invalid IL or missing references)
					//IL_0014: Unknown result type (might be due to invalid IL or missing references)
					//IL_001a: Unknown result type (might be due to invalid IL or missing references)
					//IL_002f: Unknown result type (might be due to invalid IL or missing references)
					if (param.m_ulSteamID == <>8__1.steamId.m_SteamID && (param.m_nChangeFlags & 1) != 0)
					{
						<>8__1.receivedUpdate = true;
						Logger.LogInfo((object)$"Received PersonaStateChange for {<>8__1.steamId} - name was updated");
					}
				});
				break;
			case 1:
				<>1__state = -1;
				if (PhotonNetwork.CurrentRoom == null || PhotonNetwork.CurrentRoom.GetPlayer(player.ActorNumber, false) == null)
				{
					Logger.LogInfo((object)("Player " + player.NickName + " left before name verification completed"));
					<personaCallback>5__3?.Dispose();
					return false;
				}
				break;
			}
			if (!<>8__1.receivedUpdate && Time.time - <startTime>5__2 < timeout)
			{
				<>2__current = (object)new WaitForSeconds(0.1f);
				<>1__state = 1;
				return true;
			}
			<personaCallback>5__3?.Dispose();
			string friendPersonaName = SteamFriends.GetFriendPersonaName(<>8__1.steamId);
			if (friendPersonaName.ToLower() != player.NickName.ToLower())
			{
				if (blockOnMismatch)
				{
					Logger.LogWarning((object)("Name mismatch confirmed after PersonaStateChange: Photon='" + player.NickName + "' vs Steam='" + friendPersonaName + "'"));
					LogVisually("{userColor}" + player.NickName + "</color> {leftColor}confirmed spoofing - real Steam name is '" + friendPersonaName + "'!</color>", onlySendOnce: true, sfxJoin: false, sfxLeave: true);
					if (PhotonNetwork.CurrentRoom != null && PhotonNetwork.CurrentRoom.GetPlayer(player.ActorNumber, false) != null)
					{
						DetectionManager.RecordDetection(DetectionType.SteamNameMismatch, player, "Name spoofing confirmed - real name: " + friendPersonaName);
					}
				}
				else
				{
					Logger.LogWarning((object)("Name mismatch on join after refresh: Photon='" + player.NickName + "' vs Steam='" + friendPersonaName + "'"));
					LogVisually("{userColor}" + player.NickName + "</color> {leftColor}has mismatched Steam name: '" + friendPersonaName + "'</color>", onlySendOnce: true, sfxJoin: false, sfxLeave: true);
					DetectionManager.RecordDetection(DetectionType.SteamNameMismatch, player, "Name mismatch: Photon='" + player.NickName + "' vs Steam='" + friendPersonaName + "'");
				}
			}
			else
			{
				Logger.LogInfo((object)("Name verification passed for " + player.NickName + " after fresh data"));
				LogVisually("{userColor}" + player.NickName + "</color> {joinedColor}name verified successfully</color>", onlySendOnce: 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();
		}
	}

	public static ManualLogSource Logger;

	public static ConfigFile Config;

	private static readonly Dictionary<int, (string itemName, DateTime timestamp, bool wasCookable)> _playerLastHeldItems = new Dictionary<int, (string, DateTime, bool)>();

	private static readonly Dictionary<int, Vector3> _playerLastKnownCoordinates = new Dictionary<int, Vector3>();

	private static readonly Dictionary<int, DateTime> _playerCoordinateTimestamps = new Dictionary<int, DateTime>();

	private const float COORDINATE_UPDATE_INTERVAL = 10f;

	private static readonly Dictionary<int, GameObject> _blockedPlayerHeldItems = new Dictionary<int, GameObject>();

	private const string PLUGIN_VERSION = "1.4.7";

	private const byte ANTICHEAT_PING_EVENT = 69;

	private static ConfigEntry<bool> ShowVisualLogs;

	private static ConfigEntry<bool> CheckSteamNames;

	public static ConfigEntry<bool> AutoBlockCheaters;

	public static ConfigEntry<bool> VerboseRPCLogging;

	private static ConfigEntry<string> WhitelistedSteamIDs;

	public static ConfigEntry<KeyboardShortcut> UIToggleKey;

	private static PlayerConnectionLog _connectionLog;

	private static readonly Queue<(string message, bool onlySendOnce, bool sfxJoin, bool sfxLeave)> _queuedLogs = new Queue<(string, bool, bool, bool)>(8);

	private static readonly List<PlayerIdentity> _knownPlayerIdentities = new List<PlayerIdentity>();

	private static MethodInfo _getColorTagMethod;

	private static MethodInfo _addMessageMethod;

	private static FieldInfo _currentLogField;

	private static FieldInfo _joinedColorField;

	private static FieldInfo _leftColorField;

	private static FieldInfo _userColorField;

	private static FieldInfo _sfxJoinField;

	private static FieldInfo _sfxLeaveField;

	private static Func<object, string> _getColorTagDelegate;

	private static Action<object, string> _addMessageDelegate;

	private static FieldInfo _currentLobbyField;

	private static readonly Dictionary<int, DateTime> _recentlySpawnedPlayers = new Dictionary<int, DateTime>();

	private const double SPAWN_GRACE_PERIOD_SECONDS = 5.0;

	private static readonly Dictionary<int, string> _anticheatUsers = new Dictionary<int, string>();

	private static readonly Dictionary<int, string[]> _playerModLists = new Dictionary<int, string[]>();

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

	private static readonly HashSet<string> _recentDetections = new HashSet<string>();

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

	private static bool _startupMessageShown = false;

	private static readonly Dictionary<int, DateTime> _playersWithoutAnticheat = new Dictionary<int, DateTime>();

	private const float ANTICHEAT_TIMEOUT_SECONDS = 10f;

	private static DateTime _lastMasterClientChange = DateTime.MinValue;

	private const float MASTER_CLIENT_CHANGE_COOLDOWN_SECONDS = 30f;

	public static ConfigEntry<bool> ShareModList;

	private const string DEV_STEAM_ID = "STEAM_0:0:143296685";

	public static AntiCheatPlugin Instance { get; private set; }

	public static bool AutoKickBlockedPlayers { get; set; } = false;


	public static bool AutoBlockNoAnticheat { get; set; } = false;


	private void Awake()
	{
		//IL_0021: Unknown result type (might be due to invalid IL or missing references)
		//IL_002b: Expected O, but got Unknown
		//IL_00e3: Unknown result type (might be due to invalid IL or missing references)
		//IL_0145: Unknown result type (might be due to invalid IL or missing references)
		Instance = this;
		Logger = ((BaseUnityPlugin)this).Logger;
		Config = new ConfigFile(Path.Combine(Paths.ConfigPath, "com.hiccup444.anticheat.cfg"), true);
		ShowVisualLogs = Config.Bind<bool>("General", "ShowVisualLogs", true, "Show anti-cheat messages in the connection log");
		CheckSteamNames = Config.Bind<bool>("General", "CheckSteamNames", true, "Check if Photon names match Steam names");
		AutoBlockCheaters = Config.Bind<bool>("General", "AutoBlockCheaters", true, "Automatically block all RPCs from detected cheaters");
		VerboseRPCLogging = Config.Bind<bool>("Debug", "VerboseRPCLogging", false, "Log all RPC calls for debugging");
		WhitelistedSteamIDs = Config.Bind<string>("General", "WhitelistedSteamIDs", "", "Comma-separated list of Steam IDs that should never be RPC blocked (e.g. '76561198012345678,76561198087654321')");
		UIToggleKey = Config.Bind<KeyboardShortcut>("General", "UIToggleKey", new KeyboardShortcut((KeyCode)283, Array.Empty<KeyCode>()), "Key to toggle the anti-cheat UI (default: F2)");
		ShareModList = Config.Bind<bool>("General", "ShareModList", true, "Share your mod list with the host (enabled by default)");
		ParseWhitelist();
		Config.Save();
		InitializeDetectionManager();
		InitializeEventHandlers();
		Logger.LogInfo((object)"[PEAKAntiCheat] Protection active! (RPC Blocking Mode)");
		new Harmony("com.hiccup444.PEAKanticheat").PatchAll();
		PhotonNetwork.AddCallbackTarget((object)this);
		((MonoBehaviour)this).StartCoroutine(CheckPlayersForCheats());
		((MonoBehaviour)this).StartCoroutine(TrackPlayerItems());
		((MonoBehaviour)this).StartCoroutine(TrackPlayerCoordinates());
		((MonoBehaviour)this).StartCoroutine(CheckPlayersWithoutAnticheat());
		SceneManager.activeSceneChanged += OnSceneChanged;
	}

	private void OnSceneChanged(Scene oldScene, Scene newScene)
	{
		Logger.LogInfo((object)("[PEAKAntiCheat] Scene changed from " + ((Scene)(ref oldScene)).name + " to " + ((Scene)(ref newScene)).name));
		if (((Scene)(ref newScene)).name.Contains("Airport") || ((Scene)(ref newScene)).name.Contains("Level"))
		{
			Logger.LogInfo((object)("[PEAKAntiCheat] Game scene detected: " + ((Scene)(ref newScene)).name + " - creating UI"));
			CreateUI();
			if (((Scene)(ref newScene)).name.Contains("Airport") && !_startupMessageShown)
			{
				((MonoBehaviour)this).StartCoroutine(ShowAnticheatLoadedMessage());
			}
		}
		if (((Scene)(ref newScene)).name.Contains("Level"))
		{
			Player[] playerList = PhotonNetwork.PlayerList;
			for (int i = 0; i < playerList.Length; i++)
			{
				OnPlayerSpawned(playerList[i].ActorNumber);
			}
			if (PhotonNetwork.InRoom && PhotonNetwork.LocalPlayer != null)
			{
				OnPlayerSpawned(PhotonNetwork.LocalPlayer.ActorNumber);
			}
			Logger.LogInfo((object)("Entered game scene '" + ((Scene)(ref newScene)).name + "' - granting spawn grace period to all players including local"));
		}
	}

	private void CreateUI()
	{
		//IL_0036: Unknown result type (might be due to invalid IL or missing references)
		//IL_003c: Expected O, but got Unknown
		if ((Object)(object)GameObject.Find("AntiCheatUI") != (Object)null)
		{
			Logger.LogInfo((object)"[PEAKAntiCheat] UI already exists, skipping creation");
			return;
		}
		Logger.LogInfo((object)"[PEAKAntiCheat] Creating UI...");
		GameObject val = new GameObject("AntiCheatUI");
		Logger.LogInfo((object)$"[PEAKAntiCheat] UI GameObject created: {((Object)val).name}, Active: {val.activeInHierarchy}");
		AntiCheatUI antiCheatUI = val.AddComponent<AntiCheatUI>();
		Logger.LogInfo((object)$"[PEAKAntiCheat] UI component added: {(Object)(object)antiCheatUI != (Object)null}, Component enabled: {((antiCheatUI != null) ? new bool?(((Behaviour)antiCheatUI).enabled) : null)}");
		val.SetActive(true);
		Logger.LogInfo((object)$"[PEAKAntiCheat] UI GameObject activated: {val.activeInHierarchy}");
		if ((Object)(object)antiCheatUI != (Object)null)
		{
			Logger.LogInfo((object)"[PEAKAntiCheat] Manually calling Start method on UI component");
			((Component)antiCheatUI).SendMessage("Start", (SendMessageOptions)1);
		}
		Object.DontDestroyOnLoad((Object)(object)val);
		Logger.LogInfo((object)"[PEAKAntiCheat] UI set to persist across scenes");
		Logger.LogInfo((object)"[PEAKAntiCheat] UI creation completed");
		((MonoBehaviour)this).StartCoroutine(TestUIGameObject());
	}

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

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

	private void InitializeDetectionManager()
	{
		bool flag = false;
		ConfigEntry<string> obj = Config.Bind<string>("UI", "GroupSliders", "", "Saved group slider settings");
		ConfigEntry<string> val = Config.Bind<string>("UI", "IndividualSliders", "", "Saved individual slider settings");
		if (!string.IsNullOrEmpty(obj.Value) || !string.IsNullOrEmpty(val.Value))
		{
			flag = true;
			Logger.LogInfo((object)"[PEAKAntiCheat] UI settings detected - skipping default detection initialization");
		}
		if (!flag)
		{
			Logger.LogInfo((object)"[PEAKAntiCheat] No UI settings found - initializing with default detection settings");
			DetectionManager.SetDetectionSettings(DetectionType.CherryMod, new DetectionSettings(isEnabled: true, AutoBlockCheaters.Value, ShowVisualLogs.Value));
			DetectionManager.SetDetectionSettings(DetectionType.AtlasMod, new DetectionSettings(isEnabled: true, AutoBlockCheaters.Value, ShowVisualLogs.Value));
			DetectionManager.SetDetectionSettings(DetectionType.SteamNameMismatch, new DetectionSettings(CheckSteamNames.Value, AutoBlockCheaters.Value, ShowVisualLogs.Value));
			DetectionManager.SetDetectionSettings(DetectionType.NameImpersonation, new DetectionSettings(isEnabled: true, AutoBlockCheaters.Value, ShowVisualLogs.Value));
			DetectionManager.SetDetectionSettings(DetectionType.MidGameNameChange, new DetectionSettings(isEnabled: true, AutoBlockCheaters.Value, ShowVisualLogs.Value));
			DetectionManager.SetDetectionSettings(DetectionType.SteamIDSpoofing, new DetectionSettings(isEnabled: true, AutoBlockCheaters.Value, ShowVisualLogs.Value));
			DetectionManager.SetDetectionSettings(DetectionType.OwnershipTheft, new DetectionSettings(isEnabled: true, AutoBlockCheaters.Value, ShowVisualLogs.Value));
			DetectionManager.SetDetectionSettings(DetectionType.UnauthorizedDestroy, new DetectionSettings(isEnabled: true, AutoBlockCheaters.Value, ShowVisualLogs.Value));
			DetectionManager.SetDetectionSettings(DetectionType.RateLimitExceeded, new DetectionSettings(isEnabled: true, AutoBlockCheaters.Value, ShowVisualLogs.Value));
			DetectionManager.SetDetectionSettings(DetectionType.UnauthorizedKill, new DetectionSettings(isEnabled: true, AutoBlockCheaters.Value, ShowVisualLogs.Value));
			DetectionManager.SetDetectionSettings(DetectionType.UnauthorizedRevive, new DetectionSettings(isEnabled: true, AutoBlockCheaters.Value, ShowVisualLogs.Value));
			DetectionManager.SetDetectionSettings(DetectionType.UnauthorizedWarp, new DetectionSettings(isEnabled: true, AutoBlockCheaters.Value, ShowVisualLogs.Value));
			DetectionManager.SetDetectionSettings(DetectionType.UnauthorizedStatusEffect, new DetectionSettings(isEnabled: true, AutoBlockCheaters.Value, ShowVisualLogs.Value));
			DetectionManager.SetDetectionSettings(DetectionType.UnauthorizedMovement, new DetectionSettings(isEnabled: true, AutoBlockCheaters.Value, ShowVisualLogs.Value));
			DetectionManager.SetDetectionSettings(DetectionType.UnauthorizedEmote, new DetectionSettings(isEnabled: true, AutoBlockCheaters.Value, ShowVisualLogs.Value));
			DetectionManager.SetDetectionSettings(DetectionType.UnauthorizedItemDrop, new DetectionSettings(isEnabled: true, AutoBlockCheaters.Value, ShowVisualLogs.Value));
			DetectionManager.SetDetectionSettings(DetectionType.UnauthorizedCampfireModification, new DetectionSettings(isEnabled: true, AutoBlockCheaters.Value, ShowVisualLogs.Value));
			DetectionManager.SetDetectionSettings(DetectionType.UnauthorizedFlareLighting, new DetectionSettings(isEnabled: true, AutoBlockCheaters.Value, ShowVisualLogs.Value));
			DetectionManager.SetDetectionSettings(DetectionType.UnauthorizedBananaSlip, new DetectionSettings(isEnabled: true, AutoBlockCheaters.Value, ShowVisualLogs.Value));
			DetectionManager.SetDetectionSettings(DetectionType.MasterClientTheft, new DetectionSettings(isEnabled: true, AutoBlockCheaters.Value, ShowVisualLogs.Value));
			DetectionManager.SetDetectionSettings(DetectionType.InfinityWarp, new DetectionSettings(isEnabled: true, AutoBlockCheaters.Value, ShowVisualLogs.Value));
		}
	}

	private void InitializeEventHandlers()
	{
		DetectionManager.OnDetectionOccurred += OnDetectionOccurred;
		PlayerManager.OnPlayerAdded += OnPlayerAdded;
		PlayerManager.OnPlayerStatusChanged += OnPlayerStatusChanged;
		BlockingManager.OnPlayerBlocked += OnPlayerBlocked;
		BlockingManager.OnPlayerUnblocked += OnPlayerUnblocked;
	}

	private void Update()
	{
		RPCDetection.ProcessPendingItemChecks();
		if (_queuedLogs.Count > 0)
		{
			var (message, onlySendOnce, sfxJoin, sfxLeave) = _queuedLogs.Dequeue();
			LogVisually(message, onlySendOnce, sfxJoin, sfxLeave, allowNonMaster: true);
		}
	}

	private void OnDestroy()
	{
		PhotonNetwork.RemoveCallbackTarget((object)this);
		SceneManager.activeSceneChanged -= OnSceneChanged;
		DetectionManager.OnDetectionOccurred -= OnDetectionOccurred;
		PlayerManager.OnPlayerAdded -= OnPlayerAdded;
		PlayerManager.OnPlayerStatusChanged -= OnPlayerStatusChanged;
		BlockingManager.OnPlayerBlocked -= OnPlayerBlocked;
		BlockingManager.OnPlayerUnblocked -= OnPlayerUnblocked;
	}

	private void OnDetectionOccurred(DetectionResult result)
	{
		if (result.Target == null)
		{
			return;
		}
		if (DetectionManager.ShouldLogToConsole(result.Type))
		{
			Logger.LogWarning((object)$"[DETECTION] {result.Target.NickName} ({result.Type}): {result.Reason}");
		}
		if (!PhotonNetwork.IsMasterClient)
		{
			ReportDetectionToMaster(result.Type, result.Target, result.Reason);
			return;
		}
		DetectionSettings detectionSettings = DetectionManager.GetDetectionSettings(result.Type);
		if (detectionSettings.IsEnabled)
		{
			LogVisually("{userColor}" + result.Target.NickName + "</color> {leftColor}" + result.Reason + "</color>", onlySendOnce: false, sfxJoin: false, sfxLeave: true);
			if (detectionSettings.AutoBlock)
			{
				BlockPlayer(result.Target, result.Reason, result.Type);
				LogVisually($"{{userColor}}{result.Target.NickName}</color> {{leftColor}}was auto-blocked for {result.Type}</color>", onlySendOnce: false, sfxJoin: false, sfxLeave: true);
			}
			else if (detectionSettings.ShowVisualWarning)
			{
				string text = $"{result.Target.ActorNumber}_{result.Type}";
				if (!_recentDetections.Contains(text))
				{
					LogVisually($"{{userColor}}{result.Target.NickName}</color> {{leftColor}}detected - {result.Type} - no action taken</color>", onlySendOnce: false, sfxJoin: false, sfxLeave: true);
					_recentDetections.Add(text);
					((MonoBehaviour)this).StartCoroutine(RemoveDetectionFromRecent(text, 30f));
				}
			}
		}
		PlayerManager.AddDetectionReason(result.Target.ActorNumber, result.Reason);
	}

	[IteratorStateMachine(typeof(<RemoveDetectionFromRecent>d__55))]
	private IEnumerator RemoveDetectionFromRecent(string detectionKey, float delay)
	{
		//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
		return new <RemoveDetectionFromRecent>d__55(0)
		{
			detectionKey = detectionKey,
			delay = delay
		};
	}

	private void OnPlayerAdded(PlayerInfo playerInfo)
	{
		Logger.LogInfo((object)$"[PLAYER ADDED] {playerInfo.PhotonName} (Actor #{playerInfo.ActorNumber})");
	}

	private void OnPlayerStatusChanged(PlayerInfo playerInfo)
	{
		Logger.LogInfo((object)$"[STATUS CHANGE] {playerInfo.PhotonName}: {playerInfo.Status}");
	}

	private void OnPlayerBlocked(BlockEntry blockEntry)
	{
		Logger.LogWarning((object)("[PLAYER BLOCKED] " + blockEntry.PlayerName + ": " + blockEntry.SpecificReason));
	}

	private void OnPlayerUnblocked(int actorNumber)
	{
		Logger.LogInfo((object)$"[PLAYER UNBLOCKED] Actor #{actorNumber}");
		_detectedCheatModUsers.Remove(actorNumber);
		Room currentRoom = PhotonNetwork.CurrentRoom;
		Player val = ((currentRoom != null) ? currentRoom.GetPlayer(actorNumber, false) : null);
		if (val != null)
		{
			string item = $"{val.NickName}_{actorNumber}_AtlasMod";
			_recentDetections.Remove(item);
			item = $"{val.NickName}_{actorNumber}_CherryMod";
			_recentDetections.Remove(item);
		}
		RPCDetection.ClearFlagCounts(actorNumber);
		BlockingManager.GrantImmunity(actorNumber);
		Logger.LogInfo((object)$"[PLAYER UNBLOCKED] Granted immunity to Actor #{actorNumber} to prevent re-detection");
	}

	public static void BlockPlayer(Player cheater, string reason, DetectionType? detectionType = null)
	{
		//IL_00d4: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d9: Unknown result type (might be due to invalid IL or missing references)
		//IL_0103: Unknown result type (might be due to invalid IL or missing references)
		//IL_0108: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f5: Unknown result type (might be due to invalid IL or missing references)
		//IL_00fa: Unknown result type (might be due to invalid IL or missing references)
		//IL_0110: Unknown result type (might be due to invalid IL or missing references)
		//IL_011e: Unknown result type (might be due to invalid IL or missing references)
		if (cheater.ActorNumber == PhotonNetwork.LocalPlayer.ActorNumber)
		{
			Logger.LogInfo((object)"Not blocking local player");
			return;
		}
		if (cheater.IsMasterClient)
		{
			Logger.LogWarning((object)("[BLOCK PREVENTED] Attempted to block master client " + cheater.NickName + " for: " + reason));
			return;
		}
		bool flag = true;
		if (!((!detectionType.HasValue) ? AutoBlockCheaters.Value : DetectionManager.ShouldAutoBlock(detectionType.Value)))
		{
			Logger.LogInfo((object)("Auto-blocking disabled for this detection - only logging cheater: " + cheater.NickName));
			return;
		}
		Logger.LogWarning((object)("CHEATER DETECTED: " + cheater.NickName + " - Reason: " + reason));
		CSteamID nil = CSteamID.Nil;
		nil = _knownPlayerIdentities.Find((PlayerIdentity p) => p.ActorNumber == cheater.ActorNumber)?.SteamID ?? GetPlayerSteamID(cheater);
		AntiCheatEvents.NotifyCheaterDetected(cheater, reason, nil);
		BlockingManager.BlockPlayer(cheater, reason, BlockReason.AutoDetection, nil, detectionType);
		Logger.LogInfo((object)$"All RPCs from {cheater.NickName} (Actor #{cheater.ActorNumber}) are now blocked");
	}

	public static bool IsBlocked(int actorNumber)
	{
		return BlockingManager.IsBlocked(actorNumber);
	}

	public static bool HasAnticheat(int actorNumber)
	{
		return _anticheatUsers.ContainsKey(actorNumber);
	}

	public static string GetAnticheatVersion(int actorNumber)
	{
		if (!_anticheatUsers.TryGetValue(actorNumber, out var value))
		{
			return null;
		}
		return value;
	}

	public static bool AreKicksAllowed()
	{
		if (_lastMasterClientChange == DateTime.MinValue)
		{
			return true;
		}
		double totalSeconds = (DateTime.Now - _lastMasterClientChange).TotalSeconds;
		bool num = totalSeconds >= 30.0;
		if (!num)
		{
			Logger.LogWarning((object)$"[KICK SECURITY] Kicks disabled - master client changed {totalSeconds:F1} seconds ago (cooldown: {30f}s)");
		}
		return num;
	}

	public static void UpdatePlayerHeldItem(int actorNumber, string itemName, bool wasCookable = false)
	{
		if (!string.IsNullOrEmpty(itemName))
		{
			_playerLastHeldItems[actorNumber] = (itemName.ToLower(), DateTime.Now, wasCookable);
		}
	}

	public static bool PlayerHadItem(int actorNumber, string itemNamePart, float withinSeconds = 2f, bool checkCookable = false)
	{
		if (_playerLastHeldItems.TryGetValue(actorNumber, out (string, DateTime, bool) value) && (DateTime.Now - value.Item2).TotalSeconds <= (double)withinSeconds)
		{
			if (checkCookable)
			{
				return value.Item3;
			}
			return value.Item1.Contains(itemNamePart.ToLower());
		}
		return false;
	}

	public static bool PlayerHadCookableItem(int actorNumber, float withinSeconds = 2f)
	{
		return PlayerHadItem(actorNumber, "", withinSeconds, checkCookable: true);
	}

	private static void InitializeReflectionCache()
	{
		if ((Object)(object)_connectionLog == (Object)null)
		{
			_connectionLog = Object.FindObjectOfType<PlayerConnectionLog>();
			if ((Object)(object)_connectionLog == (Object)null)
			{
				Logger.LogWarning((object)"[PEAKAntiCheat] PlayerConnectionLog not found in scene");
				return;
			}
			Logger.LogInfo((object)"[PEAKAntiCheat] Found PlayerConnectionLog, setting up reflection cache");
		}
		Type type = ((object)_connectionLog).GetType();
		_getColorTagMethod = type.GetMethod("GetColorTag", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
		_addMessageMethod = type.GetMethod("AddMessage", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
		_currentLogField = type.GetField("currentLog", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
		_joinedColorField = type.GetField("joinedColor", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
		_leftColorField = type.GetField("leftColor", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
		_userColorField = type.GetField("userColor", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
		_sfxJoinField = type.GetField("sfxJoin", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
		_sfxLeaveField = type.GetField("sfxLeave", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
		try
		{
			if (_getColorTagMethod != null)
			{
				_getColorTagDelegate = (Func<object, string>)Delegate.CreateDelegate(typeof(Func<object, string>), _connectionLog, _getColorTagMethod);
			}
			if (_addMessageMethod != null)
			{
				_addMessageDelegate = (Action<object, string>)Delegate.CreateDelegate(typeof(Action<object, string>), _connectionLog, _addMessageMethod);
			}
		}
		catch (Exception ex)
		{
			Logger.LogWarning((object)("[Reflection Cache] Failed to create delegates, falling back to direct reflection: " + ex.Message));
			_getColorTagDelegate = null;
			_addMessageDelegate = null;
		}
	}

	public static bool LogVisually(string message, bool onlySendOnce = false, bool sfxJoin = false, bool sfxLeave = false, bool allowNonMaster = false)
	{
		//IL_0307: Unknown result type (might be due to invalid IL or missing references)
		//IL_0371: Unknown result type (might be due to invalid IL or missing references)
		if (!PhotonNetwork.IsMasterClient && !allowNonMaster && !message.Contains("has anticheat installed"))
		{
			return true;
		}
		if (!ShowVisualLogs.Value)
		{
			return true;
		}
		if ((Object)(object)_connectionLog == (Object)null || _getColorTagMethod == null || _addMessageMethod == null)
		{
			InitializeReflectionCache();
		}
		if (!Object.op_Implicit((Object)(object)_connectionLog) || _getColorTagMethod == null || _addMessageMethod == null)
		{
			Logger.LogWarning((object)$"[PEAKAntiCheat] LogVisually failed - ConnectionLog: {(Object)(object)_connectionLog != (Object)null}, GetColorTagMethod: {_getColorTagMethod != null}, AddMessageMethod: {_addMessageMethod != null}");
			_queuedLogs.Enqueue((message, onlySendOnce, sfxJoin, sfxLeave));
			return false;
		}
		try
		{
			StringBuilder stringBuilder = new StringBuilder(message);
			if (_joinedColorField != null && _leftColorField != null && _userColorField != null)
			{
				object value = _joinedColorField.GetValue(_connectionLog);
				object value2 = _leftColorField.GetValue(_connectionLog);
				object value3 = _userColorField.GetValue(_connectionLog);
				string text = "";
				string text2 = "";
				string text3 = "";
				if (_getColorTagDelegate != null)
				{
					text = _getColorTagDelegate(value);
					text2 = _getColorTagDelegate(value2);
					text3 = _getColorTagDelegate(value3);
				}
				else if (_getColorTagMethod != null)
				{
					text = (string)_getColorTagMethod.Invoke(_connectionLog, new object[1] { value });
					text2 = (string)_getColorTagMethod.Invoke(_connectionLog, new object[1] { value2 });
					text3 = (string)_getColorTagMethod.Invoke(_connectionLog, new object[1] { value3 });
				}
				stringBuilder.Replace("{joinedColor}", text ?? "");
				stringBuilder.Replace("{leftColor}", text2 ?? "");
				stringBuilder.Replace("{userColor}", text3 ?? "");
			}
			message = stringBuilder.ToString();
			if (onlySendOnce && _currentLogField != null)
			{
				string text4 = _currentLogField.GetValue(_connectionLog) as string;
				if (!string.IsNullOrEmpty(text4) && text4.Contains(message))
				{
					return true;
				}
			}
			if (_addMessageDelegate != null)
			{
				_addMessageDelegate(_connectionLog, message);
			}
			else
			{
				_addMessageMethod.Invoke(_connectionLog, new object[1] { message });
			}
			if (sfxJoin && _sfxJoinField != null)
			{
				object value4 = _sfxJoinField.GetValue(_connectionLog);
				value4?.GetType().GetMethod("Play", new Type[1] { typeof(Vector3) })?.Invoke(value4, new object[1] { Vector3.zero });
			}
			if (sfxLeave && _sfxLeaveField != null)
			{
				object value5 = _sfxLeaveField.GetValue(_connectionLog);
				value5?.GetType().GetMethod("Play", new Type[1] { typeof(Vector3) })?.Invoke(value5, new object[1] { Vector3.zero });
			}
			return true;
		}
		catch (Exception ex)
		{
			Logger.LogError((object)("Error in LogVisually: " + ex.Message));
			return false;
		}
	}

	public static void OnPlayerSpawned(int actorNumber)
	{
		_recentlySpawnedPlayers[actorNumber] = DateTime.Now;
		Logger.LogInfo((object)$"Tracking spawn for actor #{actorNumber}");
	}

	public static bool IsInSpawnGracePeriod(int actorNumber)
	{
		if (_recentlySpawnedPlayers.ContainsKey(actorNumber))
		{
			if ((DateTime.Now - _recentlySpawnedPlayers[actorNumber]).TotalSeconds <= 5.0)
			{
				return true;
			}
			_recentlySpawnedPlayers.Remove(actorNumber);
		}
		return false;
	}

	[HarmonyPatch(typeof(PlayerConnectionLog), "OnPlayerEnteredRoom")]
	[HarmonyPrefix]
	public static bool PreOnPlayerEnteredRoom(PlayerConnectionLog __instance, Player newPlayer)
	{
		//IL_001f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0024: Unknown result type (might be due to invalid IL or missing references)
		//IL_0025: Unknown result type (might be due to invalid IL or missing references)
		//IL_0026: Unknown result type (might be due to invalid IL or missing references)
		//IL_0159: Unknown result type (might be due to invalid IL or missing references)
		//IL_015e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0168: Unknown result type (might be due to invalid IL or missing references)
		//IL_016d: Unknown result type (might be due to invalid IL or missing references)
		//IL_017a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0199: Unknown result type (might be due to invalid IL or missing references)
		//IL_0247: Unknown result type (might be due to invalid IL or missing references)
		if (newPlayer.IsLocal || newPlayer.NickName == "Bing Bong")
		{
			return true;
		}
		bool flag = false;
		try
		{
			CSteamID playerSteamID = GetPlayerSteamID(newPlayer);
			if (playerSteamID != CSteamID.Nil)
			{
				string text = ((object)(CSteamID)(ref playerSteamID)).ToString();
				flag = text == "STEAM_0:0:143296685";
				if (flag)
				{
					Logger.LogInfo((object)("[DEV JOIN] Detected dev joining: " + newPlayer.NickName + " (Steam ID: " + text + ")"));
				}
			}
		}
		catch (Exception ex)
		{
			Logger.LogWarning((object)("[DEV JOIN] Error checking Steam ID for " + newPlayer.NickName + ": " + ex.Message));
		}
		if (flag)
		{
			try
			{
				FieldInfo field = ((object)__instance).GetType().GetField("userColor", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
				FieldInfo field2 = ((object)__instance).GetType().GetField("joinedColor", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
				FieldInfo field3 = ((object)__instance).GetType().GetField("sfxJoin", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
				MethodInfo method = ((object)__instance).GetType().GetMethod("AddMessage", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
				MethodInfo method2 = ((object)__instance).GetType().GetMethod("GetColorTag", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
				if (field != null && field2 != null && method != null && method2 != null)
				{
					Color val = (Color)field.GetValue(__instance);
					Color val2 = (Color)field2.GetValue(__instance);
					string text2 = (string)method2.Invoke(__instance, new object[1] { val });
					string obj = (string)method2.Invoke(__instance, new object[1] { val2 });
					string newValue = text2 + " [Anticheat Dev] " + newPlayer.NickName + "</color>";
					string text3 = obj + LocalizedText.GetText("JOINEDTHEEXPEDITION", true).Replace("#", newValue) + "</color>";
					method.Invoke(__instance, new object[1] { text3 });
					if (field3 != null)
					{
						object value = field3.GetValue(__instance);
						value?.GetType().GetMethod("Play", new Type[1] { typeof(Vector3) })?.Invoke(value, new object[1] { Vector3.zero });
					}
					Logger.LogInfo((object)("[DEV JOIN] Custom dev join message displayed for " + newPlayer.NickName));
					return false;
				}
			}
			catch (Exception ex2)
			{
				Logger.LogError((object)("[DEV JOIN] Error creating custom dev message: " + ex2.Message));
			}
		}
		return true;
	}

	private static CSteamID GetPlayerSteamID(Player player)
	{
		//IL_042d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0432: Unknown result type (might be due to invalid IL or missing references)
		//IL_0018: Unknown result type (might be due to invalid IL or missing references)
		//IL_001d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0436: Unknown result type (might be due to invalid IL or missing references)
		//IL_007b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0080: Unknown result type (might be due to invalid IL or missing references)
		//IL_0081: Unknown result type (might be due to invalid IL or missing references)
		//IL_0082: Unknown result type (might be due to invalid IL or missing references)
		//IL_0064: Unknown result type (might be due to invalid IL or missing references)
		//IL_0069: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a9: Unknown result type (might be due to invalid IL or missing references)
		//IL_009d: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a2: Unknown result type (might be due to invalid IL or missing references)
		//IL_00e2: Unknown result type (might be due to invalid IL or missing references)
		//IL_00e5: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ea: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ec: Unknown result type (might be due to invalid IL or missing references)
		//IL_0114: Unknown result type (might be due to invalid IL or missing references)
		//IL_011d: Unknown result type (might be due to invalid IL or missing references)
		//IL_031f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0324: Unknown result type (might be due to invalid IL or missing references)
		//IL_0356: Unknown result type (might be due to invalid IL or missing references)
		//IL_035b: Unknown result type (might be due to invalid IL or missing references)
		//IL_035d: Unknown result type (might be due to invalid IL or missing references)
		//IL_035f: Unknown result type (might be due to invalid IL or missing references)
		//IL_01ec: Unknown result type (might be due to invalid IL or missing references)
		//IL_0203: Unknown result type (might be due to invalid IL or missing references)
		//IL_0208: Unknown result type (might be due to invalid IL or missing references)
		//IL_036d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0390: Unknown result type (might be due to invalid IL or missing references)
		//IL_0395: Unknown result type (might be due to invalid IL or missing references)
		//IL_0399: Unknown result type (might be due to invalid IL or missing references)
		//IL_03b2: Unknown result type (might be due to invalid IL or missing references)
		//IL_03c3: Unknown result type (might be due to invalid IL or missing references)
		//IL_03c5: Unknown result type (might be due to invalid IL or missing references)
		//IL_03fc: Unknown result type (might be due to invalid IL or missing references)
		//IL_0401: Unknown result type (might be due to invalid IL or missing references)
		//IL_0247: Unknown result type (might be due to invalid IL or missing references)
		//IL_024c: Unknown result type (might be due to invalid IL or missing references)
		//IL_024e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0250: Unknown result type (might be due to invalid IL or missing references)
		//IL_025e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0281: Unknown result type (might be due to invalid IL or missing references)
		//IL_0286: Unknown result type (might be due to invalid IL or missing references)
		//IL_028a: Unknown result type (might be due to invalid IL or missing references)
		//IL_02a3: Unknown result type (might be due to invalid IL or missing references)
		//IL_02b4: Unknown result type (might be due to invalid IL or missing references)
		//IL_02b6: Unknown result type (might be due to invalid IL or missing references)
		try
		{
			SteamLobbyHandler service = GameHandler.GetService<SteamLobbyHandler>();
			if (service == null)
			{
				Logger.LogWarning((object)"[GetPlayerSteamID] SteamLobbyHandler not found.");
				return CSteamID.Nil;
			}
			if (_currentLobbyField == null)
			{
				_currentLobbyField = ((object)service).GetType().GetField("m_currentLobby", BindingFlags.Instance | BindingFlags.NonPublic);
			}
			if (_currentLobbyField == null)
			{
				Logger.LogError((object)"[GetPlayerSteamID] Could not find m_currentLobby field via reflection.");
				return CSteamID.Nil;
			}
			CSteamID val = (CSteamID)_currentLobbyField.GetValue(service);
			if (val == CSteamID.Nil)
			{
				Logger.LogWarning((object)"[GetPlayerSteamID] Current Steam lobby is NIL.");
				return CSteamID.Nil;
			}
			int numLobbyMembers = SteamMatchmaking.GetNumLobbyMembers(val);
			Logger.LogInfo((object)$"[GetPlayerSteamID] Scanning {numLobbyMembers} Steam lobby members for match with Photon name '{player.NickName}'.");
			Dictionary<string, List<CSteamID>> dictionary = new Dictionary<string, List<CSteamID>>();
			List<CSteamID> list = new List<CSteamID>();
			for (int i = 0; i < numLobbyMembers; i++)
			{
				CSteamID lobbyMemberByIndex = SteamMatchmaking.GetLobbyMemberByIndex(val, i);
				string friendPersonaName = SteamFriends.GetFriendPersonaName(lobbyMemberByIndex);
				if (!dictionary.ContainsKey(friendPersonaName))
				{
					dictionary[friendPersonaName] = new List<CSteamID>();
				}
				dictionary[friendPersonaName].Add(lobbyMemberByIndex);
				list.Add(lobbyMemberByIndex);
			}
			Player[] playerList;
			if (dictionary.ContainsKey(player.NickName))
			{
				List<CSteamID> list2 = dictionary[player.NickName];
				Logger.LogInfo((object)string.Format("[GetPlayerSteamID] Found {0} Steam players with name '{1}': {2}", list2.Count, player.NickName, string.Join(", ", list2)));
				List<Player> list3 = new List<Player>();
				playerList = PhotonNetwork.PlayerList;
				foreach (Player val2 in playerList)
				{
					if (val2.NickName == player.NickName)
					{
						list3.Add(val2);
					}
				}
				if (list2.Count == 1 && list3.Count == 1)
				{
					Logger.LogInfo((object)$"[GetPlayerSteamID] Unique match found: {player.NickName} -> {list2[0]}");
					return list2[0];
				}
				if (list2.Count > 1)
				{
					HashSet<CSteamID> hashSet = new HashSet<CSteamID>();
					playerList = PhotonNetwork.PlayerList;
					foreach (Player val3 in playerList)
					{
						if (val3.ActorNumber != player.ActorNumber)
						{
							CSteamID playerSteamID = GetPlayerSteamID(val3);
							if (playerSteamID != CSteamID.Nil)
							{
								hashSet.Add(playerSteamID);
							}
						}
					}
					foreach (CSteamID item in list2)
					{
						if (!hashSet.Contains(item))
						{
							Logger.LogInfo((object)$"[GetPlayerSteamID] Found unassigned Steam ID for {player.NickName}: {item}");
							return item;
						}
					}
					Logger.LogWarning((object)("[GetPlayerSteamID] No unassigned Steam IDs found for " + player.NickName));
				}
			}
			int num = PhotonNetwork.PlayerList.Length;
			if (num > numLobbyMembers)
			{
				Logger.LogWarning((object)$"[GetPlayerSteamID] More Photon players ({num}) than Steam lobby members ({numLobbyMembers}). Possible spoofer.");
				return CSteamID.Nil;
			}
			HashSet<CSteamID> hashSet2 = new HashSet<CSteamID>();
			playerList = PhotonNetwork.PlayerList;
			foreach (Player val4 in playerList)
			{
				if (val4.ActorNumber != player.ActorNumber)
				{
					CSteamID playerSteamID2 = GetPlayerSteamID(val4);
					if (playerSteamID2 != CSteamID.Nil)
					{
						hashSet2.Add(playerSteamID2);
					}
				}
			}
			foreach (CSteamID item2 in list)
			{
				if (!hashSet2.Contains(item2))
				{
					Logger.LogInfo((object)$"[GetPlayerSteamID] Found unassigned Steam ID for {player.NickName}: {item2}");
					return item2;
				}
			}
			Logger.LogWarning((object)$"[GetPlayerSteamID] No unassigned Steam IDs found. All {numLobbyMembers} lobby members are accounted for.");
			return CSteamID.Nil;
		}
		catch (Exception ex)
		{
			Logger.LogError((object)("[GetPlayerSteamID] Error getting Steam ID for " + player.NickName + ": " + ex.Message));
			return CSteamID.Nil;
		}
	}

	private static void ParseWhitelist()
	{
		string value = WhitelistedSteamIDs.Value;
		if (string.IsNullOrWhiteSpace(value))
		{
			return;
		}
		string[] array = value.Split(new char[1] { ',' });
		for (int i = 0; i < array.Length; i++)
		{
			string text = array[i].Trim();
			if (ulong.TryParse(text, out var result))
			{
				BlockingManager.AddToWhitelist(result);
				Logger.LogInfo((object)$"[WHITELIST] Added Steam ID to whitelist: {result}");
			}
			else if (!string.IsNullOrEmpty(text))
			{
				Logger.LogWarning((object)("[WHITELIST] Invalid Steam ID format: " + text));
			}
		}
	}

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

	private void CheckPlayerForCheatMods(Player player)
	{
		//IL_0043: Unknown result type (might be due to invalid IL or missing references)
		//IL_0048: Unknown result type (might be due to invalid IL or missing references)
		//IL_007c: 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_00b1: Unknown result type (might be due to invalid IL or missing references)
		//IL_0181: Unknown result type (might be due to invalid IL or missing references)
		//IL_0187: Unknown result type (might be due to invalid IL or missing references)
		//IL_020c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0212: Unknown result type (might be due to invalid IL or missing references)
		//IL_0297: Unknown result type (might be due to invalid IL or missing references)
		//IL_029d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0322: Unknown result type (might be due to invalid IL or missing references)
		//IL_0328: Unknown result type (might be due to invalid IL or missing references)
		if (player.ActorNumber == PhotonNetwork.LocalPlayer.ActorNumber)
		{
			return;
		}
		if (!_knownPlayerIdentities.Exists((PlayerIdentity p) => p.ActorNumber == player.ActorNumber))
		{
			CSteamID playerSteamID = GetPlayerSteamID(player);
			Logger.LogInfo((object)$"[Identity Log] Joined: PhotonName={player.NickName} | ActorNumber={player.ActorNumber} | SteamName={SteamFriends.GetFriendPersonaName(playerSteamID)} | SteamID={playerSteamID}");
			_knownPlayerIdentities.Add(new PlayerIdentity(player.NickName, player.ActorNumber, playerSteamID));
		}
		if (!player.IsMasterClient && !_detectedCheatModUsers.Contains(player.ActorNumber))
		{
			if (BlockingManager.HasImmunity(player.ActorNumber))
			{
				Logger.LogInfo((object)("[CHEAT MOD CHECK] Skipping " + player.NickName + " - player has immunity"));
			}
			else if (((Dictionary<object, object>)(object)player.CustomProperties).ContainsKey((object)"CherryUser"))
			{
				Logger.LogWarning((object)(player.NickName + " is using the Cherry cheat mod!"));
				LogVisually("{userColor}" + player.NickName + "</color> {leftColor}is using the Cherry cheat mod!</color>", onlySendOnce: true, sfxJoin: false, sfxLeave: true);
				DetectionManager.RecordDetection(DetectionType.CherryMod, player, "Cherry cheat mod user");
				_detectedCheatModUsers.Add(player.ActorNumber);
			}
			else if (((Dictionary<object, object>)(object)player.CustomProperties).ContainsKey((object)"CherryOwner"))
			{
				Logger.LogWarning((object)(player.NickName + " is the Owner of the Cherry cheat mod!"));
				LogVisually("{userColor}" + player.NickName + "</color> {leftColor}is the Owner of the Cherry cheat mod!</color>", onlySendOnce: true, sfxJoin: false, sfxLeave: true);
				DetectionManager.RecordDetection(DetectionType.CherryMod, player, "Cherry cheat mod owner");
				_detectedCheatModUsers.Add(player.ActorNumber);
			}
			else if (((Dictionary<object, object>)(object)player.CustomProperties).ContainsKey((object)"AtlUser"))
			{
				Logger.LogWarning((object)(player.NickName + " is using the Atlas cheat mod!"));
				LogVisually("{userColor}" + player.NickName + "</color> {leftColor}is using the Atlas cheat mod!</color>", onlySendOnce: true, sfxJoin: false, sfxLeave: true);
				DetectionManager.RecordDetection(DetectionType.AtlasMod, player, "Atlas cheat mod user");
				_detectedCheatModUsers.Add(player.ActorNumber);
			}
			else if (((Dictionary<object, object>)(object)player.CustomProperties).ContainsKey((object)"AtlOwner"))
			{
				Logger.LogWarning((object)(player.NickName + " is the Owner of the Atlas cheat mod!"));
				LogVisually("{userColor}" + player.NickName + "</color> {leftColor}is the Owner of the Atlas cheat mod!</color>", onlySendOnce: true, sfxJoin: false, sfxLeave: true);
				DetectionManager.RecordDetection(DetectionType.AtlasMod, player, "Atlas cheat mod owner");
				_detectedCheatModUsers.Add(player.ActorNumber);
			}
			else if (CheckSteamNames.Value)
			{
				CheckSteamNameMatch(player);
			}
		}
	}

	private void CheckSteamNameMatch(Player player)
	{
		//IL_002b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0030: Unknown result type (might be due to invalid IL or missing references)
		//IL_0047: Unknown result type (might be due to invalid IL or missing references)
		//IL_0052: Unknown result type (might be due to invalid IL or missing references)
		//IL_0080: Unknown result type (might be due to invalid IL or missing references)
		//IL_0068: Unknown result type (might be due to invalid IL or missing references)
		//IL_0165: Unknown result type (might be due to invalid IL or missing references)
		//IL_016b: Unknown result type (might be due to invalid IL or missing references)
		PlayerIdentity playerIdentity = _knownPlayerIdentities.Find((PlayerIdentity p) => p.ActorNumber == player.ActorNumber);
		if (playerIdentity == null || !(playerIdentity.SteamID != CSteamID.Nil))
		{
			return;
		}
		CheckForSteamIDSpoofing(player, playerIdentity.SteamID);
		if (SteamFriends.RequestUserInformation(playerIdentity.SteamID, true))
		{
			((MonoBehaviour)this).StartCoroutine(WaitForPersonaStateChange(player, playerIdentity.SteamID, 5f, blockOnMismatch: false));
			return;
		}
		string friendPersonaName = SteamFriends.GetFriendPersonaName(playerIdentity.SteamID);
		if (!(friendPersonaName.ToLower() == player.NickName.ToLower()))
		{
			Logger.LogWarning((object)("Name mismatch detected on join: Photon='" + player.NickName + "' vs Steam='" + friendPersonaName + "'"));
			LogVisually("{userColor}" + player.NickName + "</color> {leftColor}has mismatched Steam name: '" + friendPersonaName + "'</color>", onlySendOnce: true, sfxJoin: false, sfxLeave: true);
			DetectionManager.RecordDetection(DetectionType.SteamNameMismatch, player, "Name mismatch: Photon='" + player.NickName + "' vs Steam='" + friendPersonaName + "'");
		}
	}

	private void CheckForSteamIDSpoofing(Player player, CSteamID playerSteamID)
	{
		//IL_0010: Unknown result type (might be due to invalid IL or missing references)
		//IL_0015: Unknown result type (might be due to invalid IL or missing references)
		//IL_0016: 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)
		//IL_00a9: Unknown result type (might be due to invalid IL or missing references)
		//IL_00af: Unknown result type (might be due to invalid IL or missing references)
		if (!PhotonNetwork.IsMasterClient || player.IsMasterClient)
		{
			return;
		}
		CSteamID steamID = SteamUser.GetSteamID();
		if (playerSteamID == steamID)
		{
			Logger.LogError((object)("[STEAM ID SPOOFING DETECTED] " + player.NickName + " is spoofing the master client's Steam ID!"));
			LogVisually("{userColor}" + player.NickName + "</color> {leftColor}is spoofing the master client's Steam ID!</color>", onlySendOnce: false, sfxJoin: false, sfxLeave: true);
			bool num = DetectionManager.ShouldAutoBlock(DetectionType.SteamIDSpoofing);
			if (DetectionManager.ShouldShowVisualWarning(DetectionType.SteamIDSpoofing))
			{
				LogVisually("{userColor}" + player.NickName + "</color> {leftColor}is spoofing the master client's Steam ID!</color>", onlySendOnce: false, sfxJoin: false, sfxLeave: true);
			}
			if (num)
			{
				BlockPlayer(player, "Steam ID spoofing - pretending to be master client", DetectionType.SteamIDSpoofing);
			}
			DetectionManager.RecordDetection(DetectionType.SteamIDSpoofing, player, "Spoofed master client's Steam ID");
		}
	}

	[IteratorStateMachine(typeof(<WaitForPersonaStateChange>d__89))]
	private IEnumerator WaitForPersonaStateChange(Player player, CSteamID steamId, float timeout, bool blockOnMismatch = true)
	{
		//IL_000e: Unknown result type (might be due to invalid IL or missing references)
		//IL_000f: Unknown result type (might be due to invalid IL or missing references)
		//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
		return new <WaitForPersonaStateChange>d__89(0)
		{
			player = player,
			steamId = steamId,
			timeout = timeout,
			blockOnMismatch = blockOnMismatch
		};
	}

	public void OnMasterClientSwitched(Player newMasterClient)
	{
		//IL_027b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0281: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a9: Unknown result type (might be due to invalid IL or missing references)
		//IL_00aa: Unknown result type (might be due to invalid IL or missing references)
		//IL_00af: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c4: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c9: Unknown result type (might be due to invalid IL or missing references)
		//IL_02c1: Unknown result type (might be due to invalid IL or missing references)
		//IL_02c6: Unknown result type (might be due to invalid IL or missing references)
		//IL_02c8: Unknown result type (might be due to invalid IL or missing references)
		//IL_02cd: Unknown result type (might be due to invalid IL or missing references)
		//IL_02d7: Expected O, but got Unknown
		//IL_0176: Unknown result type (might be due to invalid IL or missing references)
		//IL_017c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0183: Unknown result type (might be due to invalid IL or missing references)
		//IL_0184: Unknown result type (might be due to invalid IL or missing references)
		Logger.LogInfo((object)$"{newMasterClient.NickName} (#{newMasterClient.ActorNumber}) is the new master client!");
		_lastMasterClientChange = DateTime.Now;
		Logger.LogInfo((object)$"[MASTER CLIENT] Master client change recorded - kicks disabled for {30f} seconds");
		PlayerManager.HandleMasterClientSwitch(newMasterClient);
		bool flag = false;
		if (newMasterClient.ActorNumber == PhotonNetwork.LocalPlayer.ActorNumber)
		{
			Logger.LogInfo((object)"[MASTER CLIENT] Local player became master client - legitimate switch");
			flag = true;
			CreateUI();
			((MonoBehaviour)this).StartCoroutine(SendSyncToAllClients());
		}
		else
		{
			SteamLobbyHandler service = GameHandler.GetService<SteamLobbyHandler>();
			CSteamID val = default(CSteamID);
			if (service != null && service.InSteamLobby(ref val))
			{
				CSteamID lobbyOwner = SteamMatchmaking.GetLobbyOwner(val);
				bool flag2 = false;
				Player[] playerList = PhotonNetwork.PlayerList;
				for (int i = 0; i < playerList.Length; i++)
				{
					if (GetPlayerSteamID(playerList[i]) == lobbyOwner)
					{
						flag2 = true;
						break;
					}
				}
				if (flag2)
				{
					Logger.LogError((object)("[MASTER CLIENT THEFT DETECTED] " + newMasterClient.NickName + " stole master client while original master is still in room!"));
					LogVisually("{userColor}" + newMasterClient.NickName + "</color> {leftColor}stole master client while original master is still here!</color>", onlySendOnce: false, sfxJoin: false, sfxLeave: true);
					bool num = DetectionManager.ShouldAutoBlock(DetectionType.MasterClientTheft);
					if (DetectionManager.ShouldShowVisualWarning(DetectionType.MasterClientTheft))
					{
						LogVisually("{userColor}" + newMasterClient.NickName + "</color> {leftColor}stole master client while original master is still here!</color>", onlySendOnce: false, sfxJoin: false, sfxLeave: true);
					}
					if (num)
					{
						BlockPlayer(newMasterClient, "Master client theft - original master still in room", DetectionType.MasterClientTheft);
					}
					DetectionManager.RecordDetection(DetectionType.MasterClientTheft, newMasterClient, "Stole master client while original master still present");
					if (lobbyOwner == SteamUser.GetSteamID())
					{
						Logger.LogInfo((object)"[MASTER CLIENT] Taking master client back from thief");
						PhotonNetwork.SetMasterClient(PhotonNetwork.LocalPlayer);
						GameObject val2 = GameObject.Find("AntiCheatUI");
						if ((Object)(object)val2 != (Object)null)
						{
							AntiCheatUI component = val2.GetComponent<AntiCheatUI>();
							if ((Object)(object)component != (Object)null)
							{
								component.OnMasterClientRecovered();
							}
						}
					}
				}
				else
				{
					Logger.LogInfo((object)"[MASTER CLIENT] Original master left - likely legitimate switch");
					flag = true;
				}
			}
			else if (_anticheatUsers.ContainsKey(newMasterClient.ActorNumber))
			{
				Logger.LogInfo((object)("[MASTER CLIENT] New master client " + newMasterClient.NickName + " has anticheat - likely legitimate switch"));
				flag = true;
			}
			else
			{
				Logger.LogWarning((object)("[MASTER CLIENT] New master client " + newMasterClient.NickName + " does not have anticheat - potential theft"));
				LogVisually("{userColor}" + newMasterClient.NickName + "</color> {leftColor}became master client without anticheat!</color>", onlySendOnce: false, sfxJoin: false, sfxLeave: true);
				DetectionManager.RecordDetection(DetectionType.MasterClientTheft, newMasterClient, "Became master client without anticheat");
			}
		}
		if (flag && _anticheatUsers.ContainsKey(newMasterClient.ActorNumber))
		{
			Logger.LogInfo((object)("[MASTER CLIENT] Syncing with new master client " + newMasterClient.NickName));
			if (!PhotonNetwork.IsMasterClient)
			{
				PhotonNetwork.RaiseEvent((byte)104, (object)null, new RaiseEventOptions
				{
					Receivers = (ReceiverGroup)2
				}, SendOptions.SendReliable);
			}
		}
	}

	[IteratorStateMachine(typeof(<SendSyncToAllClients>d__91))]
	private IEnumerator