Decompiled source of HardAntiCheat v2.2.7

HardAntiCheat.dll

Decompiled 8 hours ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Cryptography;
using System.Security.Permissions;
using System.Text;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using BepInEx.Logging;
using CodeTalker.Networking;
using CodeTalker.Packets;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using Mirror;
using Newtonsoft.Json;
using Steamworks;
using UnityEngine;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("com.HardAntiCheat.sftwre")]
[assembly: AssemblyConfiguration("Debug")]
[assembly: AssemblyFileVersion("2.2.7.0")]
[assembly: AssemblyInformationalVersion("2.2.7+d4b044556ebdcea5721c39ffb7f0fb3f6b74d888")]
[assembly: AssemblyProduct("HardAntiCheat")]
[assembly: AssemblyTitle("HardAntiCheat")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("2.2.7.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableAttribute : Attribute
	{
		public readonly byte[] NullableFlags;

		public NullableAttribute(byte P_0)
		{
			NullableFlags = new byte[1] { P_0 };
		}

		public NullableAttribute(byte[] P_0)
		{
			NullableFlags = P_0;
		}
	}
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableContextAttribute : Attribute
	{
		public readonly byte Flag;

		public NullableContextAttribute(byte P_0)
		{
			Flag = P_0;
		}
	}
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace HardAntiCheat
{
	public class HAC_HandshakeRequest : PacketBase
	{
		[JsonProperty]
		public ulong TargetSteamID;

		[JsonProperty]
		public string ChallengeToken;

		[JsonProperty]
		public int ChallengeType;

		public override string PacketSourceGUID => "HardAntiCheat";
	}
	public class HAC_HandshakeResponse : PacketBase
	{
		[JsonProperty]
		public string ChallengeHash;

		[JsonProperty]
		public Dictionary<string, string> ModListings;

		public override string PacketSourceGUID => "HardAntiCheat";
	}
	public class HAC_HeartbeatRequest : PacketBase
	{
		[JsonProperty]
		public ulong TargetSteamID;

		[JsonProperty]
		public string ChallengeToken;

		public override string PacketSourceGUID => "HardAntiCheat";
	}
	public class HAC_HeartbeatResponse : PacketBase
	{
		[JsonProperty]
		public string ChallengeHash;

		public override string PacketSourceGUID => "HardAntiCheat";
	}
	public struct PlayerPositionData
	{
		public Vector3 Position;

		public float Timestamp;
	}
	public struct PlayerStatsData
	{
		public int Level;

		public int Experience;
	}
	public struct PlayerAirborneData
	{
		public float AirTime;

		public Vector3 LastGroundedPosition;

		public int ServerSideJumpCount;

		public float LastVerticalPosition;

		public float VerticalStallTime;
	}
	public struct PlayerMovementStats
	{
		public List<float> RecentSpeeds;

		public float TimeAtMaxSpeed;
	}
	public static class HACIntegrity
	{
		public static string GenerateClientCompositeHash(string token, Dictionary<string, string> modListings)
		{
			if (string.IsNullOrEmpty(token))
			{
				return string.Empty;
			}
			try
			{
				using SHA256 sHA = SHA256.Create();
				using MemoryStream memoryStream = new MemoryStream();
				byte[] array = File.ReadAllBytes(Assembly.GetExecutingAssembly().Location);
				memoryStream.Write(array, 0, array.Length);
				string bepInExRootPath = Paths.BepInExRootPath;
				string[] array2 = new string[3]
				{
					Path.Combine(bepInExRootPath, "core", "BepInEx.dll"),
					Path.Combine(bepInExRootPath, "core", "0Harmony.dll"),
					Path.Combine(Paths.ManagedPath, "Assembly-CSharp.dll")
				};
				string[] array3 = array2;
				foreach (string path in array3)
				{
					if (File.Exists(path))
					{
						byte[] array4 = File.ReadAllBytes(path);
						memoryStream.Write(array4, 0, array4.Length);
					}
				}
				if (modListings != null)
				{
					IEnumerable<string> values = from kvp in modListings
						orderby kvp.Key
						select kvp.Key + ":" + kvp.Value;
					string s = string.Join(",", values);
					byte[] bytes = Encoding.UTF8.GetBytes(s);
					memoryStream.Write(bytes, 0, bytes.Length);
				}
				byte[] bytes2 = Encoding.UTF8.GetBytes(token);
				memoryStream.Write(bytes2, 0, bytes2.Length);
				memoryStream.Position = 0L;
				return Convert.ToBase64String(sHA.ComputeHash(memoryStream));
			}
			catch (Exception ex)
			{
				Main.Log.LogError((object)("Hash generation failed: " + ex.Message));
				return "HASH_GENERATION_FAILED";
			}
		}
	}
	[BepInPlugin("com.HardAntiCheat.sftwre", "HardAntiCheat", "2.2.7")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	public class Main : BaseUnityPlugin
	{
		[CompilerGenerated]
		private static class <>O
		{
			public static PacketListener <0>__OnClientReceivedHandshakeRequest;

			public static PacketListener <1>__OnServerReceivedHandshakeResponse;

			public static PacketListener <2>__OnClientReceivedHeartbeatRequest;

			public static PacketListener <3>__OnServerReceivedHeartbeatResponse;
		}

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

			private object <>2__current;

			public ulong steamId;

			public Main <>4__this;

			private Player <player>5__1;

			private string <token>5__2;

			private Dictionary<string, string> <modListings>5__3;

			private string <expectedHash>5__4;

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

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

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

			[DebuggerHidden]
			void IDisposable.Dispose()
			{
				<player>5__1 = null;
				<token>5__2 = null;
				<modListings>5__3 = null;
				<expectedHash>5__4 = null;
				<>1__state = -2;
			}

			private bool MoveNext()
			{
				//IL_0039: Unknown result type (might be due to invalid IL or missing references)
				//IL_0043: Expected O, but got Unknown
				//IL_0195: Unknown result type (might be due to invalid IL or missing references)
				//IL_019f: Expected O, but got Unknown
				switch (<>1__state)
				{
				default:
					return false;
				case 0:
					<>1__state = -1;
					<>2__current = (object)new WaitForSeconds(HeartbeatInterval.Value);
					<>1__state = 1;
					return true;
				case 1:
					<>1__state = -1;
					break;
				case 2:
					<>1__state = -1;
					<player>5__1 = null;
					break;
				}
				if (VerifiedSteamIDs.Contains(steamId))
				{
					<player>5__1 = GetPlayerBySteamID(steamId);
					if ((Object)(object)<player>5__1 != (Object)null)
					{
						if (PendingHeartbeats.ContainsKey(steamId))
						{
							PunishHandshakeFailure(steamId, "Did not respond to previous heartbeat in time.");
							return false;
						}
						<token>5__2 = Guid.NewGuid().ToString();
						<modListings>5__3 = Chainloader.PluginInfos.ToDictionary((KeyValuePair<string, PluginInfo> kvp) => kvp.Key, (KeyValuePair<string, PluginInfo> kvp) => kvp.Value.Metadata.Name);
						<expectedHash>5__4 = HACIntegrity.GenerateClientCompositeHash(<token>5__2, <modListings>5__3);
						PendingHeartbeats[steamId] = <expectedHash>5__4;
						CodeTalkerNetwork.SendNetworkPacket((PacketBase)(object)new HAC_HeartbeatRequest
						{
							ChallengeToken = <token>5__2,
							TargetSteamID = steamId
						});
						<token>5__2 = null;
						<modListings>5__3 = null;
						<expectedHash>5__4 = null;
						<>2__current = (object)new WaitForSeconds(HeartbeatInterval.Value);
						<>1__state = 2;
						return true;
					}
					PendingHeartbeats.Remove(steamId);
					return false;
				}
				PendingHeartbeats.Remove(steamId);
				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 <KickClientAfterDelay>d__70 : IEnumerator<object>, IEnumerator, IDisposable
		{
			private int <>1__state;

			private object <>2__current;

			public Player player;

			public Main <>4__this;

			private ulong <steamId>5__1;

			private string <reason>5__2;

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

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

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

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

			private bool MoveNext()
			{
				//IL_005b: Unknown result type (might be due to invalid IL or missing references)
				//IL_0065: Expected O, but got Unknown
				switch (<>1__state)
				{
				default:
					return false;
				case 0:
					<>1__state = -1;
					if ((Object)(object)player == (Object)null || !ulong.TryParse(player._steamID, out <steamId>5__1))
					{
						return false;
					}
					<>2__current = (object)new WaitForSeconds(VerificationTimeout.Value);
					<>1__state = 1;
					return true;
				case 1:
					<>1__state = -1;
					if ((Object)(object)player != (Object)null && !VerifiedSteamIDs.Contains(<steamId>5__1))
					{
						<reason>5__2 = $"Disconnecting player {player._nickname} (SteamID: {<steamId>5__1}) for failing to respond to client integrity check.";
						Log.LogWarning((object)<reason>5__2);
						PunishHandshakeFailure(<steamId>5__1, <reason>5__2);
						<reason>5__2 = null;
					}
					PendingVerification.Remove(<steamId>5__1);
					return false;
				}
			}

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

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

		private readonly Harmony harmony = new Harmony("com.HardAntiCheat.sftwre");

		internal static ManualLogSource Log;

		internal static string InfractionLogPath;

		public static ConfigEntry<bool> EnableAntiCheat;

		public static ConfigEntry<bool> DisableForHost;

		public static ConfigEntry<string> TrustedSteamIDs;

		public static ConfigEntry<bool> EnableIntegrityChecks;

		public static ConfigEntry<bool> EnableHeartbeatCheck;

		public static ConfigEntry<float> HeartbeatInterval;

		public static ConfigEntry<bool> HACEnforce;

		public static ConfigEntry<string> HACListType;

		public static ConfigEntry<string> HACHandshakeFailAction;

		public static ConfigEntry<string> HACModList;

		public static ConfigEntry<float> VerificationTimeout;

		public static ConfigEntry<int> MaxLogFileSizeMB;

		public static ConfigEntry<bool> EnableMovementChecks;

		public static ConfigEntry<float> MaxEffectiveSpeed;

		public static ConfigEntry<float> MovementGraceBuffer;

		public static ConfigEntry<float> MovementTimeThreshold;

		public static ConfigEntry<float> TeleportDistanceThreshold;

		public static ConfigEntry<bool> EnableAirborneChecks;

		public static ConfigEntry<bool> EnableSpeedChecks;

		public static ConfigEntry<float> SpeedHackDetectionCooldown;

		public static ConfigEntry<float> JumpHackDetectionCooldown;

		public static ConfigEntry<float> AirborneHackDetectionCooldown;

		public static ConfigEntry<bool> EnableExperienceChecks;

		public static ConfigEntry<int> JumpThreshold;

		public static ConfigEntry<int> MaxPlausibleXPGain;

		public static ConfigEntry<int> MaxXPGainPerWindow;

		public static ConfigEntry<float> XPGainWindowSeconds;

		public static ConfigEntry<bool> EnableCooldownChecks;

		public static ConfigEntry<bool> EnableReviveChecks;

		public static ConfigEntry<bool> EnablePunishmentSystem;

		public static ConfigEntry<int> WarningsUntilAction;

		public static ConfigEntry<string> ActionType;

		public static ConfigEntry<bool> EnableDetailedLogs;

		public static ConfigEntry<bool> LogPlayerName;

		public static ConfigEntry<bool> LogPlayerID;

		public static ConfigEntry<bool> LogInfractionCount;

		public static ConfigEntry<bool> LogInfractionDetails;

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

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

		public static readonly Dictionary<uint, Dictionary<string, float>> ServerRemainingCooldowns = new Dictionary<uint, Dictionary<string, float>>();

		public static readonly Dictionary<uint, PlayerPositionData> ServerPlayerPositions = new Dictionary<uint, PlayerPositionData>();

		public static readonly Dictionary<uint, PlayerStatsData> ServerPlayerStats = new Dictionary<uint, PlayerStatsData>();

		public static readonly Dictionary<uint, List<(float Timestamp, int Amount)>> XpGainHistory = new Dictionary<uint, List<(float, int)>>();

		public static readonly Dictionary<uint, PlayerAirborneData> ServerPlayerAirborneStates = new Dictionary<uint, PlayerAirborneData>();

		public static readonly Dictionary<uint, float> ServerPlayerInitialSpeeds = new Dictionary<uint, float>();

		public static readonly Dictionary<uint, PlayerMovementStats> ServerPlayerMovementStats = new Dictionary<uint, PlayerMovementStats>();

		public static readonly Dictionary<uint, float> ServerPlayerMovementTimers = new Dictionary<uint, float>();

		public static readonly Dictionary<uint, int> ServerPlayerInfractionCount = new Dictionary<uint, int>();

		public static readonly Dictionary<uint, float> ServerPlayerGracePeriod = new Dictionary<uint, float>();

		public static readonly Dictionary<uint, float> ServerPunishmentCooldown = new Dictionary<uint, float>();

		public static readonly Dictionary<uint, float> ServerSpeedCheckCooldowns = new Dictionary<uint, float>();

		public static readonly Dictionary<uint, float> ServerJumpCheckCooldowns = new Dictionary<uint, float>();

		public static readonly Dictionary<uint, float> ServerAirborneCheckCooldowns = new Dictionary<uint, float>();

		public static readonly Dictionary<uint, float> AuthorizedSelfRevives = new Dictionary<uint, float>();

		internal static readonly Dictionary<ulong, (string ExpectedHash, Coroutine KickCoroutine)> PendingVerification = new Dictionary<ulong, (string, Coroutine)>();

		internal static readonly Dictionary<ulong, string> PendingHeartbeats = new Dictionary<ulong, string>();

		internal static readonly HashSet<ulong> VerifiedSteamIDs = new HashSet<ulong>();

		public static Main Instance { get; private set; }

		private void Awake()
		{
			//IL_01b7: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c1: Expected O, but got Unknown
			//IL_0200: Unknown result type (might be due to invalid IL or missing references)
			//IL_020a: Expected O, but got Unknown
			//IL_04f5: Unknown result type (might be due to invalid IL or missing references)
			//IL_04ff: Expected O, but got Unknown
			//IL_061b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0620: Unknown result type (might be due to invalid IL or missing references)
			//IL_0626: Expected O, but got Unknown
			//IL_063c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0641: Unknown result type (might be due to invalid IL or missing references)
			//IL_0647: Expected O, but got Unknown
			//IL_065d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0662: Unknown result type (might be due to invalid IL or missing references)
			//IL_0668: Expected O, but got Unknown
			//IL_067e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0683: Unknown result type (might be due to invalid IL or missing references)
			//IL_0689: Expected O, but got Unknown
			Instance = this;
			Log = ((BaseUnityPlugin)this).Logger;
			string fullName = Directory.GetParent(Path.GetDirectoryName(((BaseUnityPlugin)this).Info.Location)).FullName;
			string text = Path.Combine(fullName, "HardAntiCheat");
			Directory.CreateDirectory(text);
			InfractionLogPath = Path.Combine(text, "HardAntiCheat_InfractionLog.txt");
			EnableAntiCheat = ((BaseUnityPlugin)this).Config.Bind<bool>("1. General", "Enable AntiCheat", true, "Master switch to enable or disable all anti-cheat modules.");
			DisableForHost = ((BaseUnityPlugin)this).Config.Bind<bool>("1. General", "Disable Detections for Host", true, "If true, the player hosting the server will not be checked for infractions.");
			TrustedSteamIDs = ((BaseUnityPlugin)this).Config.Bind<string>("1. General", "Trusted SteamIDs", "", "A comma-separated list of 64-bit SteamIDs for users who should be exempt from all anti-cheat checks.");
			MaxLogFileSizeMB = ((BaseUnityPlugin)this).Config.Bind<int>("1. General", "Max Log File Size (MB)", 5, "If the infraction log exceeds this size, it will be archived on startup.");
			EnableIntegrityChecks = ((BaseUnityPlugin)this).Config.Bind<bool>("1. General", "Enable Client Integrity Checks", true, "If true, kicks players who fail a cryptographic challenge to prove they have the unmodified mod installed.");
			VerificationTimeout = ((BaseUnityPlugin)this).Config.Bind<float>("1. General", "Verification Timeout", 25f, "How many seconds the server will wait for a client to verify before kicking them.");
			EnableHeartbeatCheck = ((BaseUnityPlugin)this).Config.Bind<bool>("1. General", "Enable Heartbeat Re-Verification", true, "Periodically re-challenges connected clients to ensure they remain unmodified.");
			HeartbeatInterval = ((BaseUnityPlugin)this).Config.Bind<float>("1. General", "Heartbeat Interval (Seconds)", 45f, "How often to send a heartbeat check to clients. Higher is less intrusive, lower is more secure.");
			HACEnforce = ((BaseUnityPlugin)this).Config.Bind<bool>("1. General", "Enable Mod List Enforcement", false, "If true, the server will check connecting clients' mod lists against the rules below.");
			HACListType = ((BaseUnityPlugin)this).Config.Bind<string>("1. General", "Mod List Type", "blacklist", new ConfigDescription("Determines how the mod list is used.", (AcceptableValueBase)(object)new AcceptableValueList<string>(new string[2] { "blacklist", "whitelist" }), Array.Empty<object>()));
			HACHandshakeFailAction = ((BaseUnityPlugin)this).Config.Bind<string>("1. General", "Handshake Fail Action", "kick", new ConfigDescription("The action to take if a client fails the integrity check or mod list check.", (AcceptableValueBase)(object)new AcceptableValueList<string>(new string[2] { "kick", "ban" }), Array.Empty<object>()));
			HACModList = ((BaseUnityPlugin)this).Config.Bind<string>("1. General", "Mod List (GUIDs or Names)", "some.banned.mod.guid,Another Banned Mod Name", "Comma-separated list of BepInEx plugin GUIDs or Names to use for the blacklist/whitelist.");
			EnableMovementChecks = ((BaseUnityPlugin)this).Config.Bind<bool>("2. Movement Detections", "Enable Teleport/Distance Checks", true, "Checks the final result of player movement to catch physics-based speed hacks and teleports.");
			MaxEffectiveSpeed = ((BaseUnityPlugin)this).Config.Bind<float>("2. Movement Detections", "Max Effective Speed", 100f, "The maximum plausible speed (units per second) a player can move.");
			MovementGraceBuffer = ((BaseUnityPlugin)this).Config.Bind<float>("2. Movement Detections", "Movement Grace Buffer", 10f, "A flat distance buffer added to the calculation to account for dashes and small lag spikes.");
			MovementTimeThreshold = ((BaseUnityPlugin)this).Config.Bind<float>("2. Movement Detections", "Movement Time Threshold", 5.5f, "The time (in seconds) between position checks. Higher values are more lenient on lag but less precise.");
			TeleportDistanceThreshold = ((BaseUnityPlugin)this).Config.Bind<float>("2. Movement Detections", "Teleport Distance Threshold", 50f, "Any movement faster than plausible that also covers more than this distance is logged as a 'Teleport' instead of a 'Speed Hack'.");
			EnableAirborneChecks = ((BaseUnityPlugin)this).Config.Bind<bool>("2. Movement Detections", "Enable Fly/Infinite Jump Checks", true, "Checks if players are airborne for an impossibly long time and have an invalid number of max jumps.");
			EnableSpeedChecks = ((BaseUnityPlugin)this).Config.Bind<bool>("2. Movement Detections", "Enable Base Speed Stat Audits", true, "Continuously checks if a player's base movement speed stat has been illegally modified and reverts it.");
			JumpThreshold = ((BaseUnityPlugin)this).Config.Bind<int>("2. Movement Detections", "Jump threshold", 8, "The maximum number of jumps a player is allowed to perform before returning to the ground.");
			SpeedHackDetectionCooldown = ((BaseUnityPlugin)this).Config.Bind<float>("2. Movement Detections", "Speed Hack Detection Cooldown", 2f, "How long (in seconds) the anti-cheat will wait before logging another speed stat infraction for the same player.");
			JumpHackDetectionCooldown = ((BaseUnityPlugin)this).Config.Bind<float>("2. Movement Detections", "Jump Hack Detection Cooldown", 2f, "How long (in seconds) the anti-cheat will wait before logging another jump stat infraction for the same player.");
			AirborneHackDetectionCooldown = ((BaseUnityPlugin)this).Config.Bind<float>("2. Movement Detections", "Airborne Hack Detection Cooldown", 10f, "How long (in seconds) the anti-cheat will wait before logging another airborne infraction for the same player.");
			EnableExperienceChecks = ((BaseUnityPlugin)this).Config.Bind<bool>("3. Stat Detections", "Enable Experience/Level Checks", true, "Prevents players from gaining huge amounts of XP or multiple levels at once.");
			MaxPlausibleXPGain = ((BaseUnityPlugin)this).Config.Bind<int>("3. Stat Detections", "Max Plausible XP Gain (Single Transaction)", 77000, "The maximum amount of XP a player can gain in a single transaction.");
			MaxXPGainPerWindow = ((BaseUnityPlugin)this).Config.Bind<int>("3. Stat Detections", "Max XP Gain Rate", 150000, "The maximum amount of XP a player can gain within the time window specified below.");
			XPGainWindowSeconds = ((BaseUnityPlugin)this).Config.Bind<float>("3. Stat Detections", "XP Gain Time Window (Seconds)", 30f, "The time window for the XP gain rate limit.");
			EnableCooldownChecks = ((BaseUnityPlugin)this).Config.Bind<bool>("4. Combat Detections", "Enable Skill Cooldown Checks", true, "Silently enforces server-side cooldowns, blocking premature skill usage.");
			EnableReviveChecks = ((BaseUnityPlugin)this).Config.Bind<bool>("4. Combat Detections", "Enable Self-Revive Checks", true, "Prevents players from reviving themselves while dead.");
			EnablePunishmentSystem = ((BaseUnityPlugin)this).Config.Bind<bool>("5. Punishments", "Enable Punishment System", true, "If enabled, the server will automatically take action against players who accumulate too many infractions.");
			WarningsUntilAction = ((BaseUnityPlugin)this).Config.Bind<int>("5. Punishments", "Infractions Until Action", 5, "Number of infractions a player can commit before the selected action is taken.");
			ActionType = ((BaseUnityPlugin)this).Config.Bind<string>("5. Punishments", "Action Type", "Kick", new ConfigDescription("The action to take when a player reaches the infraction limit.", (AcceptableValueBase)(object)new AcceptableValueList<string>(new string[2] { "Kick", "Ban" }), Array.Empty<object>()));
			EnableDetailedLogs = ((BaseUnityPlugin)this).Config.Bind<bool>("6. Logging", "Enable Detailed Logs", true, "Master switch for detailed infraction logs.");
			LogPlayerName = ((BaseUnityPlugin)this).Config.Bind<bool>("6. Logging", "Log Player Name", true, "Include the player's name in detailed logs.");
			LogPlayerID = ((BaseUnityPlugin)this).Config.Bind<bool>("6. Logging", "Log Player ID", true, "Include the player's SteamID/netId in detailed logs.");
			LogInfractionDetails = ((BaseUnityPlugin)this).Config.Bind<bool>("6. Logging", "Log Infraction Details", true, "Include the specific reason/details of the infraction in detailed logs.");
			LogInfractionCount = ((BaseUnityPlugin)this).Config.Bind<bool>("6. Logging", "Log Infraction Count", true, "Include the player's current warning count in detailed logs.");
			CheckAndArchiveLogFile();
			ParseWhitelist();
			ParseHACModList();
			TrustedSteamIDs.SettingChanged += delegate
			{
				ParseWhitelist();
			};
			HACModList.SettingChanged += delegate
			{
				ParseHACModList();
			};
			object obj = <>O.<0>__OnClientReceivedHandshakeRequest;
			if (obj == null)
			{
				PacketListener val = OnClientReceivedHandshakeRequest;
				<>O.<0>__OnClientReceivedHandshakeRequest = val;
				obj = (object)val;
			}
			CodeTalkerNetwork.RegisterListener<HAC_HandshakeRequest>((PacketListener)obj);
			object obj2 = <>O.<1>__OnServerReceivedHandshakeResponse;
			if (obj2 == null)
			{
				PacketListener val2 = OnServerReceivedHandshakeResponse;
				<>O.<1>__OnServerReceivedHandshakeResponse = val2;
				obj2 = (object)val2;
			}
			CodeTalkerNetwork.RegisterListener<HAC_HandshakeResponse>((PacketListener)obj2);
			object obj3 = <>O.<2>__OnClientReceivedHeartbeatRequest;
			if (obj3 == null)
			{
				PacketListener val3 = OnClientReceivedHeartbeatRequest;
				<>O.<2>__OnClientReceivedHeartbeatRequest = val3;
				obj3 = (object)val3;
			}
			CodeTalkerNetwork.RegisterListener<HAC_HeartbeatRequest>((PacketListener)obj3);
			object obj4 = <>O.<3>__OnServerReceivedHeartbeatResponse;
			if (obj4 == null)
			{
				PacketListener val4 = OnServerReceivedHeartbeatResponse;
				<>O.<3>__OnServerReceivedHeartbeatResponse = val4;
				obj4 = (object)val4;
			}
			CodeTalkerNetwork.RegisterListener<HAC_HeartbeatResponse>((PacketListener)obj4);
			harmony.PatchAll();
			Log.LogInfo((object)("[HardAntiCheat] has been loaded. Infractions will be logged to: " + InfractionLogPath));
		}

		public static void OnClientReceivedHandshakeRequest(PacketHeader header, PacketBase packet)
		{
			if (packet is HAC_HandshakeRequest hAC_HandshakeRequest && ulong.TryParse(Player._mainPlayer?._steamID, out var result) && hAC_HandshakeRequest.TargetSteamID == result)
			{
				Log.LogInfo((object)"Received verification request from server. Computing composite integrity hash...");
				Dictionary<string, string> modListings = Chainloader.PluginInfos.ToDictionary((KeyValuePair<string, PluginInfo> kvp) => kvp.Key, (KeyValuePair<string, PluginInfo> kvp) => kvp.Value.Metadata.Name);
				string challengeHash = HACIntegrity.GenerateClientCompositeHash(hAC_HandshakeRequest.ChallengeToken, modListings);
				CodeTalkerNetwork.SendNetworkPacket((PacketBase)(object)new HAC_HandshakeResponse
				{
					ChallengeHash = challengeHash,
					ModListings = modListings
				});
			}
		}

		public static void OnServerReceivedHandshakeResponse(PacketHeader header, PacketBase packet)
		{
			if (!(packet is HAC_HandshakeResponse hAC_HandshakeResponse))
			{
				return;
			}
			ulong senderID = header.SenderID;
			if (!PendingVerification.TryGetValue(senderID, out (string, Coroutine) value))
			{
				return;
			}
			if (HACEnforce.Value)
			{
				Dictionary<string, string> source = hAC_HandshakeResponse.ModListings ?? new Dictionary<string, string>();
				string text = HACListType.Value.ToLower();
				bool flag = false;
				string text2 = "";
				if (text == "blacklist")
				{
					KeyValuePair<string, string> keyValuePair = source.FirstOrDefault((KeyValuePair<string, string> mod) => ManagedMods.Contains(mod.Key) || ManagedMods.Contains(mod.Value));
					if (keyValuePair.Key != null)
					{
						flag = true;
						text2 = "Handshake failed: Client has a banned mod (Name: " + keyValuePair.Value + ", GUID: " + keyValuePair.Key + ").";
					}
				}
				else
				{
					KeyValuePair<string, string> keyValuePair2 = source.FirstOrDefault((KeyValuePair<string, string> mod) => mod.Key != "com.HardAntiCheat.sftwre" && !ManagedMods.Contains(mod.Key) && !ManagedMods.Contains(mod.Value));
					if (keyValuePair2.Key != null)
					{
						flag = true;
						text2 = "Handshake failed: Client has a non-whitelisted mod (Name: " + keyValuePair2.Value + ", GUID: " + keyValuePair2.Key + ").";
					}
				}
				if (flag)
				{
					Log.LogWarning((object)text2);
					PunishHandshakeFailure(senderID, text2);
					return;
				}
			}
			if (value.Item1 == hAC_HandshakeResponse.ChallengeHash)
			{
				((MonoBehaviour)Instance).StopCoroutine(value.Item2);
				PendingVerification.Remove(senderID);
				VerifiedSteamIDs.Add(senderID);
				Log.LogInfo((object)$"SteamID {senderID} has been successfully verified (Integrity and Mod List checks passed).");
				if (EnableHeartbeatCheck.Value)
				{
					((MonoBehaviour)Instance).StartCoroutine(Instance.HeartbeatCoroutine(senderID));
				}
			}
			else
			{
				string text3 = "Failed integrity check. Expected hash did not match received hash.";
				Log.LogWarning((object)($"SteamID {senderID} " + text3));
				PunishHandshakeFailure(senderID, text3);
			}
		}

		public static void OnClientReceivedHeartbeatRequest(PacketHeader header, PacketBase packet)
		{
			if (packet is HAC_HeartbeatRequest hAC_HeartbeatRequest && ulong.TryParse(Player._mainPlayer?._steamID, out var result) && hAC_HeartbeatRequest.TargetSteamID == result)
			{
				Dictionary<string, string> modListings = Chainloader.PluginInfos.ToDictionary((KeyValuePair<string, PluginInfo> kvp) => kvp.Key, (KeyValuePair<string, PluginInfo> kvp) => kvp.Value.Metadata.Name);
				string challengeHash = HACIntegrity.GenerateClientCompositeHash(hAC_HeartbeatRequest.ChallengeToken, modListings);
				CodeTalkerNetwork.SendNetworkPacket((PacketBase)(object)new HAC_HeartbeatResponse
				{
					ChallengeHash = challengeHash
				});
			}
		}

		public static void OnServerReceivedHeartbeatResponse(PacketHeader header, PacketBase packet)
		{
			if (!(packet is HAC_HeartbeatResponse hAC_HeartbeatResponse))
			{
				return;
			}
			ulong senderID = header.SenderID;
			if (PendingHeartbeats.TryGetValue(senderID, out string value))
			{
				if (value != hAC_HeartbeatResponse.ChallengeHash)
				{
					PunishHandshakeFailure(senderID, "Failed heartbeat re-verification.");
				}
				PendingHeartbeats.Remove(senderID);
			}
		}

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

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

		private static void ParseWhitelist()
		{
			WhitelistedUsers.Clear();
			string value = TrustedSteamIDs.Value;
			if (string.IsNullOrWhiteSpace(value))
			{
				Log.LogInfo((object)"Whitelist is empty. Only the host may be exempt from checks.");
				return;
			}
			string[] array = value.Split(',');
			int num = 0;
			string[] array2 = array;
			foreach (string text in array2)
			{
				if (ulong.TryParse(text.Trim(), out var result))
				{
					WhitelistedUsers.Add(result);
					num++;
				}
				else
				{
					Log.LogWarning((object)("Could not parse '" + text.Trim() + "' as a valid SteamID. Please ensure it is a 64-bit numerical ID."));
				}
			}
			Log.LogInfo((object)$"Successfully loaded {num} user(s) into the anti-cheat whitelist.");
		}

		private static void ParseHACModList()
		{
			ManagedMods.Clear();
			string value = HACModList.Value;
			if (string.IsNullOrWhiteSpace(value))
			{
				Log.LogInfo((object)"HAC Mod List is empty.");
				return;
			}
			string[] array = value.Split(',');
			int num = 0;
			string[] array2 = array;
			foreach (string text in array2)
			{
				string text2 = text.Trim();
				if (!string.IsNullOrEmpty(text2))
				{
					ManagedMods.Add(text2);
					num++;
				}
			}
			Log.LogInfo((object)$"Successfully loaded {num} entry(s) into the HAC Mod List for {HACListType.Value} enforcement.");
		}

		private static void PunishHandshakeFailure(ulong steamId, string reason)
		{
			if (PendingVerification.TryGetValue(steamId, out (string, Coroutine) value))
			{
				if ((Object)(object)Instance != (Object)null)
				{
					((MonoBehaviour)Instance).StopCoroutine(value.Item2);
				}
				PendingVerification.Remove(steamId);
			}
			PendingHeartbeats.Remove(steamId);
			VerifiedSteamIDs.Remove(steamId);
			Player playerBySteamID = GetPlayerBySteamID(steamId);
			if ((Object)(object)playerBySteamID == (Object)null || ((NetworkBehaviour)playerBySteamID).connectionToClient == null)
			{
				Log.LogError((object)$"Could not find player with SteamID {steamId} to enforce handshake punishment.");
				return;
			}
			string text = HACHandshakeFailAction.Value.ToLower();
			string text2 = $"Player {playerBySteamID._nickname} (ID: {steamId}) was automatically {text.ToUpper()}ed. Reason: {reason}";
			Log.LogWarning((object)text2);
			try
			{
				File.AppendAllText(InfractionLogPath, $"[{DateTime.Now:yyyy-MM-dd HH:mm:ss}] [HANDSHAKE_FAIL] " + text2 + Environment.NewLine);
			}
			catch (Exception ex)
			{
				Log.LogError((object)("Failed to write punishment to log: " + ex.Message));
			}
			if ((Object)(object)HostConsole._current != (Object)null)
			{
				HostConsole._current.Init_ServerMessage("[HAC]: " + text2);
			}
			if (text == "ban")
			{
				HC_PeerListEntry val = null;
				if ((Object)(object)HostConsole._current != (Object)null)
				{
					foreach (HC_PeerListEntry peerListEntry in HostConsole._current._peerListEntries)
					{
						if ((Object)(object)peerListEntry._netId != (Object)null && peerListEntry._netId.netId == ((NetworkBehaviour)playerBySteamID).netId)
						{
							val = peerListEntry;
							break;
						}
					}
				}
				if ((Object)(object)val != (Object)null)
				{
					HostConsole._current._selectedPeerEntry = val;
					HostConsole._current.Ban_Peer();
				}
				else
				{
					((NetworkConnection)((NetworkBehaviour)playerBySteamID).connectionToClient).Disconnect();
					Log.LogError((object)$"Could not find PeerListEntry for player {playerBySteamID._nickname} (netId: {((NetworkBehaviour)playerBySteamID).netId}) to BAN, kicked instead.");
				}
			}
			else
			{
				((NetworkConnection)((NetworkBehaviour)playerBySteamID).connectionToClient).Disconnect();
			}
		}

		public static bool IsPlayerExempt(Player player)
		{
			if ((Object)(object)player == (Object)null)
			{
				return false;
			}
			if (DisableForHost.Value && player._isHostPlayer)
			{
				return true;
			}
			if (!string.IsNullOrEmpty(player._steamID) && ulong.TryParse(player._steamID, out var result) && WhitelistedUsers.Contains(result))
			{
				return true;
			}
			return false;
		}

		private void CheckAndArchiveLogFile()
		{
			try
			{
				if (File.Exists(InfractionLogPath))
				{
					FileInfo fileInfo = new FileInfo(InfractionLogPath);
					long num = (long)MaxLogFileSizeMB.Value * 1024L * 1024;
					if (fileInfo.Length > num)
					{
						string destFileName = Path.Combine(Path.GetDirectoryName(InfractionLogPath), $"{Path.GetFileNameWithoutExtension(InfractionLogPath)}_ARCHIVED_{DateTime.Now:yyyy-MM-dd_HH-mm-ss}.txt");
						File.Move(InfractionLogPath, destFileName);
						Log.LogInfo((object)$"Infraction log exceeded {MaxLogFileSizeMB.Value}MB and was archived.");
					}
				}
			}
			catch (Exception ex)
			{
				Log.LogError((object)("Error while checking/archiving log file: " + ex.Message));
			}
		}

		public static void LogInfraction(NetworkBehaviour instance, string cheatType, string details)
		{
			uint netId = instance.netId;
			if (ServerPunishmentCooldown.TryGetValue(netId, out var value) && Time.time < value)
			{
				return;
			}
			ServerPunishmentCooldown.Remove(netId);
			if (!ServerPlayerInfractionCount.ContainsKey(netId))
			{
				ServerPlayerInfractionCount[netId] = 0;
			}
			ServerPlayerInfractionCount[netId]++;
			int num = ServerPlayerInfractionCount[netId];
			int value2 = WarningsUntilAction.Value;
			Player component = ((Component)instance).GetComponent<Player>();
			string text = component?._nickname ?? "Unknown";
			string text2 = component?._steamID ?? $"netId:{netId}";
			if (EnablePunishmentSystem.Value && !AtlyssNetworkManager._current._soloMode && num >= value2)
			{
				if (!NetworkServer.active || !((Object)(object)component != (Object)null) || ((NetworkBehaviour)component).connectionToClient == null)
				{
					return;
				}
				ServerPunishmentCooldown[netId] = Time.time + 60f;
				string text3 = ActionType.Value.ToLower();
				string text4 = $"Player {text} (ID: {text2}) was automatically {text3.ToUpper()}ed for reaching {num}/{value2} infractions.";
				Log.LogWarning((object)text4);
				try
				{
					File.AppendAllText(InfractionLogPath, $"[{DateTime.Now:yyyy-MM-dd HH:mm:ss}] [PUNISHMENT] " + text4 + Environment.NewLine);
				}
				catch (Exception ex)
				{
					Log.LogError((object)("Failed to write punishment to log: " + ex.Message));
				}
				if ((Object)(object)HostConsole._current != (Object)null)
				{
					HostConsole._current.Init_ServerMessage("[HAC]: " + text4);
				}
				if (text3 == "kick")
				{
					((NetworkConnection)((NetworkBehaviour)component).connectionToClient).Disconnect();
				}
				else
				{
					HC_PeerListEntry val = null;
					if ((Object)(object)HostConsole._current != (Object)null)
					{
						foreach (HC_PeerListEntry peerListEntry in HostConsole._current._peerListEntries)
						{
							if ((Object)(object)peerListEntry._netId != (Object)null && peerListEntry._netId.netId == netId)
							{
								val = peerListEntry;
								break;
							}
						}
					}
					if ((Object)(object)val != (Object)null)
					{
						HostConsole._current._selectedPeerEntry = val;
						HostConsole._current.Ban_Peer();
					}
					else
					{
						((NetworkConnection)((NetworkBehaviour)component).connectionToClient).Disconnect();
						Log.LogError((object)$"Could not find PeerListEntry for player {text} (netId: {netId}) to BAN, kicked instead.");
					}
				}
				ServerPlayerInfractionCount.Remove(netId);
			}
			else if (EnableDetailedLogs.Value)
			{
				StringBuilder stringBuilder = new StringBuilder();
				stringBuilder.Append($"[{DateTime.Now:yyyy-MM-dd HH:mm:ss}]");
				List<string> list = new List<string>();
				if (LogPlayerName.Value)
				{
					list.Add("Player: " + text);
				}
				if (LogPlayerID.Value)
				{
					list.Add("ID: " + text2);
				}
				if (list.Any())
				{
					stringBuilder.Append(" " + string.Join(" | ", list));
				}
				stringBuilder.Append(" | Type: " + cheatType);
				if (LogInfractionDetails.Value)
				{
					stringBuilder.Append(" | Details: " + details);
				}
				if (LogInfractionCount.Value)
				{
					stringBuilder.Append($" | Warning {num}/{value2}");
				}
				string text5 = stringBuilder.ToString();
				Log.LogWarning((object)text5);
				try
				{
					File.AppendAllText(InfractionLogPath, text5 + Environment.NewLine);
				}
				catch (Exception ex2)
				{
					Log.LogError((object)("Failed to write to infraction log: " + ex2.Message));
				}
			}
		}

		public static void ClearAllPlayerData(uint netId, ulong steamId)
		{
			ServerRemainingCooldowns.Remove(netId);
			ServerPlayerPositions.Remove(netId);
			ServerPlayerStats.Remove(netId);
			XpGainHistory.Remove(netId);
			ServerPlayerAirborneStates.Remove(netId);
			ServerPlayerInitialSpeeds.Remove(netId);
			ServerPlayerMovementStats.Remove(netId);
			ServerPlayerMovementTimers.Remove(netId);
			ServerPlayerInfractionCount.Remove(netId);
			ServerPlayerGracePeriod.Remove(netId);
			ServerPunishmentCooldown.Remove(netId);
			ServerSpeedCheckCooldowns.Remove(netId);
			ServerJumpCheckCooldowns.Remove(netId);
			ServerAirborneCheckCooldowns.Remove(netId);
			if (PendingVerification.TryGetValue(steamId, out (string, Coroutine) value))
			{
				if ((Object)(object)Instance != (Object)null)
				{
					((MonoBehaviour)Instance).StopCoroutine(value.Item2);
				}
				PendingVerification.Remove(steamId);
			}
			VerifiedSteamIDs.Remove(steamId);
			PendingHeartbeats.Remove(steamId);
		}

		private static Player GetPlayerBySteamID(ulong steamId)
		{
			Player val = default(Player);
			foreach (NetworkConnectionToClient value in NetworkServer.connections.Values)
			{
				if ((Object)(object)((NetworkConnection)value).identity != (Object)null && ((Component)((NetworkConnection)value).identity).TryGetComponent<Player>(ref val) && ulong.TryParse(val._steamID, out var result) && result == steamId)
				{
					return val;
				}
			}
			return null;
		}
	}
	[HarmonyPatch(typeof(PlayerMove), "Start")]
	public static class PlayerSpawnPatch
	{
		private const float GRACE_PERIOD_SECONDS = 3f;

		private static bool hasServerInitialized;

		public static void Postfix(PlayerMove __instance)
		{
			//IL_0095: Unknown result type (might be due to invalid IL or missing references)
			//IL_009a: Unknown result type (might be due to invalid IL or missing references)
			if (!NetworkServer.active)
			{
				return;
			}
			if (!hasServerInitialized)
			{
				Main.Log.LogInfo((object)"First player has spawned. HardAntiCheat server-side modules are now active.");
				hasServerInitialized = true;
			}
			uint netId = ((NetworkBehaviour)__instance).netId;
			Player component = ((Component)__instance).GetComponent<Player>();
			Main.ServerPlayerGracePeriod[netId] = Time.time + 3f;
			if (!Main.ServerPlayerInitialSpeeds.ContainsKey(netId))
			{
				Main.ServerPlayerInitialSpeeds[netId] = __instance.Network_movSpeed;
			}
			Main.ServerPlayerPositions[netId] = new PlayerPositionData
			{
				Position = ((Component)__instance).transform.position,
				Timestamp = Time.time
			};
			Main.ServerPlayerMovementStats[netId] = new PlayerMovementStats
			{
				RecentSpeeds = new List<float>(),
				TimeAtMaxSpeed = 0f
			};
			Main.ServerPlayerMovementTimers[netId] = Time.time;
			if (!Main.EnableIntegrityChecks.Value || !((Object)(object)component != (Object)null) || ((NetworkBehaviour)component).isLocalPlayer || !ulong.TryParse(component._steamID, out var result))
			{
				return;
			}
			if (Main.IsPlayerExempt(component))
			{
				Main.Log.LogInfo((object)("Player " + component._nickname + " is exempt from anti-cheat checks. Skipping verification."));
				Main.VerifiedSteamIDs.Add(result);
			}
			else if (!Main.PendingVerification.ContainsKey(result) && !Main.VerifiedSteamIDs.Contains(result))
			{
				Main.Log.LogInfo((object)("Player " + component._nickname + " spawned on server. Sending integrity challenge..."));
				string text = Guid.NewGuid().ToString();
				Dictionary<string, string> modListings = Chainloader.PluginInfos.ToDictionary((KeyValuePair<string, PluginInfo> kvp) => kvp.Key, (KeyValuePair<string, PluginInfo> kvp) => kvp.Value.Metadata.Name);
				string item = HACIntegrity.GenerateClientCompositeHash(text, modListings);
				HAC_HandshakeRequest hAC_HandshakeRequest = new HAC_HandshakeRequest
				{
					TargetSteamID = result,
					ChallengeToken = text,
					ChallengeType = 0
				};
				CodeTalkerNetwork.SendNetworkPacket((PacketBase)(object)hAC_HandshakeRequest);
				Coroutine item2 = ((MonoBehaviour)Main.Instance).StartCoroutine(Main.Instance.KickClientAfterDelay(component));
				Main.PendingVerification[result] = (item, item2);
			}
		}
	}
	[HarmonyPatch]
	public static class ButtonPressValidationPatch
	{
		private static DeathPromptManager _deathPromptManagerInstance;

		[HarmonyPatch(typeof(Button), "Press")]
		[HarmonyPrefix]
		public static bool OnButtonPress(Button __instance)
		{
			if ((Object)(object)_deathPromptManagerInstance == (Object)null)
			{
				_deathPromptManagerInstance = Object.FindObjectOfType<DeathPromptManager>();
				if ((Object)(object)_deathPromptManagerInstance == (Object)null)
				{
					return true;
				}
			}
			Button value = Traverse.Create((object)_deathPromptManagerInstance).Field<Button>("_useTearButton").Value;
			if ((Object)(object)value != (Object)null && (Object)(object)__instance == (Object)(object)value)
			{
				Player mainPlayer = Player._mainPlayer;
				if ((Object)(object)mainPlayer != (Object)null)
				{
					PlayerInventory component = ((Component)mainPlayer).GetComponent<PlayerInventory>();
					if ((Object)(object)component != (Object)null)
					{
						foreach (ItemData heldItem in component._heldItems)
						{
							if (heldItem != null && heldItem._itemName == "Angela's Tear")
							{
								component.Cmd_UseConsumable(heldItem);
								return true;
							}
						}
					}
				}
			}
			return true;
		}
	}
	[HarmonyPatch]
	public static class ItemUsageValidationPatch
	{
		[HarmonyPatch(typeof(PlayerInventory), "UserCode_Cmd_UseConsumable__ItemData")]
		[HarmonyPrefix]
		public static void GrantTokenOnTearUsage(PlayerInventory __instance, ItemData _itemData)
		{
			if (NetworkServer.active && _itemData != null && _itemData._itemName == "Angela's Tear")
			{
				Main.AuthorizedSelfRevives[((NetworkBehaviour)__instance).netId] = Time.time;
			}
		}
	}
	[HarmonyPatch]
	public static class ServerAuthorityValidationPatch
	{
		[HarmonyPatch(typeof(StatusEntity), "Cmd_RevivePlayer")]
		[HarmonyPrefix]
		public static bool ValidateRevive(StatusEntity __instance, StatusEntity _statusEntity)
		{
			if (!NetworkServer.active || !Main.EnableAntiCheat.Value || !Main.EnableReviveChecks.Value)
			{
				return true;
			}
			Player component = ((Component)_statusEntity).GetComponent<Player>();
			if ((Object)(object)component == (Object)null)
			{
				return true;
			}
			if (Main.IsPlayerExempt(component))
			{
				return true;
			}
			if (((NetworkBehaviour)__instance).netId == ((NetworkBehaviour)_statusEntity).netId)
			{
				Main.LogInfraction((NetworkBehaviour)(object)__instance, "Unauthorized Action (Direct Self-Revive)", "Blocked direct call to self-revive.");
				return false;
			}
			return true;
		}

		[HarmonyPatch(typeof(StatusEntity), "Cmd_ReplenishAll")]
		[HarmonyPrefix]
		public static bool ValidateReplenish(StatusEntity __instance)
		{
			Player component = ((Component)__instance).GetComponent<Player>();
			if (!NetworkServer.active || !Main.EnableAntiCheat.Value || !Main.EnableReviveChecks.Value)
			{
				return true;
			}
			if (Main.IsPlayerExempt(component))
			{
				return true;
			}
			if (__instance.Network_currentHealth <= 0)
			{
				uint netId = ((NetworkBehaviour)component).netId;
				if (Main.AuthorizedSelfRevives.TryGetValue(netId, out var value) && Time.time - value < 1.5f)
				{
					Main.AuthorizedSelfRevives.Remove(netId);
					return true;
				}
				Main.LogInfraction((NetworkBehaviour)(object)__instance, "Unauthorized Action (Replenish while Dead)", "Blocked replenish call - was not authorized by UI button press.");
				return false;
			}
			return true;
		}
	}
	[HarmonyPatch(typeof(NetworkTransformBase), "CmdTeleport", new Type[]
	{
		typeof(Vector3),
		typeof(Quaternion)
	})]
	public static class CmdTeleportValidationPatch2
	{
		public static bool Prefix(NetworkBehaviour __instance)
		{
			if (!NetworkServer.active || !Main.EnableAntiCheat.Value || !Main.EnableMovementChecks.Value)
			{
				return true;
			}
			Player component = ((Component)__instance).GetComponent<Player>();
			if (Main.IsPlayerExempt(component))
			{
				return true;
			}
			Main.LogInfraction(__instance, "Movement Hack (Illegal Teleport Command)", "Player directly called a Teleport command.");
			return false;
		}
	}
	[HarmonyPatch(typeof(NetworkTransformBase), "CmdTeleport", new Type[] { typeof(Vector3) })]
	public static class CmdTeleportValidationPatch
	{
		public static bool Prefix(NetworkBehaviour __instance)
		{
			if (!NetworkServer.active || !Main.EnableAntiCheat.Value || !Main.EnableMovementChecks.Value)
			{
				return true;
			}
			Player component = ((Component)__instance).GetComponent<Player>();
			if (Main.IsPlayerExempt(component))
			{
				return true;
			}
			Main.LogInfraction(__instance, "Movement Hack (Illegal Teleport Command)", "Player directly called a Teleport command.");
			return false;
		}
	}
	[HarmonyPatch(typeof(Player))]
	public static class PlayerHoneypotPatch
	{
		[HarmonyPatch("Start")]
		[HarmonyPostfix]
		public static void AddHoneypot(Player __instance)
		{
			if ((Object)(object)((Component)__instance).gameObject.GetComponent<HoneypotComponent>() == (Object)null)
			{
				((Component)__instance).gameObject.AddComponent<HoneypotComponent>();
			}
		}
	}
	public class HoneypotComponent : NetworkBehaviour
	{
		[Command]
		public void Cmd_ExecuteDebugBypass()
		{
			if (ulong.TryParse(((Component)this).GetComponent<Player>()._steamID, out var result))
			{
				Main.Log.LogWarning((object)$"HONEYPOT TRIGGERED by SteamID {result}. Banning immediately.");
				HC_PeerListEntry val = ((IEnumerable<HC_PeerListEntry>)HostConsole._current._peerListEntries).FirstOrDefault((Func<HC_PeerListEntry, bool>)((HC_PeerListEntry p) => (Object)(object)p._netId != (Object)null && p._netId.netId == ((NetworkBehaviour)this).netId));
				if ((Object)(object)HostConsole._current != (Object)null && (Object)(object)val != (Object)null)
				{
					HostConsole._current._selectedPeerEntry = val;
					HostConsole._current.Ban_Peer();
				}
				else
				{
					((NetworkConnection)((NetworkBehaviour)this).connectionToClient).Disconnect();
				}
			}
		}
	}
	[HarmonyPatch(typeof(PlayerMove), "Init_Jump")]
	public static class JumpValidationPatch
	{
		public static bool Prefix(PlayerMove __instance)
		{
			//IL_0088: Unknown result type (might be due to invalid IL or missing references)
			//IL_008d: 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)
			Player component = ((Component)__instance).GetComponent<Player>();
			if (!NetworkServer.active || !Main.EnableAntiCheat.Value || !Main.EnableAirborneChecks.Value)
			{
				return true;
			}
			if (Main.IsPlayerExempt(component))
			{
				return true;
			}
			uint netId = ((NetworkBehaviour)__instance).netId;
			if (!Main.ServerPlayerAirborneStates.ContainsKey(netId))
			{
				Main.ServerPlayerAirborneStates[netId] = new PlayerAirborneData
				{
					AirTime = 0f,
					LastGroundedPosition = ((Component)__instance).transform.position,
					ServerSideJumpCount = 0,
					LastVerticalPosition = ((Component)__instance).transform.position.y,
					VerticalStallTime = 0f
				};
			}
			PlayerAirborneData value = Main.ServerPlayerAirborneStates[netId];
			if (value.ServerSideJumpCount >= Main.JumpThreshold.Value)
			{
				return false;
			}
			value.ServerSideJumpCount++;
			Main.ServerPlayerAirborneStates[netId] = value;
			return true;
		}
	}
	[HarmonyPatch(typeof(PlayerMove), "Update")]
	public static class MovementAndAirborneValidationPatch
	{
		private const float MAX_ALLOWED_AIR_TIME = 10f;

		private const float VERTICAL_STALL_TOLERANCE = 0.05f;

		private const float VERTICAL_STALL_GRACE_PERIOD = 0.5f;

		private const float MAX_FLIGHT_HEIGHT = 4240f;

		private const int STATS_BUFFER_SIZE = 20;

		private const float STATS_ANALYSIS_INTERVAL = 2f;

		public static void Postfix(PlayerMove __instance)
		{
			//IL_0163: Unknown result type (might be due to invalid IL or missing references)
			//IL_0168: Unknown result type (might be due to invalid IL or missing references)
			//IL_03ce: Unknown result type (might be due to invalid IL or missing references)
			//IL_03cf: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a5: Unknown result type (might be due to invalid IL or missing references)
			//IL_01aa: Unknown result type (might be due to invalid IL or missing references)
			//IL_0420: Unknown result type (might be due to invalid IL or missing references)
			//IL_0421: Unknown result type (might be due to invalid IL or missing references)
			//IL_0430: Unknown result type (might be due to invalid IL or missing references)
			//IL_0530: Unknown result type (might be due to invalid IL or missing references)
			//IL_050a: Unknown result type (might be due to invalid IL or missing references)
			//IL_050b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0571: Unknown result type (might be due to invalid IL or missing references)
			//IL_057c: Unknown result type (might be due to invalid IL or missing references)
			//IL_03b0: Unknown result type (might be due to invalid IL or missing references)
			//IL_05b8: Unknown result type (might be due to invalid IL or missing references)
			//IL_0666: Unknown result type (might be due to invalid IL or missing references)
			if (!NetworkServer.active || !Main.EnableAntiCheat.Value || AtlyssNetworkManager._current._soloMode)
			{
				return;
			}
			Player component = ((Component)__instance).GetComponent<Player>();
			if (Main.IsPlayerExempt(component))
			{
				return;
			}
			uint netId = ((NetworkBehaviour)__instance).netId;
			if (Main.ServerPlayerGracePeriod.TryGetValue(netId, out var value))
			{
				if (Time.time < value)
				{
					return;
				}
				Main.ServerPlayerGracePeriod.Remove(netId);
			}
			if (Main.EnableSpeedChecks.Value && (!Main.ServerSpeedCheckCooldowns.ContainsKey(netId) || Time.time > Main.ServerSpeedCheckCooldowns[netId]) && Main.ServerPlayerInitialSpeeds.TryGetValue(netId, out var value2))
			{
				if (__instance._movSpeed > value2 * 1.5f)
				{
					Main.LogInfraction((NetworkBehaviour)(object)__instance, "Stat Manipulation (Move Speed)", $"Detected illegal move speed of {__instance._movSpeed}. Reverting to initial speed of {value2}.");
					__instance.Reset_MoveSpeed();
					Main.ServerSpeedCheckCooldowns[netId] = Time.time + Main.SpeedHackDetectionCooldown.Value;
				}
				else if (__instance._movSpeed < 20f)
				{
					__instance.Reset_MoveSpeed();
				}
			}
			Vector3 position = ((Component)__instance).transform.position;
			if (Main.EnableMovementChecks.Value)
			{
				if (Main.ServerPlayerPositions.TryGetValue(netId, out var value3))
				{
					float num = Time.time - value3.Timestamp;
					float num2 = Vector3.Distance(value3.Position, position);
					if (num > 0.1f)
					{
						float num3 = num2 / num;
						float value4;
						float num4 = (Main.ServerPlayerInitialSpeeds.TryGetValue(netId, out value4) ? value4 : 50f);
						float num5 = num4 * 1.5f;
						if (Main.ServerPlayerMovementStats.TryGetValue(netId, out var value5))
						{
							value5.RecentSpeeds.Add(num3);
							if (value5.RecentSpeeds.Count > 20)
							{
								value5.RecentSpeeds.RemoveAt(0);
							}
							if (num3 / num5 > 0.95f)
							{
								value5.TimeAtMaxSpeed += num;
							}
							if (Main.ServerPlayerMovementTimers.TryGetValue(netId, out var value6) && Time.time > value6 + 2f)
							{
								Main.ServerPlayerMovementTimers[netId] = Time.time;
								float num6 = value5.RecentSpeeds.Average();
								if (num6 > num5 * 0.9f || value5.TimeAtMaxSpeed > 1.6f)
								{
									Main.LogInfraction((NetworkBehaviour)(object)__instance, "Movement Hack (Statistical)", $"Player exhibited unnaturally consistent high speed. Avg: {num6:F1}, MaxTime: {value5.TimeAtMaxSpeed:F1}s");
								}
								value5.TimeAtMaxSpeed = 0f;
							}
							Main.ServerPlayerMovementStats[netId] = value5;
						}
					}
					if (num > Main.MovementTimeThreshold.Value)
					{
						float value7;
						float num7 = (Main.ServerPlayerInitialSpeeds.TryGetValue(netId, out value7) ? value7 : 50f) * 1.5f * num + Main.MovementGraceBuffer.Value;
						if (num2 > num7)
						{
							string cheatType = ((num2 > Main.TeleportDistanceThreshold.Value) ? "Movement Hack (Teleport)" : "Movement Hack (Speed Mismatch)");
							string details = $"Moved {num2:F1} units in {num:F2}s (Expected max: {num7:F1}). Reverting position.";
							Main.LogInfraction((NetworkBehaviour)(object)__instance, cheatType, details);
							((Component)component).transform.position = value3.Position;
						}
					}
				}
				Main.ServerPlayerPositions[netId] = new PlayerPositionData
				{
					Position = position,
					Timestamp = Time.time
				};
			}
			if (!Main.EnableAirborneChecks.Value)
			{
				return;
			}
			PlayerAirborneData playerAirborneData2;
			if (!Main.ServerPlayerAirborneStates.ContainsKey(netId))
			{
				PlayerAirborneData playerAirborneData = default(PlayerAirborneData);
				playerAirborneData.AirTime = 0f;
				playerAirborneData.LastGroundedPosition = position;
				playerAirborneData.ServerSideJumpCount = 0;
				playerAirborneData.LastVerticalPosition = position.y;
				playerAirborneData.VerticalStallTime = 0f;
				playerAirborneData2 = playerAirborneData;
			}
			else
			{
				playerAirborneData2 = Main.ServerPlayerAirborneStates[netId];
			}
			PlayerAirborneData value8 = playerAirborneData2;
			if ((!Main.ServerJumpCheckCooldowns.ContainsKey(netId) || Time.time > Main.ServerJumpCheckCooldowns[netId]) && __instance._maxJumps >= Main.JumpThreshold.Value)
			{
				Main.LogInfraction((NetworkBehaviour)(object)__instance, "Stat Manipulation (Overboarded Jumps)", $"Client reported _maxJumps of {__instance._maxJumps}. Reverting to 2.");
				__instance._maxJumps = 2;
				Main.ServerJumpCheckCooldowns[netId] = Time.time + Main.JumpHackDetectionCooldown.Value;
			}
			if (__instance.RayGroundCheck())
			{
				value8.AirTime = 0f;
				value8.ServerSideJumpCount = 0;
				value8.LastGroundedPosition = position;
				value8.VerticalStallTime = 0f;
			}
			else
			{
				value8.AirTime += Time.deltaTime;
				if (Mathf.Abs(position.y - value8.LastVerticalPosition) < 0.05f)
				{
					value8.VerticalStallTime += Time.deltaTime;
				}
				else
				{
					value8.VerticalStallTime = 0f;
				}
			}
			value8.LastVerticalPosition = position.y;
			if (position.y > 4240f)
			{
				Main.LogInfraction((NetworkBehaviour)(object)__instance, "Movement Hack (Fly)", $"Exceeded maximum height limit of {4240f}. Reverting to last ground position.");
				((Component)__instance).transform.position = value8.LastGroundedPosition;
				return;
			}
			if (value8.AirTime > 10f)
			{
				if (value8.VerticalStallTime < 0.5f && (!Main.ServerAirborneCheckCooldowns.ContainsKey(netId) || Time.time > Main.ServerAirborneCheckCooldowns[netId]))
				{
					Main.LogInfraction((NetworkBehaviour)(object)__instance, "Movement Hack (Fly)", $"Airborne for {value8.AirTime:F1} seconds. Reverting to last ground position.");
					Main.ServerAirborneCheckCooldowns[netId] = Time.time + Main.AirborneHackDetectionCooldown.Value;
				}
				((Component)__instance).transform.position = value8.LastGroundedPosition;
				value8.AirTime = 0f;
				value8.ServerSideJumpCount = 0;
				value8.VerticalStallTime = 0f;
			}
			Main.ServerPlayerAirborneStates[netId] = value8;
		}
	}
	[HarmonyPatch]
	public static class ExperienceValidationPatch
	{
		[HarmonyPatch(typeof(PlayerStats), "set_Network_currentExp")]
		[HarmonyPrefix]
		public static bool ValidateExperienceChange(PlayerStats __instance, ref int value)
		{
			Player component = ((Component)__instance).GetComponent<Player>();
			if (!NetworkServer.active || !Main.EnableAntiCheat.Value || !Main.EnableExperienceChecks.Value)
			{
				return true;
			}
			if (Main.IsPlayerExempt(component))
			{
				return true;
			}
			uint netId = ((NetworkBehaviour)__instance).netId;
			if (!Main.ServerPlayerStats.TryGetValue(netId, out var value2))
			{
				Main.ServerPlayerStats[netId] = new PlayerStatsData
				{
					Experience = value,
					Level = __instance.Network_currentLevel
				};
				return true;
			}
			int experience = value2.Experience;
			int num = value - experience;
			if (num <= 0)
			{
				PlayerStatsData value3 = Main.ServerPlayerStats[netId];
				value3.Experience = value;
				Main.ServerPlayerStats[netId] = value3;
				return true;
			}
			if (num > Main.MaxPlausibleXPGain.Value)
			{
				Main.LogInfraction((NetworkBehaviour)(object)__instance, "Stat Manipulation (Experience)", $"Attempted to gain {num} XP at once (Limit: {Main.MaxPlausibleXPGain.Value}). Blocked.");
				value = experience;
				return false;
			}
			if (IsXpGainRateExceeded(netId, num))
			{
				Main.LogInfraction((NetworkBehaviour)(object)__instance, "Stat Manipulation (XP Rate)", "Attempted to gain XP too quickly. Blocked.");
				value = experience;
				return false;
			}
			PlayerStatsData value4 = Main.ServerPlayerStats[netId];
			value4.Experience = value;
			Main.ServerPlayerStats[netId] = value4;
			return true;
		}

		private static bool IsXpGainRateExceeded(uint netId, int gain)
		{
			if (!Main.XpGainHistory.ContainsKey(netId))
			{
				Main.XpGainHistory[netId] = new List<(float, int)>();
			}
			List<(float, int)> list = Main.XpGainHistory[netId];
			float currentTime = Time.time;
			float window = Main.XPGainWindowSeconds.Value;
			list.RemoveAll(((float Timestamp, int Amount) entry) => currentTime - entry.Timestamp > window);
			int num = list.Sum<(float, int)>(((float Timestamp, int Amount) entry) => entry.Amount);
			if (num + gain > Main.MaxXPGainPerWindow.Value)
			{
				return true;
			}
			list.Add((currentTime, gain));
			return false;
		}

		[HarmonyPatch(typeof(PlayerStats), "set_Network_currentLevel")]
		[HarmonyPrefix]
		public static bool ValidateLevelChange(PlayerStats __instance, ref int value)
		{
			Player component = ((Component)__instance).GetComponent<Player>();
			if (!NetworkServer.active || !Main.EnableAntiCheat.Value || !Main.EnableExperienceChecks.Value)
			{
				return true;
			}
			if (Main.IsPlayerExempt(component))
			{
				return true;
			}
			uint netId = ((NetworkBehaviour)__instance).netId;
			if (!Main.ServerPlayerStats.TryGetValue(netId, out var value2))
			{
				Main.ServerPlayerStats[netId] = new PlayerStatsData
				{
					Experience = __instance.Network_currentExp,
					Level = value
				};
				return true;
			}
			int level = value2.Level;
			int num = value - level;
			if (num > 1)
			{
				Main.LogInfraction((NetworkBehaviour)(object)__instance, "Stat Manipulation (Level)", $"Attempted to jump from level {level} to {value}. Blocked.");
				value = level;
			}
			PlayerStatsData value3 = Main.ServerPlayerStats[netId];
			value3.Level = value;
			Main.ServerPlayerStats[netId] = value3;
			return true;
		}
	}
	[HarmonyPatch]
	public static class CombatValidationPatch
	{
		[HarmonyPatch(typeof(PlayerCasting), "Update")]
		[HarmonyPostfix]
		public static void CooldownUpdate(PlayerCasting __instance)
		{
			if (!NetworkServer.active || !Main.EnableAntiCheat.Value || !Main.EnableCooldownChecks.Value)
			{
				return;
			}
			uint netId = ((NetworkBehaviour)__instance).netId;
			if (!Main.ServerRemainingCooldowns.TryGetValue(netId, out Dictionary<string, float> value))
			{
				return;
			}
			List<string> list = new List<string>();
			List<string> list2 = new List<string>(value.Keys);
			foreach (string item in list2)
			{
				float num = Time.deltaTime + Time.deltaTime * __instance._cooldownMod;
				float num2 = value[item] - num;
				if (num2 <= 0f)
				{
					list.Add(item);
				}
				else
				{
					value[item] = num2;
				}
			}
			foreach (string item2 in list)
			{
				value.Remove(item2);
			}
		}

		[HarmonyPatch(typeof(PlayerCasting), "Server_CastSkill")]
		[HarmonyPrefix]
		public static bool UnifiedCooldownValidation(PlayerCasting __instance)
		{
			Player component = ((Component)__instance).GetComponent<Player>();
			if (!NetworkServer.active || !Main.EnableAntiCheat.Value || !Main.EnableCooldownChecks.Value)
			{
				return true;
			}
			if (Main.IsPlayerExempt(component))
			{
				return true;
			}
			ScriptableSkill currentCastSkill = __instance._currentCastSkill;
			if ((Object)(object)currentCastSkill == (Object)null)
			{
				return true;
			}
			uint netId = ((NetworkBehaviour)__instance).netId;
			if (Main.ServerRemainingCooldowns.TryGetValue(netId, out Dictionary<string, float> value) && value.ContainsKey(((Object)currentCastSkill).name))
			{
				__instance.Server_InterruptCast();
				Main.LogInfraction((NetworkBehaviour)(object)__instance, "Skill Manipulation", "Attempted to cast " + ((Object)currentCastSkill).name + " while on cooldown.");
				return false;
			}
			if (!Main.ServerRemainingCooldowns.ContainsKey(netId))
			{
				Main.ServerRemainingCooldowns[netId] = new Dictionary<string, float>();
			}
			Main.ServerRemainingCooldowns[netId][((Object)currentCastSkill).name] = currentCastSkill._skillRankParams._baseCooldown;
			return true;
		}
	}
	[HarmonyPatch(typeof(AtlyssNetworkManager), "OnServerDisconnect")]
	public static class PlayerDisconnectPatch
	{
		public static void Postfix(NetworkConnectionToClient _conn)
		{
			if (_conn != null && (Object)(object)((NetworkConnection)_conn).identity != (Object)null)
			{
				uint netId = ((NetworkConnection)_conn).identity.netId;
				if (ulong.TryParse(((Component)((NetworkConnection)_conn).identity).GetComponent<Player>()?._steamID, out var result))
				{
					Main.ClearAllPlayerData(netId, result);
				}
			}
		}
	}
	[HarmonyPatch(typeof(AtlyssNetworkManager), "OnStartServer")]
	public static class ServerStartPatch
	{
		[CompilerGenerated]
		private static class <>O
		{
			public static PacketListener <0>__OnServerReceivedHandshakeResponse;
		}

		public static void Postfix()
		{
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			//IL_0046: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_002b: Expected O, but got Unknown
			//IL_0058: 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)
			if (Main.EnableIntegrityChecks.Value)
			{
				object obj = <>O.<0>__OnServerReceivedHandshakeResponse;
				if (obj == null)
				{
					PacketListener val = Main.OnServerReceivedHandshakeResponse;
					<>O.<0>__OnServerReceivedHandshakeResponse = val;
					obj = (object)val;
				}
				CodeTalkerNetwork.RegisterListener<HAC_HandshakeResponse>((PacketListener)obj);
				Main.Log.LogInfo((object)"HAC Server-side integrity check handler registered.");
				CSteamID steamID = SteamUser.GetSteamID();
				if (((CSteamID)(ref steamID)).IsValid())
				{
					Main.VerifiedSteamIDs.Add(steamID.m_SteamID);
					Main.Log.LogInfo((object)$"Host (SteamID: {steamID.m_SteamID}) has been automatically verified.");
				}
			}
		}
	}
	internal static class ModInfo
	{
		public const string GUID = "com.HardAntiCheat.sftwre";

		public const string NAME = "HardAntiCheat";

		public const string VERSION = "2.2.7";
	}
}
namespace System.Runtime.CompilerServices
{
	[AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)]
	internal sealed class IgnoresAccessChecksToAttribute : Attribute
	{
		public IgnoresAccessChecksToAttribute(string assemblyName)
		{
		}
	}
}