Decompiled source of PEAKAntiCheat v1.3.6

PEAKAntiCheat.dll

Decompiled 3 hours ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using System.Text;
using BepInEx;
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.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[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")]
public static class AntiCheatEvents
{
	public static event Action<Player, string, CSteamID, string> OnCheaterDetected;

	public static void NotifyCheaterDetected(Player player, string reason, CSteamID steamID)
	{
		//IL_0021: 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);
	}
}
namespace AntiCheatMod;

public static class ConfigFileExtensions
{
	public static bool ContainsKey(this ConfigFile config, ConfigDefinition key)
	{
		try
		{
			PropertyInfo property = ((object)config).GetType().GetProperty("Entries", BindingFlags.Instance | BindingFlags.NonPublic);
			if (property != null && property.GetValue(config) is IDictionary dictionary)
			{
				return dictionary.Contains(key);
			}
			ConfigEntry<string> val = config.Bind<string>(key.Section, key.Key, "TEST_DEFAULT", (ConfigDescription)null);
			bool result = val.Value != "TEST_DEFAULT";
			config.Remove(key);
			return result;
		}
		catch
		{
			return false;
		}
	}
}
[BepInPlugin("com.hiccup444.anticheat", "PEAK Anticheat", "1.3.6")]
public class AntiCheatPlugin : BaseUnityPlugin, IConnectionCallbacks, IMatchmakingCallbacks, IInRoomCallbacks, IOnEventCallback
{
	[CompilerGenerated]
	private sealed class <>c__DisplayClass46_0
	{
		public CSteamID steamId;

		public bool receivedUpdate;

		internal void <WaitForPersonaStateChange>b__0(PersonaStateChange_t param)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: Invalid comparison between Unknown and I4
			//IL_003b: 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__71 : IEnumerator<object>, IDisposable, IEnumerator
	{
		private int <>1__state;

		private object <>2__current;

		public AntiCheatPlugin <>4__this;

		private Player[] <>s__1;

		private int <>s__2;

		private Player <player>5__3;

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

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

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

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

		private bool MoveNext()
		{
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: 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;
				<>s__1 = PhotonNetwork.PlayerList;
				for (<>s__2 = 0; <>s__2 < <>s__1.Length; <>s__2++)
				{
					<player>5__3 = <>s__1[<>s__2];
					if (<player>5__3.ActorNumber != PhotonNetwork.LocalPlayer.ActorNumber)
					{
						<>4__this.CheckPlayerForCheatMods(<player>5__3);
					}
					<player>5__3 = null;
				}
				<>s__1 = null;
				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__61 : IEnumerator<object>, IDisposable, IEnumerator
	{
		private int <>1__state;

		private object <>2__current;

		public Player player;

		public AntiCheatPlugin <>4__this;

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

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

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

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

		private bool MoveNext()
		{
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: 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;
				<>4__this.CheckPlayerForCheatMods(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__37 : IEnumerator<object>, IDisposable, IEnumerator
	{
		private int <>1__state;

		private object <>2__current;

		public AntiCheatPlugin <>4__this;

		private Player[] <>s__1;

		private int <>s__2;

		private Player <player>5__3;

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

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

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

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

		private bool MoveNext()
		{
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0036: Expected O, but got Unknown
			switch (<>1__state)
			{
			default:
				return false;
			case 0:
				<>1__state = -1;
				break;
			case 1:
				<>1__state = -1;
				if (PhotonNetwork.InRoom)
				{
					<>s__1 = PhotonNetwork.PlayerList;
					for (<>s__2 = 0; <>s__2 < <>s__1.Length; <>s__2++)
					{
						<player>5__3 = <>s__1[<>s__2];
						<>4__this.CheckPlayerForCheatMods(<player>5__3);
						<player>5__3 = null;
					}
					<>s__1 = null;
				}
				break;
			}
			<>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 <DelayedNameCheck>d__45 : IEnumerator<object>, IDisposable, IEnumerator
	{
		private int <>1__state;

		private object <>2__current;

		public Player player;

		public float delay;

		public AntiCheatPlugin <>4__this;

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

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

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

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

		private bool MoveNext()
		{
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: 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;
				if (PhotonNetwork.CurrentRoom != null && PhotonNetwork.CurrentRoom.GetPlayer(player.ActorNumber, false) != null && !_detectedPlayers.Contains(player.ActorNumber) && !_nameWarningShown.Contains(player.ActorNumber))
				{
					Logger.LogInfo((object)("Performing delayed name check for " + player.NickName));
					<>4__this.CheckSteamNameMatch(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 <SendAntiCheatPingDelayed>d__68 : 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__68(int <>1__state)
		{
			this.<>1__state = <>1__state;
		}

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

		private bool MoveNext()
		{
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: Expected O, but got Unknown
			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;
				<>4__this.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 <SendAntiCheatPingResponse>d__74 : IEnumerator<object>, IDisposable, IEnumerator
	{
		private int <>1__state;

		private object <>2__current;

		public Player targetPlayer;

		public AntiCheatPlugin <>4__this;

		private object[] <pingData>5__1;

		private RaiseEventOptions <opts>5__2;

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

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

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

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

		private bool MoveNext()
		{
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: Expected O, but got Unknown
			//IL_00ad: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b3: Expected O, but got Unknown
			//IL_00e1: 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(0.5f);
				<>1__state = 1;
				return true;
			case 1:
			{
				<>1__state = -1;
				if (!PhotonNetwork.IsConnected || !PhotonNetwork.InRoom)
				{
					return false;
				}
				Room currentRoom = PhotonNetwork.CurrentRoom;
				if (((currentRoom != null) ? currentRoom.GetPlayer(targetPlayer.ActorNumber, false) : null) == null)
				{
					return false;
				}
				<pingData>5__1 = new object[3]
				{
					PhotonNetwork.LocalPlayer.NickName,
					PhotonNetwork.LocalPlayer.UserId,
					"1.3.6"
				};
				RaiseEventOptions val = new RaiseEventOptions();
				val.TargetActors = new int[1] { targetPlayer.ActorNumber };
				<opts>5__2 = val;
				PhotonNetwork.RaiseEvent((byte)69, (object)<pingData>5__1, <opts>5__2, SendOptions.SendReliable);
				Logger.LogInfo((object)("[AntiCheat] Sent anticheat ping response to " + targetPlayer.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__62 : IEnumerator<object>, IDisposable, IEnumerator
	{
		private int <>1__state;

		private object <>2__current;

		public Player newPlayer;

		public AntiCheatPlugin <>4__this;

		private object[] <pingData>5__1;

		private RaiseEventOptions <opts>5__2;

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

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

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

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

		private bool MoveNext()
		{
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: Expected O, but got Unknown
			//IL_00b4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ba: Expected O, but got Unknown
			//IL_00e8: 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.IsConnected || !PhotonNetwork.InRoom || PhotonNetwork.LocalPlayer == null)
				{
					return false;
				}
				Room currentRoom = PhotonNetwork.CurrentRoom;
				if (((currentRoom != null) ? currentRoom.GetPlayer(newPlayer.ActorNumber, false) : null) == null)
				{
					return false;
				}
				<pingData>5__1 = new object[3]
				{
					PhotonNetwork.LocalPlayer.NickName,
					PhotonNetwork.LocalPlayer.UserId,
					"1.3.6"
				};
				RaiseEventOptions val = new RaiseEventOptions();
				val.TargetActors = new int[1] { newPlayer.ActorNumber };
				<opts>5__2 = val;
				PhotonNetwork.RaiseEvent((byte)69, (object)<pingData>5__1, <opts>5__2, SendOptions.SendReliable);
				Logger.LogInfo((object)("[AntiCheat] Sent anticheat ping to new player " + newPlayer.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 <TrackPlayerItems>d__63 : IEnumerator<object>, IDisposable, IEnumerator
	{
		private int <>1__state;

		private object <>2__current;

		public AntiCheatPlugin <>4__this;

		private Character[] <allCharacters>5__1;

		private Character[] <>s__2;

		private int <>s__3;

		private Character <character>5__4;

		private PhotonView <photonView>5__5;

		private CharacterData <characterData>5__6;

		private bool <canBeCooked>5__7;

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

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

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

		[DebuggerHidden]
		void IDisposable.Dispose()
		{
			<allCharacters>5__1 = null;
			<>s__2 = null;
			<character>5__4 = null;
			<photonView>5__5 = null;
			<characterData>5__6 = null;
			<>1__state = -2;
		}

		private bool MoveNext()
		{
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0036: Expected O, but got Unknown
			switch (<>1__state)
			{
			default:
				return false;
			case 0:
				<>1__state = -1;
				break;
			case 1:
				<>1__state = -1;
				if (!PhotonNetwork.InRoom)
				{
					break;
				}
				<allCharacters>5__1 = Object.FindObjectsOfType<Character>();
				<>s__2 = <allCharacters>5__1;
				for (<>s__3 = 0; <>s__3 < <>s__2.Length; <>s__3++)
				{
					<character>5__4 = <>s__2[<>s__3];
					<photonView>5__5 = ((Component)<character>5__4).GetComponent<PhotonView>();
					if (!((Object)(object)<photonView>5__5 == (Object)null) && <photonView>5__5.Owner != null && !IsBlocked(<photonView>5__5.Owner.ActorNumber))
					{
						<characterData>5__6 = ((Component)<character>5__4).GetComponent<CharacterData>();
						if ((Object)(object)<characterData>5__6 != (Object)null && (Object)(object)<characterData>5__6.currentItem != (Object)null)
						{
							<canBeCooked>5__7 = (Object)(object)<characterData>5__6.currentItem.cooking != (Object)null && <characterData>5__6.currentItem.cooking.canBeCooked;
							UpdatePlayerHeldItem(<photonView>5__5.Owner.ActorNumber, ((Object)<characterData>5__6.currentItem).name, <canBeCooked>5__7);
						}
						<photonView>5__5 = null;
						<characterData>5__6 = null;
						<character>5__4 = null;
					}
				}
				<>s__2 = null;
				<allCharacters>5__1 = null;
				break;
			}
			<>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__46 : IEnumerator<object>, IDisposable, IEnumerator
	{
		private int <>1__state;

		private object <>2__current;

		public Player player;

		public CSteamID steamId;

		public float timeout;

		public bool blockOnMismatch;

		public AntiCheatPlugin <>4__this;

		private <>c__DisplayClass46_0 <>8__1;

		private float <startTime>5__2;

		private string <lastKnownSteamName>5__3;

		private Callback<PersonaStateChange_t> <personaCallback>5__4;

		private string <freshSteamName>5__5;

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

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

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

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

		private bool MoveNext()
		{
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			//IL_0051: Unknown result type (might be due to invalid IL or missing references)
			//IL_009b: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a5: Expected O, but got Unknown
			//IL_015b: 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__DisplayClass46_0();
				<>8__1.steamId = steamId;
				<startTime>5__2 = Time.time;
				<lastKnownSteamName>5__3 = SteamFriends.GetFriendPersonaName(<>8__1.steamId);
				<>8__1.receivedUpdate = false;
				<personaCallback>5__4 = null;
				<personaCallback>5__4 = Callback<PersonaStateChange_t>.Create((DispatchDelegate<PersonaStateChange_t>)delegate(PersonaStateChange_t param)
				{
					//IL_0001: Unknown result type (might be due to invalid IL or missing references)
					//IL_0019: Unknown result type (might be due to invalid IL or missing references)
					//IL_001a: Unknown result type (might be due to invalid IL or missing references)
					//IL_0020: Unknown result type (might be due to invalid IL or missing references)
					//IL_0022: Invalid comparison between Unknown and I4
					//IL_003b: 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__4?.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__4?.Dispose();
			<freshSteamName>5__5 = SteamFriends.GetFriendPersonaName(<>8__1.steamId);
			if (<freshSteamName>5__5.ToLower() != player.NickName.ToLower())
			{
				if (blockOnMismatch)
				{
					Logger.LogWarning((object)("Name mismatch confirmed after PersonaStateChange: Photon='" + player.NickName + "' vs Steam='" + <freshSteamName>5__5 + "'"));
					LogVisually("{userColor}" + player.NickName + "</color> {leftColor}confirmed spoofing - real Steam name is '" + <freshSteamName>5__5 + "'!</color>", onlySendOnce: true, sfxJoin: false, sfxLeave: true);
					if (PhotonNetwork.CurrentRoom != null && PhotonNetwork.CurrentRoom.GetPlayer(player.ActorNumber, false) != null)
					{
						BlockPlayer(player, "Name spoofing confirmed - real name: " + <freshSteamName>5__5);
					}
				}
				else if (!_nameWarningShown.Contains(player.ActorNumber))
				{
					Logger.LogWarning((object)("Name mismatch on join after refresh: Photon='" + player.NickName + "' vs Steam='" + <freshSteamName>5__5 + "'"));
					LogVisually("{userColor}" + player.NickName + "</color> {leftColor}has mismatched Steam name: '" + <freshSteamName>5__5 + "'</color>", onlySendOnce: true, sfxJoin: false, sfxLeave: true);
					_nameWarningShown.Add(player.ActorNumber);
				}
			}
			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;

	private static AntiCheatPlugin Instance;

	private static ConfigFile Config;

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

	private const string PLUGIN_VERSION = "1.3.6";

	private const byte ANTICHEAT_PING_EVENT = 69;

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

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

	private static readonly HashSet<ulong> _whitelistedSteamIDs = new HashSet<ulong>();

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

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

	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;

	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 readonly Dictionary<int, DateTime> _recentlySpawnedPlayers = new Dictionary<int, DateTime>();

	private const double SPAWN_GRACE_PERIOD_SECONDS = 5.0;

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

	private void Awake()
	{
		//IL_0022: Unknown result type (might be due to invalid IL or missing references)
		//IL_002c: Expected O, but got Unknown
		//IL_0076: Unknown result type (might be due to invalid IL or missing references)
		//IL_007c: Expected O, but got Unknown
		//IL_0198: Unknown result type (might be due to invalid IL or missing references)
		//IL_019e: Expected O, but got Unknown
		Instance = this;
		Logger = ((BaseUnityPlugin)this).Logger;
		Config = new ConfigFile(Path.Combine(Paths.ConfigPath, "com.hiccup444.PEAKanticheat.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");
		bool flag = true;
		ConfigDefinition val = new ConfigDefinition("General", "AutoPunishCheaters");
		if (Config.ContainsKey(val))
		{
			ConfigEntry<bool> val2 = Config.Bind<bool>("General", "AutoPunishCheaters", true, "DEPRECATED - Use AutoBlockCheaters instead");
			flag = val2.Value;
			Config.Remove(val);
			Logger.LogInfo((object)$"[CONFIG MIGRATION] Migrated AutoPunishCheaters ({flag}) to AutoBlockCheaters");
		}
		AutoBlockCheaters = Config.Bind<bool>("General", "AutoBlockCheaters", flag, "Automatically block all RPCs from detected cheaters (replaces AutoPunishCheaters)");
		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')");
		ParseWhitelist();
		Config.Save();
		Logger.LogInfo((object)"[PEAKAntiCheat] Protection active! (RPC Blocking Mode)");
		if (_whitelistedSteamIDs.Count > 0)
		{
			Logger.LogInfo((object)$"[PEAKAntiCheat] Loaded {_whitelistedSteamIDs.Count} whitelisted Steam IDs");
		}
		Harmony val3 = new Harmony("com.hiccup444.PEAKanticheat");
		val3.PatchAll();
		PhotonNetwork.AddCallbackTarget((object)this);
		((MonoBehaviour)this).StartCoroutine(CheckPlayersForCheats());
		((MonoBehaviour)this).StartCoroutine(TrackPlayerItems());
		SceneManager.sceneLoaded += OnSceneLoaded;
	}

	private void Update()
	{
		while (_queuedLogs.Count != 0)
		{
			(string, bool, bool, bool) tuple = _queuedLogs.Peek();
			if (!LogVisually(tuple.Item1, tuple.Item2, tuple.Item3, tuple.Item4))
			{
				break;
			}
			_queuedLogs.Dequeue();
		}
	}

	private void OnDestroy()
	{
		PhotonNetwork.RemoveCallbackTarget((object)this);
		SceneManager.sceneLoaded -= OnSceneLoaded;
	}

	private static void ParseWhitelist()
	{
		_whitelistedSteamIDs.Clear();
		string value = WhitelistedSteamIDs.Value;
		if (string.IsNullOrWhiteSpace(value))
		{
			return;
		}
		string[] array = value.Split(new char[1] { ',' });
		string[] array2 = array;
		foreach (string text in array2)
		{
			string text2 = text.Trim();
			if (ulong.TryParse(text2, out var result))
			{
				_whitelistedSteamIDs.Add(result);
				Logger.LogInfo((object)$"[WHITELIST] Added Steam ID to whitelist: {result}");
			}
			else if (!string.IsNullOrEmpty(text2))
			{
				Logger.LogWarning((object)("[WHITELIST] Invalid Steam ID format: " + text2));
			}
		}
	}

	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)
	{
		Logger.LogInfo((object)$"[PlayerHadItem] Checking actor {actorNumber} for item containing '{itemNamePart}' within {withinSeconds} seconds (cookable check: {checkCookable})");
		if (_playerLastHeldItems.TryGetValue(actorNumber, out (string, DateTime, bool) value))
		{
			double totalSeconds = (DateTime.Now - value.Item2).TotalSeconds;
			Logger.LogInfo((object)$"[PlayerHadItem] Found item: {value.Item1}, held {totalSeconds:F2} seconds ago");
			if (totalSeconds <= (double)withinSeconds)
			{
				if (checkCookable)
				{
					Logger.LogInfo((object)$"[PlayerHadItem] Within time window. Was cookable? {value.Item3}");
					return value.Item3;
				}
				bool flag = value.Item1.Contains(itemNamePart.ToLower());
				Logger.LogInfo((object)$"[PlayerHadItem] Within time window. Contains '{itemNamePart}'? {flag}");
				return flag;
			}
			Logger.LogInfo((object)$"[PlayerHadItem] Outside time window ({totalSeconds:F2} > {withinSeconds})");
		}
		else
		{
			Logger.LogInfo((object)$"[PlayerHadItem] No item history found for actor {actorNumber}");
		}
		return false;
	}

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

	public static bool LogVisually(string message, bool onlySendOnce = false, bool sfxJoin = false, bool sfxLeave = false)
	{
		//IL_0399: Unknown result type (might be due to invalid IL or missing references)
		//IL_0413: Unknown result type (might be due to invalid IL or missing references)
		if (!ShowVisualLogs.Value)
		{
			return true;
		}
		if (!Object.op_Implicit((Object)(object)_connectionLog))
		{
			_connectionLog = Object.FindObjectOfType<PlayerConnectionLog>();
			if (Object.op_Implicit((Object)(object)_connectionLog))
			{
				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);
				if (_getColorTagMethod == null)
				{
					Logger.LogWarning((object)"GetColorTag method not found!");
				}
				if (_addMessageMethod == null)
				{
					Logger.LogWarning((object)"AddMessage method not found!");
				}
				if (_currentLogField == null)
				{
					Logger.LogWarning((object)"currentLog field not found!");
				}
			}
		}
		if (!Object.op_Implicit((Object)(object)_connectionLog) || _getColorTagMethod == null || _addMessageMethod == null)
		{
			_queuedLogs.Enqueue((message, onlySendOnce, sfxJoin, sfxLeave));
			return false;
		}
		try
		{
			StringBuilder stringBuilder = new StringBuilder(message);
			FieldInfo field = ((object)_connectionLog).GetType().GetField("joinedColor", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
			FieldInfo field2 = ((object)_connectionLog).GetType().GetField("leftColor", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
			FieldInfo field3 = ((object)_connectionLog).GetType().GetField("userColor", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
			if (field != null && field2 != null && field3 != null)
			{
				object value = field.GetValue(_connectionLog);
				object value2 = field2.GetValue(_connectionLog);
				object value3 = field3.GetValue(_connectionLog);
				string text = (string)_getColorTagMethod.Invoke(_connectionLog, new object[1] { value });
				string text2 = (string)_getColorTagMethod.Invoke(_connectionLog, new object[1] { value2 });
				string 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;
				}
			}
			_addMessageMethod.Invoke(_connectionLog, new object[1] { message });
			FieldInfo field4 = ((object)_connectionLog).GetType().GetField("sfxJoin", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
			FieldInfo field5 = ((object)_connectionLog).GetType().GetField("sfxLeave", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
			if (sfxJoin && field4 != null)
			{
				object value4 = field4.GetValue(_connectionLog);
				value4?.GetType().GetMethod("Play", new Type[1] { typeof(Vector3) })?.Invoke(value4, new object[1] { Vector3.zero });
			}
			if (sfxLeave && field5 != null)
			{
				object value5 = field5.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 BlockPlayer(Player cheater, string reason)
	{
		//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)
		//IL_019b: Unknown result type (might be due to invalid IL or missing references)
		//IL_01a0: Unknown result type (might be due to invalid IL or missing references)
		//IL_01a1: Unknown result type (might be due to invalid IL or missing references)
		//IL_01a2: Unknown result type (might be due to invalid IL or missing references)
		//IL_0102: Unknown result type (might be due to invalid IL or missing references)
		//IL_0107: Unknown result type (might be due to invalid IL or missing references)
		//IL_0128: Unknown result type (might be due to invalid IL or missing references)
		//IL_0139: Unknown result type (might be due to invalid IL or missing references)
		//IL_013a: Unknown result type (might be due to invalid IL or missing references)
		//IL_01da: Unknown result type (might be due to invalid IL or missing references)
		//IL_01db: 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_026e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0216: Unknown result type (might be due to invalid IL or missing references)
		//IL_025b: 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");
		}
		else if (cheater.IsMasterClient)
		{
			Logger.LogWarning((object)("[BLOCK PREVENTED] Attempted to block master client " + cheater.NickName + " for: " + reason));
		}
		else
		{
			if (_detectedPlayers.Contains(cheater.ActorNumber))
			{
				return;
			}
			Logger.LogWarning((object)("CHEATER DETECTED: " + cheater.NickName + " - Reason: " + reason));
			_detectedPlayers.Add(cheater.ActorNumber);
			CSteamID nil = CSteamID.Nil;
			PlayerIdentity playerIdentity = _knownPlayerIdentities.Find((PlayerIdentity p) => p.ActorNumber == cheater.ActorNumber);
			if (playerIdentity != null)
			{
				nil = playerIdentity.SteamID;
				Logger.LogWarning((object)$"[Detection] Found identity for Actor #{cheater.ActorNumber}: PhotonName={playerIdentity.PhotonName}, SteamID={nil}");
				if (nil == CSteamID.Nil)
				{
					Logger.LogWarning((object)("[Detection] WARNING: Stored SteamID is NIL for " + playerIdentity.PhotonName + "."));
				}
			}
			else
			{
				Logger.LogWarning((object)$"[Detection] No identity found for Actor #{cheater.ActorNumber}, attempting fallback SteamID lookup...");
				nil = GetPlayerSteamID(cheater);
				if (nil == CSteamID.Nil)
				{
					Logger.LogWarning((object)("[Detection] Fallback GetPlayerSteamID() returned NIL for " + cheater.NickName + "."));
				}
			}
			if (nil != CSteamID.Nil && _whitelistedSteamIDs.Contains(nil.m_SteamID))
			{
				Logger.LogInfo((object)$"[WHITELIST] Player {cheater.NickName} (Steam ID: {nil}) is whitelisted - not blocking");
				LogVisually("{userColor}" + cheater.NickName + "</color> {joinedColor}is whitelisted - no action taken</color>");
				AntiCheatEvents.NotifyCheaterDetected(cheater, reason + " (WHITELISTED)", nil);
				return;
			}
			AntiCheatEvents.NotifyCheaterDetected(cheater, reason, nil);
			if (!AutoBlockCheaters.Value)
			{
				Logger.LogInfo((object)("Auto-blocking disabled - only logging cheater: " + cheater.NickName));
				LogVisually("{userColor}" + cheater.NickName + "</color> {leftColor}detected - " + reason + " (no action taken)</color>", onlySendOnce: false, sfxJoin: false, sfxLeave: true);
			}
			else if (!_blockedPlayers.Contains(cheater.ActorNumber))
			{
				_blockedPlayers.Add(cheater.ActorNumber);
				LogVisually("{userColor}" + cheater.NickName + "</color> {leftColor}RPC blocked - " + reason + "</color>", onlySendOnce: false, sfxJoin: false, sfxLeave: true);
				Logger.LogInfo((object)$"All RPCs from {cheater.NickName} (Actor #{cheater.ActorNumber}) are now blocked");
			}
		}
	}

	public static void SoftLockPlayer(Player cheater, string reason)
	{
		BlockPlayer(cheater, reason);
	}

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

	public static void AddToBlockList(int actorNumber)
	{
		if (!_blockedPlayers.Contains(actorNumber))
		{
			_blockedPlayers.Add(actorNumber);
			Logger.LogInfo((object)$"Added actor #{actorNumber} to RPC block list");
		}
	}

	public static void AddToSoftLockList(int actorNumber)
	{
		AddToBlockList(actorNumber);
	}

	private static CSteamID GetPlayerSteamID(Player player)
	{
		//IL_0549: Unknown result type (might be due to invalid IL or missing references)
		//IL_054e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0552: 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_0035: 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_0087: Unknown result type (might be due to invalid IL or missing references)
		//IL_0089: Unknown result type (might be due to invalid IL or missing references)
		//IL_008b: Unknown result type (might be due to invalid IL or missing references)
		//IL_006f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0074: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b8: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ac: 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_00fc: Unknown result type (might be due to invalid IL or missing references)
		//IL_0100: Unknown result type (might be due to invalid IL or missing references)
		//IL_0105: Unknown result type (might be due to invalid IL or missing references)
		//IL_0107: Unknown result type (might be due to invalid IL or missing references)
		//IL_011c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0158: Unknown result type (might be due to invalid IL or missing references)
		//IL_0162: Unknown result type (might be due to invalid IL or missing references)
		//IL_03fb: Unknown result type (might be due to invalid IL or missing references)
		//IL_0400: Unknown result type (might be due to invalid IL or missing references)
		//IL_02b5: Unknown result type (might be due to invalid IL or missing references)
		//IL_02ba: Unknown result type (might be due to invalid IL or missing references)
		//IL_0418: Unknown result type (might be due to invalid IL or missing references)
		//IL_041d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0511: Unknown result type (might be due to invalid IL or missing references)
		//IL_0516: Unknown result type (might be due to invalid IL or missing references)
		//IL_043e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0443: Unknown result type (might be due to invalid IL or missing references)
		//IL_0379: Unknown result type (might be due to invalid IL or missing references)
		//IL_0391: Unknown result type (might be due to invalid IL or missing references)
		//IL_0396: Unknown result type (might be due to invalid IL or missing references)
		//IL_0335: Unknown result type (might be due to invalid IL or missing references)
		//IL_0355: Unknown result type (might be due to invalid IL or missing references)
		//IL_035a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0499: Unknown result type (might be due to invalid IL or missing references)
		//IL_04a3: Unknown result type (might be due to invalid IL or missing references)
		//IL_04b6: Unknown result type (might be due to invalid IL or missing references)
		//IL_04d1: Unknown result type (might be due to invalid IL or missing references)
		//IL_04d3: 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;
			}
			Type type = ((object)service).GetType();
			FieldInfo field = type.GetField("m_currentLobby", BindingFlags.Instance | BindingFlags.NonPublic);
			if (field == null)
			{
				Logger.LogError((object)"[GetPlayerSteamID] Could not find m_currentLobby field via reflection.");
				return CSteamID.Nil;
			}
			CSteamID val = (CSteamID)field.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);
				Logger.LogInfo((object)$"[GetPlayerSteamID] Found Steam user: Name='{friendPersonaName}', SteamID={lobbyMemberByIndex}");
				if (!dictionary.ContainsKey(friendPersonaName))
				{
					dictionary[friendPersonaName] = new List<CSteamID>();
				}
				dictionary[friendPersonaName].Add(lobbyMemberByIndex);
				list.Add(lobbyMemberByIndex);
			}
			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>();
				Player[] playerList = PhotonNetwork.PlayerList;
				foreach (Player val2 in playerList)
				{
					if (val2.NickName == player.NickName)
					{
						list3.Add(val2);
					}
				}
				Logger.LogInfo((object)$"[GetPlayerSteamID] Found {list3.Count} Photon players with name '{player.NickName}'.");
				if (list3.Count > list2.Count)
				{
					Logger.LogWarning((object)$"[GetPlayerSteamID] More Photon players ({list3.Count}) than Steam players ({list2.Count}) for name '{player.NickName}'. Returning NIL as it's likely spoofed.");
					return CSteamID.Nil;
				}
				list3.Sort((Player a, Player b) => a.ActorNumber.CompareTo(b.ActorNumber));
				int num = list3.FindIndex((Player p) => p.ActorNumber == player.ActorNumber);
				if (num >= 0 && num < list2.Count)
				{
					Logger.LogInfo((object)$"[GetPlayerSteamID] Matched ActorNumber {player.ActorNumber} to SteamID {list2[num]} (index {num}).");
					return list2[num];
				}
				Logger.LogWarning((object)$"[GetPlayerSteamID] Could not find matching ActorNumber for {player.NickName}. Returning first available SteamID: {list2[0]}");
				return list2[0];
			}
			Logger.LogInfo((object)("[GetPlayerSteamID] No exact match for '" + player.NickName + "', checking for unassigned Steam IDs..."));
			int num2 = PhotonNetwork.PlayerList.Length;
			if (num2 > numLobbyMembers)
			{
				Logger.LogWarning((object)$"[GetPlayerSteamID] More Photon players ({num2}) than Steam lobby members ({numLobbyMembers}). Possible spoofer.");
				return CSteamID.Nil;
			}
			foreach (CSteamID item in list)
			{
				bool flag = false;
				foreach (PlayerIdentity knownPlayerIdentity in _knownPlayerIdentities)
				{
					if (knownPlayerIdentity.SteamID == item && knownPlayerIdentity.ActorNumber != player.ActorNumber)
					{
						flag = true;
						break;
					}
				}
				if (!flag)
				{
					bool flag2 = SteamFriends.RequestUserInformation(item, true);
					string friendPersonaName2 = SteamFriends.GetFriendPersonaName(item);
					Logger.LogWarning((object)$"[GetPlayerSteamID] Found unassigned Steam ID {item} (name: '{friendPersonaName2}', needs refresh: {flag2})");
					return item;
				}
			}
			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] Exception while resolving Steam ID for " + player.NickName + ": " + ex.Message));
			return CSteamID.Nil;
		}
	}

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

	private static List<CSteamID> GetSteamIDsForName(string steamName)
	{
		//IL_0053: Unknown result type (might be due to invalid IL or missing references)
		//IL_0058: Unknown result type (might be due to invalid IL or missing references)
		//IL_0059: Unknown result type (might be due to invalid IL or missing references)
		//IL_005a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0076: Unknown result type (might be due to invalid IL or missing references)
		//IL_008b: Unknown result type (might be due to invalid IL or missing references)
		//IL_008e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0093: Unknown result type (might be due to invalid IL or missing references)
		//IL_0095: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ae: Unknown result type (might be due to invalid IL or missing references)
		try
		{
			SteamLobbyHandler service = GameHandler.GetService<SteamLobbyHandler>();
			if (service == null)
			{
				return new List<CSteamID>();
			}
			Type type = ((object)service).GetType();
			FieldInfo field = type.GetField("m_currentLobby", BindingFlags.Instance | BindingFlags.NonPublic);
			if (field == null)
			{
				return new List<CSteamID>();
			}
			CSteamID val = (CSteamID)field.GetValue(service);
			if (val == CSteamID.Nil)
			{
				return new List<CSteamID>();
			}
			int numLobbyMembers = SteamMatchmaking.GetNumLobbyMembers(val);
			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 (friendPersonaName == steamName)
				{
					list.Add(lobbyMemberByIndex);
				}
			}
			return list;
		}
		catch (Exception ex)
		{
			Logger.LogError((object)("Error getting SteamIDs for name " + steamName + ": " + ex.Message));
			return new List<CSteamID>();
		}
	}

	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;
	}

	private void CheckPlayerForCheatMods(Player player)
	{
		//IL_0075: Unknown result type (might be due to invalid IL or missing references)
		//IL_007a: 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_00b9: 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)
		if (player.ActorNumber == PhotonNetwork.LocalPlayer.ActorNumber || _detectedPlayers.Contains(player.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));
		}
		List<Player> list = new List<Player>();
		Player[] playerList = PhotonNetwork.PlayerList;
		foreach (Player val in playerList)
		{
			if (val.ActorNumber != player.ActorNumber && val.NickName == player.NickName)
			{
				list.Add(val);
			}
		}
		if (list.Count > 0)
		{
			if (player.NickName.ToLower() == PhotonNetwork.LocalPlayer.NickName.ToLower())
			{
				Logger.LogWarning((object)(player.NickName + " joined with the same name as the local player! This can cause character assignment issues."));
				LogVisually("{userColor}" + player.NickName + "</color> {leftColor}joined with your name - possible impersonator!</color>", onlySendOnce: true, sfxJoin: false, sfxLeave: true);
				BlockPlayer(player, "Name impersonation - using local player's name");
				return;
			}
			Logger.LogInfo((object)("Duplicate Photon name '" + player.NickName + "' found, but enough matching Steam names exist. Allowing."));
		}
		if (player.IsMasterClient)
		{
			Logger.LogInfo((object)("[CHECK SKIPPED] Not checking master client " + player.NickName + " for cheat mods"));
		}
		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);
			BlockPlayer(player, "Cherry cheat mod user");
		}
		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);
			BlockPlayer(player, "Cherry cheat mod owner");
		}
		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);
			BlockPlayer(player, "Atlas cheat mod user");
		}
		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);
			BlockPlayer(player, "Atlas cheat mod owner");
		}
		else if (CheckSteamNames.Value)
		{
			CheckSteamNameMatch(player);
		}
	}

	private void CheckSteamNameMatch(Player player)
	{
		//IL_0049: Unknown result type (might be due to invalid IL or missing references)
		//IL_004e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0066: Unknown result type (might be due to invalid IL or missing references)
		//IL_00dc: 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_00c0: Unknown result type (might be due to invalid IL or missing references)
		//IL_01cd: Unknown result type (might be due to invalid IL or missing references)
		//IL_01e1: Unknown result type (might be due to invalid IL or missing references)
		//IL_01e4: Unknown result type (might be due to invalid IL or missing references)
		//IL_01e9: Unknown result type (might be due to invalid IL or missing references)
		//IL_01eb: Unknown result type (might be due to invalid IL or missing references)
		//IL_0205: Unknown result type (might be due to invalid IL or missing references)
		if (_nameWarningShown.Contains(player.ActorNumber))
		{
			return;
		}
		PlayerIdentity playerIdentity = _knownPlayerIdentities.Find((PlayerIdentity p) => p.ActorNumber == player.ActorNumber);
		if (playerIdentity != null && playerIdentity.SteamID != CSteamID.Nil)
		{
			if (SteamFriends.RequestUserInformation(playerIdentity.SteamID, true))
			{
				Logger.LogInfo((object)$"Requesting fresh Steam data for {player.NickName} (Actor #{player.ActorNumber}, SteamID: {playerIdentity.SteamID})");
				((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);
				_nameWarningShown.Add(player.ActorNumber);
			}
			return;
		}
		SteamLobbyHandler service = GameHandler.GetService<SteamLobbyHandler>();
		CSteamID val = default(CSteamID);
		if (service == null || !service.InSteamLobby(ref val))
		{
			return;
		}
		int numLobbyMembers = SteamMatchmaking.GetNumLobbyMembers(val);
		bool flag = false;
		int num = 0;
		for (int i = 0; i < numLobbyMembers; i++)
		{
			CSteamID lobbyMemberByIndex = SteamMatchmaking.GetLobbyMemberByIndex(val, i);
			if (SteamFriends.RequestUserInformation(lobbyMemberByIndex, true))
			{
				num++;
			}
			string friendPersonaName2 = SteamFriends.GetFriendPersonaName(lobbyMemberByIndex);
			if (friendPersonaName2 == player.NickName)
			{
				flag = true;
				break;
			}
		}
		if (num > 0 && !flag)
		{
			Logger.LogInfo((object)$"{num} Steam members need data refresh. Delaying name check for {player.NickName}");
			((MonoBehaviour)this).StartCoroutine(DelayedNameCheck(player, 3f));
		}
		else if (!flag && !_nameWarningShown.Contains(player.ActorNumber))
		{
			Logger.LogWarning((object)(player.NickName + " has no matching Steam name in lobby!"));
			LogVisually("{userColor}" + player.NickName + "</color> {leftColor}has no matching Steam name in lobby!</color>", onlySendOnce: true, sfxJoin: false, sfxLeave: true);
			_nameWarningShown.Add(player.ActorNumber);
		}
	}

	[IteratorStateMachine(typeof(<DelayedNameCheck>d__45))]
	private IEnumerator DelayedNameCheck(Player player, float delay)
	{
		//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
		return new <DelayedNameCheck>d__45(0)
		{
			<>4__this = this,
			player = player,
			delay = delay
		};
	}

	[IteratorStateMachine(typeof(<WaitForPersonaStateChange>d__46))]
	private IEnumerator WaitForPersonaStateChange(Player player, CSteamID steamId, float timeout, bool blockOnMismatch = true)
	{
		//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)
		//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
		return new <WaitForPersonaStateChange>d__46(0)
		{
			<>4__this = this,
			player = player,
			steamId = steamId,
			timeout = timeout,
			blockOnMismatch = blockOnMismatch
		};
	}

	public void OnMasterClientSwitched(Player newMasterClient)
	{
		//IL_006d: Unknown result type (might be due to invalid IL or missing references)
		//IL_006e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0073: Unknown result type (might be due to invalid IL or missing references)
		Logger.LogInfo((object)$"{newMasterClient.NickName} (#{newMasterClient.ActorNumber}) is the new master client!");
		if (newMasterClient.ActorNumber == PhotonNetwork.LocalPlayer.ActorNumber || PhotonNetwork.LocalPlayer.IsMasterClient)
		{
			return;
		}
		SteamLobbyHandler service = GameHandler.GetService<SteamLobbyHandler>();
		CSteamID val = default(CSteamID);
		if (service != null && service.InSteamLobby(ref val) && SteamMatchmaking.GetLobbyOwner(val) == SteamUser.GetSteamID())
		{
			Logger.LogWarning((object)("Master client stolen by: " + newMasterClient.NickName));
			LogVisually("{userColor}" + newMasterClient.NickName + "</color> {leftColor}tried to take master client</color>", onlySendOnce: false, sfxJoin: false, sfxLeave: true);
			BlockPlayer(newMasterClient, "Stole master client");
			if (!PhotonNetwork.LocalPlayer.IsMasterClient)
			{
				PhotonNetwork.SetMasterClient(PhotonNetwork.LocalPlayer);
				Logger.LogInfo((object)"Reclaimed master client after blocking cheater");
			}
		}
	}

	public void OnConnected()
	{
	}

	public void OnConnectedToMaster()
	{
	}

	public void OnDisconnected(DisconnectCause cause)
	{
	}

	public void OnRegionListReceived(RegionHandler regionHandler)
	{
	}

	public void OnCustomAuthenticationResponse(Dictionary<string, object> data)
	{
	}

	public void OnCustomAuthenticationFailed(string debugMessage)
	{
	}

	public void OnFriendListUpdate(List<FriendInfo> friendList)
	{
	}

	public void OnCreatedRoom()
	{
	}

	public void OnCreateRoomFailed(short returnCode, string message)
	{
	}

	public void OnJoinRoomFailed(short returnCode, string message)
	{
	}

	public void OnJoinRandomFailed(short returnCode, string message)
	{
	}

	public void OnLeftRoom()
	{
		_knownPlayerIdentities.Clear();
		_blockedPlayers.Clear();
		_detectedPlayers.Clear();
		_playerLastHeldItems.Clear();
		_anticheatUsers.Clear();
		_nameWarningShown.Clear();
	}

	public void OnPlayerEnteredRoom(Player newPlayer)
	{
		OnPlayerSpawned(newPlayer.ActorNumber);
		((MonoBehaviour)this).StartCoroutine(CheckNewPlayerDelayed(newPlayer));
		if (newPlayer.ActorNumber != PhotonNetwork.LocalPlayer.ActorNumber)
		{
			((MonoBehaviour)this).StartCoroutine(SendAntiCheatPingToNewPlayer(newPlayer));
		}
	}

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

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

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

	public void OnPlayerLeftRoom(Player otherPlayer)
	{
		_knownPlayerIdentities.RemoveAll((PlayerIdentity p) => p.ActorNumber == otherPlayer.ActorNumber);
		_playerLastHeldItems.Remove(otherPlayer.ActorNumber);
		_recentlySpawnedPlayers.Remove(otherPlayer.ActorNumber);
		if (_blockedPlayers.Contains(otherPlayer.ActorNumber))
		{
			_blockedPlayers.Remove(otherPlayer.ActorNumber);
			Logger.LogInfo((object)("Removed " + otherPlayer.NickName + " from RPC block list (disconnected)"));
		}
		if (_detectedPlayers.Contains(otherPlayer.ActorNumber))
		{
			_detectedPlayers.Remove(otherPlayer.ActorNumber);
			Logger.LogInfo((object)("Removed " + otherPlayer.NickName + " from detected list (disconnected)"));
		}
		if (_anticheatUsers.ContainsKey(otherPlayer.ActorNumber))
		{
			_anticheatUsers.Remove(otherPlayer.ActorNumber);
			Logger.LogInfo((object)("Removed " + otherPlayer.NickName + " from anticheat users list (disconnected)"));
		}
		if (_nameWarningShown.Contains(otherPlayer.ActorNumber))
		{
			_nameWarningShown.Remove(otherPlayer.ActorNumber);
		}
	}

	public void OnPlayerPropertiesUpdate(Player targetPlayer, Hashtable changedProps)
	{
		//IL_0160: Unknown result type (might be due to invalid IL or missing references)
		//IL_0158: 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_0166: Unknown result type (might be due to invalid IL or missing references)
		//IL_0167: Unknown result type (might be due to invalid IL or missing references)
		//IL_017b: Unknown result type (might be due to invalid IL or missing references)
		//IL_01ae: Unknown result type (might be due to invalid IL or missing references)
		//IL_0195: Unknown result type (might be due to invalid IL or missing references)
		if (!((Dictionary<object, object>)(object)changedProps).ContainsKey((object)"name") && !((Dictionary<object, object>)(object)changedProps).ContainsKey((object)"NickName"))
		{
			return;
		}
		Logger.LogInfo((object)$"Player {targetPlayer.ActorNumber} changed their name mid-game to {targetPlayer.NickName}");
		if (targetPlayer.ActorNumber == PhotonNetwork.LocalPlayer.ActorNumber)
		{
			return;
		}
		PlayerIdentity playerIdentity = _knownPlayerIdentities.Find((PlayerIdentity p) => p.ActorNumber == targetPlayer.ActorNumber);
		if (playerIdentity != null && playerIdentity.PhotonName != targetPlayer.NickName)
		{
			Logger.LogWarning((object)$"{targetPlayer.ActorNumber} changed their Photon name from {playerIdentity.PhotonName} to {targetPlayer.NickName} - definite spoof attempt");
			LogVisually("{userColor}" + targetPlayer.NickName + "</color> {leftColor}changed name mid-game from '" + playerIdentity.PhotonName + "' - spoofing detected!</color>", onlySendOnce: true, sfxJoin: false, sfxLeave: true);
			BlockPlayer(targetPlayer, "Mid-game name change - spoofing");
			return;
		}
		CSteamID val = playerIdentity?.SteamID ?? GetPlayerSteamID(targetPlayer);
		if (val != CSteamID.Nil)
		{
			if (SteamFriends.RequestUserInformation(val, true))
			{
				((MonoBehaviour)this).StartCoroutine(WaitForPersonaStateChange(targetPlayer, val, 5f));
			}
			else
			{
				string friendPersonaName = SteamFriends.GetFriendPersonaName(val);
				if (friendPersonaName.ToLower() != targetPlayer.NickName.ToLower())
				{
					Logger.LogWarning((object)("Mid-game name change doesn't match Steam: Photon='" + targetPlayer.NickName + "' vs Steam='" + friendPersonaName + "'"));
					LogVisually("{userColor}" + targetPlayer.NickName + "</color> {leftColor}changed name mid-game - doesn't match Steam name '" + friendPersonaName + "'!</color>", onlySendOnce: true, sfxJoin: false, sfxLeave: true);
					BlockPlayer(targetPlayer, "Mid-game name spoofing - Steam name: " + friendPersonaName);
				}
			}
		}
		CheckPlayerForCheatMods(targetPlayer);
	}

	public void OnRoomPropertiesUpdate(Hashtable propertiesThatChanged)
	{
	}

	public void OnJoinedRoom()
	{
		Logger.LogInfo((object)"Joined room - checking all existing players for cheats/spoofing");
		OnPlayerSpawned(PhotonNetwork.LocalPlayer.ActorNumber);
		Logger.LogInfo((object)"Added local player to spawn grace period on room join");
		((MonoBehaviour)this).StartCoroutine(CheckAllPlayersOnJoin());
		((MonoBehaviour)this).StartCoroutine(SendAntiCheatPingDelayed());
	}

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

	private void SendAntiCheatPing()
	{
		//IL_005a: Unknown result type (might be due to invalid IL or missing references)
		//IL_005f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0061: Unknown result type (might be due to invalid IL or missing references)
		//IL_0067: Expected O, but got Unknown
		//IL_006b: Unknown result type (might be due to invalid IL or missing references)
		if (!PhotonNetwork.IsConnected || !PhotonNetwork.InRoom || PhotonNetwork.LocalPlayer == null)
		{
			Logger.LogWarning((object)"[AntiCheat] Cannot send ping - not in a room yet");
			return;
		}
		object[] array = new object[3]
		{
			PhotonNetwork.LocalPlayer.NickName,
			PhotonNetwork.LocalPlayer.UserId,
			"1.3.6"
		};
		RaiseEventOptions val = new RaiseEventOptions
		{
			Receivers = (ReceiverGroup)0
		};
		PhotonNetwork.RaiseEvent((byte)69, (object)array, val, SendOptions.SendReliable);
		Logger.LogInfo((object)"[AntiCheat] Sent anticheat detection ping to other players");
	}

	private void OnSceneLoaded(Scene scene, LoadSceneMode mode)
	{
		if (((Scene)(ref scene)).name.Contains("Level"))
		{
			Player[] playerList = PhotonNetwork.PlayerList;
			foreach (Player val in playerList)
			{
				OnPlayerSpawned(val.ActorNumber);
			}
			if (PhotonNetwork.InRoom && PhotonNetwork.LocalPlayer != null)
			{
				OnPlayerSpawned(PhotonNetwork.LocalPlayer.ActorNumber);
			}
			Logger.LogInfo((object)("Entered game scene '" + ((Scene)(ref scene)).name + "' - granting spawn grace period to all players including local"));
		}
	}

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

	public void OnEvent(EventData photonEvent)
	{
		if (photonEvent.Code == 69)
		{
			HandleAntiCheatPing(photonEvent);
		}
	}

	private void HandleAntiCheatPing(EventData eventData)
	{
		if (!(eventData.CustomData is object[] array) || array.Length < 3)
		{
			return;
		}
		string text = array[0] as string;
		string text2 = array[1] as string;
		string text3 = array[2] as string;
		if (text == null || text3 == null)
		{
			return;
		}
		Player val = null;
		Player[] playerList = PhotonNetwork.PlayerList;
		foreach (Player val2 in playerList)
		{
			if (val2.NickName == text && val2.ActorNumber == eventData.Sender)
			{
				val = val2;
				break;
			}
		}
		if (val == null)
		{
			Logger.LogWarning((object)("[AntiCheat] Received ping from unknown player: " + text));
		}
		else if (!_anticheatUsers.ContainsKey(val.ActorNumber))
		{
			_anticheatUsers[val.ActorNumber] = text3;
			Logger.LogInfo((object)("[AntiCheat] " + val.NickName + " has PEAK Anticheat v" + text3));
			LogVisually("{joinedColor}" + val.NickName + " has PEAK Anticheat v" + text3 + "</color>", onlySendOnce: true, sfxJoin: true);
			if (val.ActorNumber != PhotonNetwork.LocalPlayer.ActorNumber)
			{
				((MonoBehaviour)this).StartCoroutine(SendAntiCheatPingResponse(val));
			}
		}
	}

	[IteratorStateMachine(typeof(<SendAntiCheatPingResponse>d__74))]
	private IEnumerator SendAntiCheatPingResponse(Player targetPlayer)
	{
		//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
		return new <SendAntiCheatPingResponse>d__74(0)
		{
			<>4__this = this,
			targetPlayer = targetPlayer
		};
	}
}
public class PlayerIdentity
{
	public string PhotonName;

	public int ActorNumber;

	public CSteamID SteamID;

	public PlayerIdentity(string photonName, int actorNumber, CSteamID steamID)
	{
		//IL_0017: 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)
		PhotonName = photonName;
		ActorNumber = actorNumber;
		SteamID = steamID;
	}
}
[HarmonyPatch]
public static class RPCDetection
{
	public enum OwnershipCondition
	{
		IsMasterClient,
		IsViewOwner,
		IsMasterClientOrViewOwner
	}

	public class RPCPattern
	{
		public string MethodId { get; set; }

		public string Description { get; set; }

		public Func<object[], bool> ParameterCheck { get; set; }

		public bool RequiresMasterClient { get; set; }
	}

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

	private static Dictionary<int, int> _ownershipRequestCount = new Dictionary<int, int>();

	private static readonly byte keyByte0 = 0;

	private static Dictionary<int, Dictionary<int, int>> _eventRateCounts = new Dictionary<int, Dictionary<int, int>>();

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

	private const int SUSPICIOUS_EVENT_THRESHOLD = 10;

	private static bool IsRpcValid(PhotonView view, Player sender, OwnershipCondition ownershipCondition, Func<bool> validCondition = null)
	{
		if (sender == null)
		{
			return true;
		}
		switch (ownershipCondition)
		{
		case OwnershipCondition.IsMasterClient:
			if (sender.IsMasterClient)
			{
				return true;
			}
			break;
		case OwnershipCondition.IsViewOwner:
			if ((Object)(object)view != (Object)null && view.Owner != null && sender.ActorNumber == view.Owner.ActorNumber)
			{
				return true;
			}
			break;
		case OwnershipCondition.IsMasterClientOrViewOwner:
			if (sender.IsMasterClient || ((Object)(object)view != (Object)null && view.Owner != null && sender.ActorNumber == view.Owner.ActorNumber))
			{
				return true;
			}
			break;
		}
		return validCondition?.Invoke() ?? true;
	}

	[HarmonyPatch(typeof(PhotonNetwork), "OnEvent")]
	[HarmonyPrefix]
	public static bool PreOnEvent(EventData photonEvent)
	{
		int sender = photonEvent.Sender;
		if (sender > 0 && AntiCheatPlugin.IsBlocked(sender))
		{
			return false;
		}
		bool flag = false;
		if (sender > 0 && (photonEvent.Code == 204 || photonEvent.Code == 209 || photonEvent.Code == 210 || photonEvent.Code == 212))
		{
			if (!_eventRateCounts.ContainsKey(sender))
			{
				_eventRateCounts[sender] = new Dictionary<int, int>();
				_eventRateTimestamps[sender] = DateTime.Now;
			}
			if ((DateTime.Now - _eventRateTimestamps[sender]).TotalSeconds >= 1.0)
			{
				_eventRateCounts[sender].Clear();
				_eventRateTimestamps[sender] = DateTime.Now;
			}
			if (!_eventRateCounts[sender].ContainsKey(photonEvent.Code))
			{
				_eventRateCounts[sender][photonEvent.Code] = 0;
			}
			_eventRateCounts[sender][photonEvent.Code]++;
			if (_eventRateCounts[sender][photonEvent.Code] >= 10)
			{
				flag = true;
				AntiCheatPlugin.Logger.LogWarning((object)$"[SUSPICIOUS RATE] Actor #{sender} sent {_eventRateCounts[sender][photonEvent.Code]} events (code {photonEvent.Code}) in 1 second!");
			}
		}
		if (PhotonNetwork.IsMasterClient && flag)
		{
			switch (photonEvent.Code)
			{
			case 204:
				AntiCheatPlugin.Logger.LogWarning((object)$"[HIGH RATE DESTROY EVENT] From actor #{sender}");
				break;
			case 209:
				AntiCheatPlugin.Logger.LogWarning((object)$"[HIGH RATE OWNERSHIP REQUEST] From actor #{sender}");
				break;
			case 210:
				AntiCheatPlugin.Logger.LogWarning((object)$"[HIGH RATE OWNERSHIP TRANSFER] From actor #{sender}");
				break;
			case 212:
				AntiCheatPlugin.Logger.LogWarning((object)$"[HIGH RATE OWNERSHIP UPDATE] From actor #{sender}");
				break;
			}
		}
		if (photonEvent.Code == 210)
		{
			int[] array = (int[])photonEvent.CustomData;
			if (array != null && array.Length >= 2)
			{
				int num = array[0];
				int num2 = array[1];
				if (AntiCheatPlugin.IsBlocked(sender))
				{
					AntiCheatPlugin.Logger.LogWarning((object)$"[OWNERSHIP BLOCKED] Blocked player (Actor #{sender}) tried to transfer ownership of view {num}");
					return false;
				}
				if (_ownershipRequestCount.ContainsKey(sender))
				{
					if (_lastOwnershipRequest.ContainsKey(sender) && (DateTime.Now - _lastOwnershipRequest[sender]).TotalSeconds < 1.0)
					{
						_ownershipRequestCount[sender]++;
						if (_ownershipRequestCount[sender] > 10)
						{
							Room currentRoom = PhotonNetwork.CurrentRoom;
							Player val = ((currentRoom != null) ? currentRoom.GetPlayer(sender, false) : null);
							if (val != null && !val.IsLocal)
							{
								AntiCheatPlugin.Logger.LogWarning((object)$"[MASS OWNERSHIP DETECTED] {val.NickName} attempted {_ownershipRequestCount[sender]} ownership transfers in 1 second!");
								if (PhotonNetwork.IsMasterClient)
								{
									AntiCheatPlugin.LogVisually("{userColor}" + val.NickName + "</color> {leftColor}attempted mass ownership theft!</color>", onlySendOnce: false, sfxJoin: false, sfxLeave: true);
									AntiCheatPlugin.BlockPlayer(val, "Mass ownership theft attempt");
								}
								return false;
							}
						}
					}
					else
					{
						_ownershipRequestCount[sender] = 1;
					}
				}
				else
				{
					_ownershipRequestCount[sender] = 1;
				}
				_lastOwnershipRequest[sender] = DateTime.Now;
				PhotonView val2 = PhotonView.Find(num);
				if ((Object)(object)val2 != (Object)null && val2.Owner != null && val2.Owner.IsLocal && num2 != PhotonNetwork.LocalPlayer.ActorNumber)
				{
					Room currentRoom2 = PhotonNetwork.CurrentRoom;
					Player val3 = ((currentRoom2 != null) ? currentRoom2.GetPlayer(sender, false) : null);
					if (val3 != null && !val3.IsMasterClient)
					{
						AntiCheatPlugin.Logger.LogWarning((object)$"[OWNERSHIP THEFT BLOCKED] {val3.NickName} tried to steal ownership of your view {num}!");
						if (PhotonNetwork.IsMasterClient)
						{
							AntiCheatPlugin.LogVisually("{userColor}" + val3.NickName + "</color> {leftColor}tried to steal your character!</color>", onlySendOnce: false, sfxJoin: false, sfxLeave: true);
							AntiCheatPlugin.BlockPlayer(val3, "Attempted ownership theft");
						}
						return false;
					}
				}
				if (photonEvent.Code == 204)
				{
					object customData = photonEvent.CustomData;
					Hashtable val4 = (Hashtable)((customData is Hashtable) ? customData : null);
					if (val4 != null && val4.ContainsKey((byte)0))
					{
						int num3 = (int)val4[(byte)0];
						PhotonView val5 = PhotonView.Find(num3);
						if ((Object)(object)val5 != (Object)null && val5.IsMine && sender != PhotonNetwork.LocalPlayer.ActorNumber)
						{
							Room currentRoom3 = PhotonNetwork.CurrentRoom;
							Player val6 = ((currentRoom3 != null) ? currentRoom3.GetPlayer(sender, false) : null);
							AntiCheatPlugin.Logger.LogError((object)$"[DESTROY BLOCKED] {((val6 != null) ? val6.NickName : null) ?? $"Actor {sender}"} tried to destroy your object (ViewID: {num3})!");
							if ((Object)(object)((Component)val5).GetComponent<Character>() != (Object)null)
							{
								AntiCheatPlugin.Logger.LogError((object)"[CHARACTER DESTROY BLOCKED] They tried to destroy YOUR CHARACTER!");
								if (PhotonNetwork.IsMasterClient && val6 != null)
								{
									AntiCheatPlugin.LogVisually("{userColor}" + val6.NickName + "</color> {leftColor}tried to destroy your character!</color>", onlySendOnce: false, sfxJoin: false, sfxLeave: true);
									AntiCheatPlugin.BlockPlayer(val6, "Attempted to destroy your character");
								}
							}
							return false;
						}
					}
				}
				return true;
			}
		}
		return true;
	}

	[HarmonyPatch(typeof(PhotonView), "TransferOwnership", new Type[] { typeof(Player) })]
	[HarmonyPrefix]
	public static bool PreTransferOwnership(PhotonView __instance, Player newOwner)
	{
		if ((Object)(object)((Component)__instance).GetComponent<Character>() != (Object)null)
		{
			Player owner = __instance.Owner;
			if (owner != null && owner.ActorNumber != PhotonNetwork.LocalPlayer.ActorNumber && newOwner.ActorNumber == PhotonNetwork.LocalPlayer.ActorNumber)
			{
				AntiCheatPlugin.Logger.LogError((object)("[BLOCKED] Attempted to steal character ownership from " + owner.NickName + "!"));
				return false;
			}
		}
		return true;
	}

	[HarmonyPatch(typeof(PhotonView), "RequestOwnership")]
	[HarmonyPrefix]
	public static bool PreRequestOwnership(PhotonView __instance)
	{
		if ((Object)(object)((Component)__instance).GetComponent<Character>() != (Object)null && !__instance.IsMine && !PhotonNetwork.IsMasterClient)
		{
			ManualLogSource logger = AntiCheatPlugin.Logger;
			Player owner = __instance.Owner;
			logger.LogError((object)("[BLOCKED] Attempted to request ownership of character owned by " + ((owner != null) ? owner.NickName : null) + "!"));
			return false;
		}
		return true;
	}

	[HarmonyPatch(typeof(PhotonNetwork), "Destroy", new Type[] { typeof(PhotonView) })]
	[HarmonyPrefix]
	public static bool PrePhotonDestroy(PhotonView targetView)
	{
		if ((Object)(object)targetView == (Object)null)
		{
			return true;
		}
		if ((Object)(object)((Component)targetView).GetComponent<Character>() != (Object)null && !targetView.IsMine && !PhotonNetwork.LocalPlayer.IsMasterClient)
		{
			ManualLogSource logger = AntiCheatPlugin.Logger;
			Player owner = targetView.Owner;
			logger.LogError((object)("[BLOCKED] Attempted to destroy character owned by " + ((owner != null) ? owner.NickName : null) + "!"));
			return false;
		}
		return true;
	}

	[HarmonyPatch(/*Could not decode attribute arguments.*/)]
	[HarmonyPrefix]
	public static bool PreOwnerActorNrSetter(PhotonView __instance, int value)
	{
		if (AntiCheatPlugin.IsInSpawnGracePeriod(value))
		{
			AntiCheatPlugin.Logger.LogInfo((object)$"[SPAWN GRACE] Allowing ownership change to actor #{value} during spawn period");
			return true;
		}
		if (AntiCheatPlugin.IsBlocked(value))
		{
			AntiCheatPlugin.Logger.LogWarning((object)$"[BLOCKED] Blocked player (actor #{value}) tried to take ownership of view {__instance.ViewID}");
			return false;
		}
		if ((Object)(object)((Component)__instance).GetComponent<Character>() != (Object)null && __instance.IsMine)
		{
			Character component = ((Component)__instance).GetComponent<Character>();
			if (__instance.CreatorActorNr == 0 || __instance.Owner == null || ((Object)(object)component != (Object)null && !((Behaviour)component).isActiveAndEnabled))
			{
				AntiCheatPlugin.Logger.LogInfo((object)$"[SPAWN] Allowing ownership change for uninitialized character to actor #{value}");
				return true;
			}
			if (value != PhotonNetwork.LocalPlayer.ActorNumber)
			{
				Room currentRoom = PhotonNetwork.CurrentRoom;
				Player val = ((currentRoom != null) ? currentRoom.GetPlayer(value, false) : null);
				AntiCheatPlugin.Logger.LogError((object)("[CHARACTER THEFT BLOCKED] " + (((val != null) ? val.NickName : null) ?? $"Actor {value}") + " tried to steal your character!"));
				if (PhotonNetwork.IsMasterClient && val != null)
				{
					AntiCheatPlugin.LogVisually("{userColor}" + val.NickName + "</color> {leftColor}tried to steal your character!</color>", onlySendOnce: false, sfxJoin: false, sfxLeave: true);
					AntiCheatPlugin.BlockPlayer(val, "Character ownership theft attempt");
				}
				return false;
			}
		}
		if (__instance.Owner != null && __instance.Owner.IsLocal && value != PhotonNetwork.LocalPlayer.ActorNumber)
		{
			AntiCheatPlugin.Logger.LogInfo((object)$"[OWNERSHIP] Actor #{value} taking ownership of view {__instance.ViewID} (was ours)");
		}
		return true;
	}

	[HarmonyPatch(typeof(Campfire), "SetFireWoodCount")]
	[HarmonyPrefix]
	public static bool PreCampfireSetFireWoodCount(Campfire __instance, int count, PhotonMessageInfo info)
	{
		//IL_0043: Unknown result type (might be due to invalid IL or missing references)
		//IL_0019: Unknown result type (might be due to invalid IL or missing references)
		//IL_004b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0066: Unknown result type (might be due to invalid IL or missing references)
		//IL_006c: Invalid comparison between Unknown and I4
		//IL_0085: Unknown result type (might be due to invalid IL or missing references)
		//IL_018c: Unknown result type (might be due to invalid IL or missing references)
		//IL_01f7: Unknown result type (might be due to invalid IL or missing references)
		//IL_0205: Unknown result type (might be due to invalid IL or missing references)
		//IL_0222: Unknown result type (might be due to invalid IL or missing references)
		//IL_023d: Unknown result type (might be due to invalid IL or missing references)
		//IL_025b: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f0: Unknown result type (might be due to invalid IL or missing references)
		//IL_01c2: Unknown result type (might be due to invalid IL or missing references)
		//IL_0155: Unknown result type (might be due to invalid IL or missing references)
		if (AntiCheatPlugin.VerboseRPCLogging.Value)
		{
			ManualLogSource logger = AntiCheatPlugin.Logger;
			Player sender = info.Sender;
			logger.LogInfo((object)$"Campfire.SetFireWoodCount called by {((sender != null) ? sender.NickName : null)} with count: {count}");
		}
		PhotonView component = ((Component)__instance).GetComponent<PhotonView>();
		if (info.Sender == null || info.Sender.IsMasterClient)
		{
			return true;
		}
		if ((int)__instance.state == 2)
		{
			return true;
		}
		if ((Object)(object)component != (Object)null && info.Sender.ActorNumber == component.Owner.ActorNumber)
		{
			return true;
		}
		Character[] array = Object.FindObjectsOfType<Character>();
		Character[] array2 = array;
		foreach (Character val in array2)
		{
			PhotonView component2 = ((Component)val).GetComponent<PhotonView>();
			if ((Object)(object)component2 != (Object)null && component2.Owner != null && component2.Owner.ActorNumber == info.Sender.ActorNumber)
			{
				if ((Object)(object)val.data.currentItem != (Object)null && val.data.currentItem.cooking.canBeCooked)
				{
					if (AntiCheatPlugin.VerboseRPCLogging.Value)
					{
						AntiCheatPlugin.Logger.LogInfo((object)("[CAMPFIRE ALLOWED] " + info.Sender.NickName + " is holding a cookable item"));
					}
					return true;
				}
				break;
			}
		}
		if (AntiCheatPlugin.PlayerHadCookableItem(info.Sender.ActorNumber))
		{
			if (AntiCheatPlugin.VerboseRPCLogging.Value)
			{
				AntiCheatPlugin.Logger.LogInfo((object)("[CAMPFIRE ALLOWED] " + info.Sender.NickName + " recently had a cookable item"));
			}
			return true;
		}
		AntiCheatPlugin.Logger.LogWarning((object)$"{info.Sender.NickName} (#{info.Sender.ActorNumber}) tried to set the log count to {count} for the {__instance.advanceToSegment} campfire without a cookable item!");
		AntiCheatPlugin.LogVisually("{userColor}" + info.Sender.NickName + "</color> {leftColor}attempted to modify campfire logs without cookable item!</color>", onlySendOnce: false, sfxJoin: false, sfxLeave: true);
		AntiCheatPlugin.BlockPlayer(info.Sender, "Campfire log manipulation - no cookable item");
		if (PhotonNetwork.IsMasterClient)
		{
			__instance.FireWoodCount = 3;
		}
		return false;
	}

	[HarmonyPatch(typeof(Campfire), "Extinguish_Rpc")]
	[HarmonyPrefix]
	public static bool PreCampfireExtinguish_Rpc(Campfire __instance, PhotonMessageInfo info)
	{
		//IL_0001: Unknown result type (might be due to invalid IL or missing references)
		//IL_0009: Unknown result type (might be due to invalid IL or missing references)
		//IL_0060: Unknown result type (might be due to invalid IL or missing references)
		//IL_003c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0071: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a5: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b0: 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_00db: 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_00ff: Unknown result type (might be due to invalid IL or missing references)
		if (info.Sender == null || info.Sender.IsMasterClient)
		{
			return true;
		}
		if (AntiCheatPlugin.VerboseRPCLogging.Value)
		{
			ManualLogSource logger = AntiCheatPlugin.Logger;
			Player sender = info.Sender;
			logger.LogInfo((object)("Campfire.Extinguish_Rpc called by " + ((sender != null) ? sender.NickName : null)));
		}
		PhotonView component = ((Component)__instance).GetComponent<PhotonView>();
		bool flag = info.Sender == null || ((Object)(object)component != (Object)null && info.Sender.ActorNumber == component.Owner.ActorNumber);
		if (!flag)
		{
			AntiCheatPlugin.Logger.LogWarning((object)$"{info.Sender.NickName} (#{info.Sender.ActorNumber}) tried to extinguish the {__instance.advanceToSegment} campfire!");
			AntiCheatPlugin.LogVisually($"{{userColor}}{info.Sender.NickName}</color> {{leftColor}}attempted to extinguish the {__instance.advanceToSegment} campfire!</color>", onlySendOnce: false, sfxJoin: false, sfxLeave: true);
			AntiCheatPlugin.BlockPlayer(info.Sender, "Unauthorized campfire extinguish");
			return false;
		}
		return flag;
	}

	[HarmonyPatch(typeof(Campfire), "Light_Rpc")]
	[HarmonyPrefix]
	public static bool PreCampfireLight_Rpc(Campfire __instance, PhotonMessageInfo info)
	{
		//IL_0036: Unknown result type (might be due to invalid IL or missing references)
		//IL_0019: Unknown result type (might be due to invalid IL or missing references)
		//IL_003e: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b0: Unknown result type (might be due to invalid IL or missing references)
		//IL_00bc: Unknown result type (might be due to invalid IL or missing references)
		//IL_0083: Unknown result type (might be due to invalid IL or missing references)
		//IL_0109: Unknown result type (might be due to invalid IL or missing references)
		//IL_0115: Unknown result type (might be due to invalid IL or missing references)
		if (AntiCheatPlugin.VerboseRPCLogging.Value)
		{
			ManualLogSource logger = AntiCheatPlugin.Logger;
			Player sender = info.Sender;
			logger.LogInfo((object)("Campfire.Light_Rpc called by " + ((sender != null) ? sender.NickName : null)));
		}
		if (info.Sender == null || info.Sender.IsMasterClient)
		{
			return true;
		}
		string text = default(string);
		if (__instance.EveryoneInRange(ref text))
		{
			if (AntiCheatPlugin.VerboseRPCLogging.Value)
			{
				AntiCheatPlugin.Logger.LogInfo((object)("[LIGHT CAMPFIRE ALLOWED] " + info.Sender.NickName + " lit campfire - everyone in range"));
			}
			return true;
		}
		AntiCheatPlugin.Logger.LogWarning((object)$"[LIGHT CAMPFIRE DETECTED] {info.Sender.NickName} attempted to light {__instance.advanceToSegment} campfire with players out of range!");
		if (!string.IsNullOrEmpty(text))
		{
			AntiCheatPlugin.Logger.LogWarning((object)("[LIGHT CAMPFIRE] Out of range players: " + text));
		}
		if (PhotonNetwork.IsMasterClient)
		{
			AntiCheatPlugin.LogVisually($"{{userColor}}{info.Sender.NickName}</color> {{leftColor}}tried to light {__instance.advanceToSegment} campfire with players out of range!</color>", onlySendOnce: false, sfxJoin: false, sfxLeave: true);
		}
		return false;
	}

	[HarmonyPatch(typeof(PhotonNetwork), "RaiseEventInternal")]
	[HarmonyPrefix]
	internal static bool PreRaiseEventInternal(byte eventCode, object eventContent, RaiseEventOptions raiseEventOptions, SendOptions sendOptions)
	{
		Player localPlayer = PhotonNetwork.LocalPlayer;
		if (localPlayer != null && AntiCheatPlugin.IsBlocked(localPlayer.ActorNumber))
		{
			switch (eventCode)
			{
			case 200:
			case 202:
			case 204:
			case 207:
			case 209:
			case 210:
			case 212:
				return false;
			}
		}
		if (eventCode == 204)
		{
			Hashtable val = (Hashtable)((eventContent is Hashtable) ? eventContent : null);
			if (val != null && val.ContainsKey((byte)0))
			{
				int num = (int)val[(byte)0];
				PhotonView val2 = PhotonView.Find(num);
				if ((Object)(object)val2 != (Object)null && val2.Owner != null && localPlayer != null && val2.Owner.ActorNumber != localPlayer.ActorNumber && !localPlayer.IsMasterClient)
				{
					AntiCheatPlugin.Logger.LogWarning((object)$"[DESTROY BLOCKED] {localPlayer.NickName} tried to destroy view {num} owned by {val2.Owner.NickName}");
					return false;
				}
			}
		}
		return true;
	}

	[HarmonyPatch(typeof(PhotonNetwork), "RemoveInstantiatedGO")]
	[HarmonyPrefix]
	internal static bool PreRemoveInstantiatedGO(GameObject go, bool localOnly)
	{
		if ((Object)(object)go == (Object)null)
		{
			return true;
		}
		PhotonView component = go.GetComponent<PhotonView>();
		if ((Object)(object)component != (Object)null && component.Owner != null)
		{
			Player localPlayer = PhotonNetwork.LocalPlayer;
			if (localPlayer != null && AntiCheatPlugin.IsBlocked(localPlayer.ActorNumber))
			{
				if (component.Owner.ActorNumber == localPlayer.ActorNumber)
				{
					return true;
				}
				AntiCheatPlugin.Logger.LogWarning((object)("[DESTROY BLOCKED] Blocked player tried to remove " + ((Object)go).name + " owned by " + component.Owner.NickName));
				return false;
			}
		}
		return true;
	}

	[HarmonyPatch(typeof(Character), "RPCA_ReviveAtPosition")]
	[HarmonyPrefix]
	public static bool PreCharacterRPCA_ReviveAtPosition(Character __instance, PhotonMessageInfo info)
	{
		//IL_0019: 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_008a: 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_00fa: Unknown result type (might be due to invalid IL or missing references)
		//IL_014a: Unknown result type (might be due to invalid IL or missing references)
		//IL_01de: Unknown result type (might be due to invalid IL or missing references)
		//IL_01ab: Unknown result type (might be due to invalid IL or missing references)
		//IL_023d: Unknown result type (might be due to invalid IL or missing references)
		//IL_020a: Unknown result type (might be due to invalid IL or missing references)
		//IL_025a: Unknown result type (might be due to invalid IL or missing references)
		//IL_02cf: Unknown result type (might be due to invalid IL or missing references)
		//IL_02dd: Unknown result type (might be due to invalid IL or missing references)
		//IL_0294: Unknown result type (might be due to invalid IL or missing references)
		//IL_0344: Unknown result type (might be due to invalid IL or missing references)
		//IL_0372: Unknown result type (might be due to invalid IL or missing references)
		if (AntiCheatPlugin.VerboseRPCLogging.Value)
		{
			ManualLogSource logger = AntiCheatPlugin.Logger;
			Player sender = info.Sender;
			string obj = ((sender != null) ? sender.NickName : null);
			PhotonView component = ((Component)__instance).GetComponent<PhotonView>();
			object obj2;
			if (component == null)
			{
				obj2 = null;
			}
			else
			{
				Player owner = component.Owner;
				obj2 = ((owner != null) ? owner.NickName : null);
			}
			logger.LogInfo((object)("Character.RPCA_ReviveAtPosition called by " + obj + " on " + (string?)obj2));
		}
		PhotonView component2 = ((Component)__instance).GetComponent<PhotonView>();
		object obj3;
		if (component2 == null)
		{
			obj3 = null;
		}
		else
		{
			Player owner2 = component2.Owner;
			obj3 = ((owner2 != null) ? owner2.NickName : null);
		}
		if (obj3 == null)
		{
			obj3 = "Unknown";
		}
		string text = (string)obj3;
		if (info.Sender == null || info.Sender.IsMasterClient)
		{
			return true;
		}
		if ((Object)(object)component2 != (Object)null && component2.Owner != null)
		{
			AntiCheatPlugin.Logger.LogInfo((object)$"[REVIVE DEBUG] Target: {text} (Actor #{component2.Owner.ActorNumber}), Sender: {info.Sender.NickName} (Actor #{info.Sender.ActorNumber})");
			AntiCheatPlugin.Logger.LogInfo((object)$"[REVIVE DEBUG] Is target in grace period? {AntiCheatPlugin.IsInSpawnGracePeriod(component2.Owner.ActorNumber)}");
			AntiCheatPlugin.Logger.LogInfo((object)$"[REVIVE DEBUG] Is sender in grace period? {AntiCheatPlugin.IsInSpawnGracePeriod(info.Sender.ActorNumber)}");
		}
		if ((Object)(object)component2 != (Object)null && component2.Owner != null && AntiCheatPlugin.IsInSpawnGracePeriod(component2.Owner.ActorNumber))
		{
			AntiCheatPlugin.Logger.LogInfo((object)("[SPAWN TELEPORT ALLOWED] " + info.Sender.NickName + " teleported " + text + " who is in spawn grace period."));
			return true;
		}
		if (AntiCheatPlugin.IsInSpawnGracePeriod(info.Sender.ActorNumber))
		{
			AntiCheatPlugin.Logger.LogInfo((object)("[SPAWN TELEPORT ALLOWED] " + info.Sender.NickName + " (in spawn grace period) teleported " + text + " who is in spawn grace period."));
			return true;
		}
		if (AntiCheatPlugin.PlayerHadItem(info.Sender.ActorNumber, "scout") && AntiCheatPlugin.PlayerHadItem(info.Sender.ActorNumber, "effigy"))
		{
			if (AntiCheatPlugin.VerboseRPCLogging.Value)
			{
				AntiCheatPlugin.Logger.LogInfo((object)(info.Sender.NickName + " used Scout Effigy to revive " + text + " - legitimate"));
			}
			return true;
		}
		ManualLogSource logger2 = AntiCheatPlugin.Logger;
		object[] obj4 = new object[4]
		{
			info.Sender.NickName,
			info.Sender.ActorNumber,
			text,
			null
		};
		int? obj5;
		if (component2 == null)
		{
			obj5 = null;
		}
		else
		{
			Player owner3 = component2.Owner;
			obj5 = ((owner3 != null) ? new int?(owner3.ActorNumber) : null);
		}
		obj4[3] = obj5;
		logger2.LogWarning((object)string.Format("{0} (#{1}) attempted to revive {2} (#{3}) without permission!", obj4));
		AntiCheatPlugin.LogVisually("{userColor}" + info.Sender.NickName + "</color> {leftColor}tried to revive</color> {userColor}" + text + "</color> {leftColor}without permission!</color>", onlySendOnce: false, sfxJoin: false, sfxLeave: true);
		AntiCheatPlugin.BlockPlayer(info.Sender, "Unauthorized revive of " + text);
		return false;
	}

	[HarmonyPatch(typeof(Character), "WarpPlayerRPC")]
	[HarmonyPrefix]
	public static bool PreWarpPlayerRPC(Character __instance, Vector3 position, bool poof, PhotonMessageInfo info)
	{
		//IL_002a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0032: Unknown result type (might be due to invalid IL or missing references)
		//IL_012e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0094: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a2: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f2: Unknown result type (might be due to invalid IL or missing references)
		//IL_011c: Unknown result type (might be due to invalid IL or missing references)
		//IL_013b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0148: Unknown result type (might be due to invalid IL or missing references)
		//IL_019e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0155: Unknown result type (might be due to invalid IL or missing references)
		//IL_0258: Unknown result type (might be due to invalid IL or missing references)
		//IL_0162: Unknown result type (might be due to invalid IL or missing references)
		//IL_016f: Unknown result type (might be due to invalid IL or missing references)
		//IL_02d1: Unknown result type (might be due to invalid IL or missing references)
		//IL_02ac: Unknown result type (might be due to invalid IL or missing references)
		//IL_02b8: Unknown result type (might be due to invalid IL or missing references)
		//IL_0317: Unknown result type (might be due to invalid IL or missing references)
		//IL_02f2: Unknown result type (might be due to invalid IL or missing references)
		//IL_02fe: Unknown result type (might be due to invalid IL or missing references)
		//IL_0228: Unknown result type (might be due to invalid IL or missing references)
		//IL_01f6: Unknown result type (might be due to invalid IL or missing references)
		//IL_0334: Unknown result type (might be due to invalid IL or missing references)
		//IL_039d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0363: Unknown result type (might be due to invalid IL or missing references)
		//IL_036f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0413: Unknown result type (might be due to invalid IL or missing references)
		//IL_03e4: Unknown result type (might be due to invalid IL or missing references)
		PhotonView component = ((Component)__instance).GetComponent<PhotonView>();
		object obj;
		if (component == null)
		{
			obj = null;
		}
		else
		{
			Player owner = component.Owner;
			obj = ((owner != null) ? owner.NickName : null);
		}
		if (obj == null)
		{
			obj = "Unknown";
		}
		string text = (string)obj;
		if (info.Sender == null || info.Sender.IsMasterClient)
		{
			return true;
		}
		if ((Object)(object)component != (Object)null && component.Owner != null)
		{
			AntiCheatPlugin.Logger.LogInfo((object)$"[WARP DEBUG] Target: {text} (Actor #{component.Owner.ActorNumber}), Sender: {info.Sender.NickName} (Actor #{info.Sender.ActorNumber})");
			AntiCheatPlugin.Logger.LogInfo((object)$"[WARP DEBUG] Is target in grace period? {AntiCheatPlugin.IsInSpawnGracePeriod(component.Owner.ActorNumber)}");
			AntiCheatPlugin.Logger.LogInfo((object)$"[WARP DEBUG] Is sender in grace period? {AntiCheatPlugin.IsInSpawnGracePeriod(info.Sender.ActorNumber)}");
			AntiCheatPlugin.Logger.LogInfo((object)$"[WARP DEBUG] Position: {position}");
		}
		if (float.IsInfinity(position.x) || float.IsInfinity(position.y) || float.IsInfinity(position.z) || float.IsNegativeInfinity(position.x) || float.IsNegativeInfinity(position.y) || float.IsNegativeInfinity(position.z))
		{
			AntiCheatPlugin.Logger.LogError((object)("[BLACK SCREEN BLOCKED] " + info.Sender.NickName + " tried to warp " + text + " to infinity!"));
			if (PhotonNetwork.IsMasterClient)
			{
				if ((Object)(object)component != (Object)null && component.IsMine)
				{
					AntiCheatPlugin.LogVisually("{userColor}" + info.Sender.NickName + "</color> {leftColor}tried to black screen YOU!</color>", onlySendOnce: false, sfxJoin: false, sfxLeave: true);
				}
				else
				{
					AntiCheatPlugin.LogVisually("{userColor}" + info.Sender.NickName + "</color> {leftColor}tried to black screen</color> {userColor}" + text + "</color>{leftColor}!</color>", onlySendOnce: false, sfxJoin: false, sfxLeave: true);
				}
			}
			AntiCheatPlugin.BlockPlayer(info.Sender, "Black screen attempt on " + text);
			return false;
		}
		if ((Object)(object)component != (Object)null && component.Owner != null && AntiCheatPlugin.IsInSpawnGracePeriod(component.Owner.ActorNumber))
		{
			AntiCheatPlugin.Logger.LogInfo((object)$"[SPAWN TELEPORT ALLOWED] {info.Sender.NickName} teleported {text} who is in spawn grace period to {position}");
			return true;
		}
		if (AntiCheatPlugin.IsInSpawnGracePeriod(info.Sender.ActorNumber))
		{
			AntiCheatPlugin.Logger.LogInfo((object)$"[SPAWN TELEPORT ALLOWED] {info.Sender.NickName} (in spawn grace period) teleported {text} to {position}");
			return true;
		}
		if (AntiCheatPlugin.PlayerHadItem(info.Sender.ActorNumber, "scout") && AntiCheatPlugin.PlayerHadItem(info.Sender.ActorNumber, "effigy"))
		{
			AntiCheatPlugin.Logger.LogInfo((object)$"[WARP ALLOWED] {info.Sender.NickName} used Scout Effigy to warp {text} to {position}");
			return true;
		}
		AntiCheatPlugin.Logger.LogWarning((object)("[WARP BLOCKED] " + info.Sender.NickName + " attempted to warp " + text + " without Scout Effigy!"));
		if (PhotonNetwork.IsMasterClient)
		{
			AntiCheatPlugin.LogVisually("{userColor}" + info.Sender.NickName + "</color> {leftColor}tried to warp</color> {userColor}" + text + "</color> {leftColor}without Scout Effigy!</color>", onlySendOnc