Decompiled source of NoAFKRaids v1.0.0

NoAFKRaids.dll

Decompiled 16 hours ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using UnityEngine;

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

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace NoAFKRaids
{
	[BepInPlugin("com.dumba.valheim.noafkraids", "No AFK Raids", "1.0.0")]
	public class NoAFKRaids : BaseUnityPlugin
	{
		public class PlayerAFKData
		{
			public bool IsAFK { get; set; }

			public DateTime LastActivity { get; set; }

			public Vector3 LastPosition { get; set; }

			public DateTime LastUpdate { get; set; }

			public bool IsConnected { get; set; } = true;

		}

		public enum FallbackPolicyType
		{
			Conservative,
			Liberal,
			Smart,
			PlayerBased
		}

		public class RaidEvaluationContext
		{
			public RandEventSystem Instance { get; set; }

			public DateTime StartTime { get; set; }

			public int AttemptCount { get; set; }

			public bool IsEvaluating { get; set; }

			public string RaidName { get; set; }
		}

		public struct PositionDetectionResult
		{
			public Vector3 Position { get; set; }

			public bool Success { get; set; }

			public string Method { get; set; }

			public int Attempt { get; set; }
		}

		public struct RaidEvaluationResult
		{
			public bool Success { get; set; }

			public bool ShouldBlock { get; set; }

			public string Reason { get; set; }

			public Vector3 Position { get; set; }
		}

		public const string GUID = "com.dumba.valheim.noafkraids";

		public const string NAME = "No AFK Raids";

		public const string VERSION = "1.0.0";

		internal static NoAFKRaids Instance;

		internal static ManualLogSource Log;

		internal static ConfigEntry<int> AFKMinutes;

		internal static ConfigEntry<float> MovementThreshold;

		internal static ConfigEntry<int> UpdateInterval;

		internal static ConfigEntry<bool> LogEvents;

		internal static ConfigEntry<bool> LogAFKStateChanges;

		internal static ConfigEntry<bool> DebugMode;

		internal static ConfigEntry<float> AFKProtectionRadius;

		internal static ConfigEntry<bool> ProtectGlobalRaids;

		internal static ConfigEntry<float> GlobalRaidAFKRadius;

		internal static ConfigEntry<bool> LogRaidPositions;

		internal static ConfigEntry<bool> ShowProtectionRadius;

		internal static ConfigEntry<float> PositionCheckDelay;

		internal static ConfigEntry<int> MaxPositionRetries;

		internal static ConfigEntry<bool> UseDelayedEvaluation;

		internal static ConfigEntry<string> FallbackPolicy;

		internal static readonly Dictionary<long, PlayerAFKData> PlayerStates = new Dictionary<long, PlayerAFKData>();

		private static readonly Dictionary<int, RaidEvaluationContext> ActiveEvaluations = new Dictionary<int, RaidEvaluationContext>();

		private Harmony _harmony;

		private Coroutine _afkDetectionCoroutine;

		private void Awake()
		{
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: Expected O, but got Unknown
			Instance = this;
			Log = ((BaseUnityPlugin)this).Logger;
			InitializeConfig();
			_harmony = new Harmony("com.dumba.valheim.noafkraids");
			_harmony.PatchAll();
			((MonoBehaviour)this).StartCoroutine(InitializeRPCSystem());
			Log.LogInfo((object)"No AFK Raids v1.0.0 loaded");
		}

		private void InitializeConfig()
		{
			AFKMinutes = ((BaseUnityPlugin)this).Config.Bind<int>("General", "AFKMinutes", 3, "Minutes without movement before a player is considered AFK");
			MovementThreshold = ((BaseUnityPlugin)this).Config.Bind<float>("General", "MovementThreshold", 0.1f, "Minimum movement distance to be considered active");
			UpdateInterval = ((BaseUnityPlugin)this).Config.Bind<int>("General", "UpdateInterval", 10, "Seconds between AFK status updates");
			AFKProtectionRadius = ((BaseUnityPlugin)this).Config.Bind<float>("Proximity Protection", "AFKProtectionRadius", 200f, "Distance in meters around AFK players where raids will be blocked");
			ProtectGlobalRaids = ((BaseUnityPlugin)this).Config.Bind<bool>("Proximity Protection", "ProtectGlobalRaids", false, "Whether to block global raids if any players are AFK anywhere on the server");
			GlobalRaidAFKRadius = ((BaseUnityPlugin)this).Config.Bind<float>("Proximity Protection", "GlobalRaidAFKRadius", 200f, "For global raids, the protection radius around AFK players (only used if ProtectGlobalRaids is true)");
			LogEvents = ((BaseUnityPlugin)this).Config.Bind<bool>("Logging", "LogRaidDecisions", true, "Log when raids are blocked or allowed");
			LogAFKStateChanges = ((BaseUnityPlugin)this).Config.Bind<bool>("Logging", "LogAFKStateChanges", false, "Log when players go AFK or become active");
			LogRaidPositions = ((BaseUnityPlugin)this).Config.Bind<bool>("Logging", "LogRaidPositions", true, "Log raid spawn positions for debugging");
			ShowProtectionRadius = ((BaseUnityPlugin)this).Config.Bind<bool>("Logging", "ShowProtectionRadius", true, "Show protection radius information in logs");
			DebugMode = ((BaseUnityPlugin)this).Config.Bind<bool>("Debug", "DebugMode", false, "Enable verbose debugging output");
			PositionCheckDelay = ((BaseUnityPlugin)this).Config.Bind<float>("Timing", "PositionCheckDelay", 0.1f, "Seconds to wait after raid start before checking position");
			MaxPositionRetries = ((BaseUnityPlugin)this).Config.Bind<int>("Timing", "MaxPositionRetries", 5, "Maximum attempts to get raid position before applying fallback");
			UseDelayedEvaluation = ((BaseUnityPlugin)this).Config.Bind<bool>("Timing", "UseDelayedEvaluation", true, "Use coroutine-based delayed evaluation for more reliable position detection");
			FallbackPolicy = ((BaseUnityPlugin)this).Config.Bind<string>("Timing", "FallbackPolicy", "Conservative", "Fallback policy when position detection fails: Conservative, Liberal, Smart, PlayerBased");
		}

		private IEnumerator InitializeRPCSystem()
		{
			yield return (object)new WaitUntil((Func<bool>)(() => (Object)(object)ZNet.instance != (Object)null));
			if (DebugMode.Value)
			{
				Log.LogInfo((object)"ZNet initialized, setting up RPC system");
			}
			RegisterRPCs();
			_afkDetectionCoroutine = ((MonoBehaviour)this).StartCoroutine(ClientAFKDetectionLoop());
		}

		private void RegisterRPCs()
		{
			try
			{
				if (ZNet.instance.IsServer())
				{
					ZRpc serverRPC = ZNet.instance.GetServerRPC();
					if (serverRPC != null)
					{
						serverRPC.Register<bool, Vector3>("NoAFKRaids_AFKUpdateWithPosition", (Action<ZRpc, bool, Vector3>)OnClientAFKUpdateWithPosition);
					}
					if (DebugMode.Value)
					{
						Log.LogInfo((object)"Server RPC registered: NoAFKRaids_AFKUpdateWithPosition");
					}
				}
			}
			catch (Exception ex)
			{
				Log.LogError((object)("Failed to register RPCs: " + ex.Message));
			}
		}

		internal void OnClientAFKUpdate(ZRpc rpc, bool isAFK)
		{
			try
			{
				ZNetPeer val = ((IEnumerable<ZNetPeer>)ZNet.instance.GetPeers()).FirstOrDefault((Func<ZNetPeer, bool>)((ZNetPeer p) => p.m_rpc == rpc));
				if (val == null)
				{
					if (DebugMode.Value)
					{
						Log.LogWarning((object)"Could not find peer for AFK update RPC");
					}
					return;
				}
				long uid = val.m_uid;
				if (DebugMode.Value)
				{
					Log.LogInfo((object)"=== AFK UPDATE RECEIVED (LEGACY) ===");
					Log.LogInfo((object)$"Peer UID: {uid}");
					Log.LogInfo((object)$"AFK State: {isAFK}");
					Log.LogInfo((object)("Socket Type: " + (((object)val.m_socket)?.GetType().Name ?? "null")));
					if (uid == 0L)
					{
						if (((object)val.m_socket)?.GetType().Name == "ZSteamSocket")
						{
							Log.LogError((object)"CRITICAL: Received AFK update for Steam connection with UID 0! This indicates the UID migration failed.");
						}
						else
						{
							Log.LogInfo((object)"AFK update for UID 0 on non-Steam connection (this might be expected for crossplay)");
						}
					}
				}
				UpdatePlayerAFKState(uid, isAFK);
				if (LogAFKStateChanges.Value || DebugMode.Value)
				{
					string arg = GetPlayerName(uid) ?? $"Player{uid}";
					Log.LogInfo((object)string.Format("{0} (UID: {1}) is now {2}", arg, uid, isAFK ? "AFK" : "active"));
				}
			}
			catch (Exception ex)
			{
				Log.LogError((object)("Error handling client AFK update: " + ex.Message));
			}
		}

		internal void OnClientAFKUpdateWithPosition(ZRpc rpc, bool isAFK, Vector3 playerPosition)
		{
			//IL_013c: 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_01a6: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				ZNetPeer val = ((IEnumerable<ZNetPeer>)ZNet.instance.GetPeers()).FirstOrDefault((Func<ZNetPeer, bool>)((ZNetPeer p) => p.m_rpc == rpc));
				if (val == null)
				{
					if (DebugMode.Value)
					{
						Log.LogWarning((object)"Could not find peer for AFK update with position RPC");
					}
					return;
				}
				long uid = val.m_uid;
				if (DebugMode.Value)
				{
					Log.LogInfo((object)"=== AFK UPDATE WITH POSITION RECEIVED ===");
					Log.LogInfo((object)$"Peer UID: {uid}");
					Log.LogInfo((object)$"AFK State: {isAFK}");
					Log.LogInfo((object)$"Player Position: {playerPosition}");
					Log.LogInfo((object)("Socket Type: " + (((object)val.m_socket)?.GetType().Name ?? "null")));
					if (uid == 0L)
					{
						if (((object)val.m_socket)?.GetType().Name == "ZSteamSocket")
						{
							Log.LogError((object)"CRITICAL: Received AFK update for Steam connection with UID 0! This indicates the UID migration failed.");
						}
						else
						{
							Log.LogInfo((object)"AFK update for UID 0 on non-Steam connection (this might be expected for crossplay)");
						}
					}
				}
				UpdatePlayerAFKStateWithPosition(uid, isAFK, playerPosition);
				if (LogAFKStateChanges.Value || DebugMode.Value)
				{
					string text = GetPlayerName(uid) ?? $"Player{uid}";
					Log.LogInfo((object)string.Format("{0} (UID: {1}) is now {2} at position {3}", text, uid, isAFK ? "AFK" : "active", playerPosition));
				}
			}
			catch (Exception ex)
			{
				Log.LogError((object)("Error handling client AFK update with position: " + ex.Message));
			}
		}

		private void UpdatePlayerAFKStateWithPosition(long playerID, bool isAFK, Vector3 position)
		{
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d0: Unknown result type (might be due to invalid IL or missing references)
			//IL_0085: Unknown result type (might be due to invalid IL or missing references)
			//IL_013a: Unknown result type (might be due to invalid IL or missing references)
			if (!PlayerStates.TryGetValue(playerID, out var value))
			{
				value = new PlayerAFKData();
				PlayerStates[playerID] = value;
			}
			bool isAFK2 = value.IsAFK;
			value.IsAFK = isAFK;
			value.LastUpdate = DateTime.UtcNow;
			value.IsConnected = true;
			if (RaidSystemPatches.IsValidPosition(position))
			{
				value.LastPosition = position;
				if (DebugMode.Value)
				{
					string arg = GetPlayerName(playerID) ?? $"Player{playerID}";
					Log.LogInfo((object)$"✓ Updated position for {arg}: {position}");
				}
			}
			else if (DebugMode.Value)
			{
				string arg2 = GetPlayerName(playerID) ?? $"Player{playerID}";
				Log.LogInfo((object)$"⚠ Invalid position provided for {arg2}: {position}, keeping last known: {value.LastPosition}");
			}
			if (LogAFKStateChanges.Value && isAFK2 != isAFK)
			{
				string text = GetPlayerName(playerID) ?? $"Player{playerID}";
				Log.LogInfo((object)$"Player {text} AFK state changed: {isAFK2} → {isAFK} (Position: {value.LastPosition})");
			}
		}

		private void UpdatePlayerAFKState(long playerID, bool isAFK)
		{
			//IL_0042: Unknown result type (might be due to invalid IL or missing references)
			//IL_0047: Unknown result type (might be due to invalid IL or missing references)
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			//IL_0049: Unknown result type (might be due to invalid IL or missing references)
			//IL_0056: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d8: Unknown result type (might be due to invalid IL or missing references)
			//IL_0091: Unknown result type (might be due to invalid IL or missing references)
			//IL_0142: Unknown result type (might be due to invalid IL or missing references)
			if (!PlayerStates.TryGetValue(playerID, out var value))
			{
				value = new PlayerAFKData();
				PlayerStates[playerID] = value;
			}
			bool isAFK2 = value.IsAFK;
			value.IsAFK = isAFK;
			value.LastUpdate = DateTime.UtcNow;
			value.IsConnected = true;
			Vector3 playerPositionEnhanced = GetPlayerPositionEnhanced(playerID);
			if (playerPositionEnhanced != Vector3.zero)
			{
				value.LastPosition = playerPositionEnhanced;
				if (DebugMode.Value)
				{
					string arg = GetPlayerName(playerID) ?? $"Player{playerID}";
					Log.LogInfo((object)$"✓ Updated position for {arg}: {playerPositionEnhanced}");
				}
			}
			else if (DebugMode.Value)
			{
				string arg2 = GetPlayerName(playerID) ?? $"Player{playerID}";
				Log.LogInfo((object)$"⚠ Could not get current position for {arg2}, keeping last known: {value.LastPosition}");
			}
			if (LogAFKStateChanges.Value && isAFK2 != isAFK)
			{
				string text = GetPlayerName(playerID) ?? $"Player{playerID}";
				Log.LogInfo((object)$"Player {text} AFK state changed: {isAFK2} → {isAFK} (Position: {value.LastPosition})");
			}
		}

		private static Vector3 GetPlayerPositionEnhanced(long playerID)
		{
			//IL_0178: Unknown result type (might be due to invalid IL or missing references)
			//IL_017d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0181: Unknown result type (might be due to invalid IL or missing references)
			//IL_003c: 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_009a: Unknown result type (might be due to invalid IL or missing references)
			//IL_009c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0056: Unknown result type (might be due to invalid IL or missing references)
			//IL_005b: Unknown result type (might be due to invalid IL or missing references)
			//IL_005c: Unknown result type (might be due to invalid IL or missing references)
			//IL_013b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0140: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c6: Unknown result type (might be due to invalid IL or missing references)
			//IL_0064: Unknown result type (might be due to invalid IL or missing references)
			//IL_0065: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				Player val = ((IEnumerable<Player>)Player.GetAllPlayers()).FirstOrDefault((Func<Player, bool>)((Player p) => p != null && p.GetPlayerID() == playerID));
				if (val != null)
				{
					Transform transform = ((Component)val).transform;
					if (((transform != null) ? new Vector3?(transform.position) : null).HasValue)
					{
						Vector3 position = ((Component)val).transform.position;
						if (RaidSystemPatches.IsValidPosition(position))
						{
							return position;
						}
					}
				}
				if ((Object)(object)Player.m_localPlayer != (Object)null && Player.m_localPlayer.GetPlayerID() == playerID)
				{
					Vector3 position2 = ((Component)Player.m_localPlayer).transform.position;
					if (RaidSystemPatches.IsValidPosition(position2))
					{
						if (DebugMode.Value)
						{
							Log.LogInfo((object)$"Using local player position for UID {playerID}: {position2}");
						}
						return position2;
					}
				}
				ZNet instance = ZNet.instance;
				if (instance != null && instance.IsServer() && ((IEnumerable<ZNetPeer>)ZNet.instance.GetPeers()).FirstOrDefault((Func<ZNetPeer, bool>)((ZNetPeer p) => p.m_uid == playerID)) != null && DebugMode.Value)
				{
					Log.LogInfo((object)$"Found peer for UID {playerID}, but no position available from peer data");
				}
				return Vector3.zero;
			}
			catch (Exception ex)
			{
				if (DebugMode.Value)
				{
					Log.LogError((object)$"Error getting enhanced player position for {playerID}: {ex.Message}");
				}
				return Vector3.zero;
			}
		}

		private static Vector3 GetPlayerPosition(long playerID)
		{
			//IL_006c: 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_0074: 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_0063: 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_0068: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				Player? obj = ((IEnumerable<Player>)Player.GetAllPlayers()).FirstOrDefault((Func<Player, bool>)((Player p) => p != null && p.GetPlayerID() == playerID));
				Vector3? obj2;
				if (obj == null)
				{
					obj2 = null;
				}
				else
				{
					Transform transform = ((Component)obj).transform;
					obj2 = ((transform != null) ? new Vector3?(transform.position) : null);
				}
				return (Vector3)(((??)obj2) ?? Vector3.zero);
			}
			catch
			{
				return Vector3.zero;
			}
		}

		internal static string GetPlayerName(long playerID)
		{
			try
			{
				Player? obj = ((IEnumerable<Player>)Player.GetAllPlayers()).FirstOrDefault((Func<Player, bool>)((Player p) => p != null && p.GetPlayerID() == playerID));
				return (obj != null) ? obj.GetPlayerName() : null;
			}
			catch
			{
				return null;
			}
		}

		private IEnumerator ClientAFKDetectionLoop()
		{
			yield return (object)new WaitUntil((Func<bool>)(() => (Object)(object)Player.m_localPlayer != (Object)null));
			if (DebugMode.Value)
			{
				Log.LogInfo((object)"Starting AFK detection loop");
			}
			Vector3 lastPosition = ((Component)Player.m_localPlayer).transform.position;
			DateTime lastActivity = DateTime.UtcNow;
			bool wasAFK = false;
			while (true)
			{
				Player localPlayer = Player.m_localPlayer;
				if ((Object)(object)localPlayer == (Object)null)
				{
					yield return (object)new WaitForSeconds((float)UpdateInterval.Value);
					continue;
				}
				try
				{
					Vector3 position = ((Component)localPlayer).transform.position;
					if (Vector3.Distance(position, lastPosition) > MovementThreshold.Value)
					{
						lastPosition = position;
						lastActivity = DateTime.UtcNow;
						if (DebugMode.Value)
						{
							Log.LogInfo((object)$"Player movement detected: {position}");
						}
					}
					bool flag = DateTime.UtcNow - lastActivity >= TimeSpan.FromMinutes(AFKMinutes.Value);
					if (flag != wasAFK)
					{
						SendAFKStateToServer(flag);
						wasAFK = flag;
						if (LogAFKStateChanges.Value)
						{
							Log.LogInfo((object)$"Local player AFK status changed: {flag}");
						}
					}
				}
				catch (Exception ex)
				{
					Log.LogError((object)("Error in AFK detection loop: " + ex.Message));
				}
				yield return (object)new WaitForSeconds((float)UpdateInterval.Value);
			}
		}

		private void SendAFKStateToServer(bool isAFK)
		{
			//IL_0087: Unknown result type (might be due to invalid IL or missing references)
			//IL_008c: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cc: 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_0056: 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)
			try
			{
				if ((Object)(object)ZNet.instance == (Object)null)
				{
					return;
				}
				if (ZNet.instance.IsServer())
				{
					Player localPlayer = Player.m_localPlayer;
					long num = ((localPlayer != null) ? localPlayer.GetPlayerID() : 0);
					if (num != 0L && (Object)(object)Player.m_localPlayer != (Object)null)
					{
						Vector3 position = ((Component)Player.m_localPlayer).transform.position;
						UpdatePlayerAFKStateWithPosition(num, isAFK, position);
					}
					return;
				}
				ZRpc serverRPC = ZNet.instance.GetServerRPC();
				if (serverRPC != null && (Object)(object)Player.m_localPlayer != (Object)null)
				{
					Vector3 position2 = ((Component)Player.m_localPlayer).transform.position;
					serverRPC.Invoke("NoAFKRaids_AFKUpdateWithPosition", new object[2] { isAFK, position2 });
					if (DebugMode.Value)
					{
						Log.LogInfo((object)$"Sent AFK state to server: {isAFK} at position {position2}");
					}
				}
			}
			catch (Exception ex)
			{
				Log.LogError((object)("Error sending AFK state to server: " + ex.Message));
			}
		}

		internal static void CleanupDisconnectedPlayer(long playerID)
		{
			if (PlayerStates.TryGetValue(playerID, out var value))
			{
				value.IsConnected = false;
				((MonoBehaviour)Instance).StartCoroutine(DelayedPlayerCleanup(playerID));
			}
		}

		private static IEnumerator DelayedPlayerCleanup(long playerID)
		{
			yield return (object)new WaitForSeconds(300f);
			if (PlayerStates.TryGetValue(playerID, out var value) && !value.IsConnected)
			{
				PlayerStates.Remove(playerID);
				if (DebugMode.Value)
				{
					Log.LogInfo((object)$"Cleaned up disconnected player state: {playerID}");
				}
			}
		}

		private void OnDestroy()
		{
			if (_afkDetectionCoroutine != null)
			{
				((MonoBehaviour)this).StopCoroutine(_afkDetectionCoroutine);
			}
			foreach (RaidEvaluationContext value in ActiveEvaluations.Values)
			{
				if (value.IsEvaluating && DebugMode.Value)
				{
					Log.LogInfo((object)("Cleaning up active evaluation for raid " + value.RaidName));
				}
			}
			ActiveEvaluations.Clear();
			Harmony harmony = _harmony;
			if (harmony != null)
			{
				harmony.UnpatchSelf();
			}
		}

		internal static void StartDelayedEvaluation(RandEventSystem instance)
		{
			if (!UseDelayedEvaluation.Value)
			{
				if (DebugMode.Value)
				{
					Log.LogInfo((object)"Delayed evaluation disabled, skipping");
				}
				return;
			}
			int instanceID = ((Object)instance).GetInstanceID();
			if (ActiveEvaluations.ContainsKey(instanceID))
			{
				if (DebugMode.Value)
				{
					Log.LogWarning((object)$"Evaluation already active for instance {instanceID}");
				}
				return;
			}
			RaidEvaluationContext value = new RaidEvaluationContext
			{
				Instance = instance,
				StartTime = DateTime.UtcNow,
				AttemptCount = 0,
				IsEvaluating = true,
				RaidName = "Unknown"
			};
			ActiveEvaluations[instanceID] = value;
			if (DebugMode.Value)
			{
				Log.LogInfo((object)$"Starting delayed evaluation for instance {instanceID}");
			}
			((MonoBehaviour)Instance).StartCoroutine(EvaluateRaidWithRetry(instanceID));
		}

		private static IEnumerator EvaluateRaidWithRetry(int instanceId)
		{
			if (!ActiveEvaluations.TryGetValue(instanceId, out var context))
			{
				if (DebugMode.Value)
				{
					Log.LogWarning((object)$"Evaluation context missing for instance {instanceId}");
				}
				yield break;
			}
			float[] retryDelays = new float[5] { 0.05f, 0.1f, 0.2f, 0.5f, 1f };
			for (int attempt = 0; attempt < Math.Min(retryDelays.Length, MaxPositionRetries.Value); attempt++)
			{
				yield return (object)new WaitForSeconds(retryDelays[attempt]);
				if (!ActiveEvaluations.ContainsKey(instanceId))
				{
					if (DebugMode.Value)
					{
						Log.LogInfo((object)$"Evaluation cancelled for instance {instanceId}");
					}
					yield break;
				}
				context.AttemptCount = attempt + 1;
				try
				{
					RaidEvaluationResult raidEvaluationResult = EvaluateRaidPosition(context, attempt + 1);
					if (raidEvaluationResult.Success)
					{
						if (raidEvaluationResult.ShouldBlock)
						{
							StopActiveRaid(context.Instance, raidEvaluationResult.Reason);
						}
						CleanupEvaluation(instanceId);
						yield break;
					}
					if (DebugMode.Value)
					{
						Log.LogInfo((object)$"Evaluation attempt {attempt + 1} failed for instance {instanceId}");
					}
				}
				catch (Exception ex)
				{
					Log.LogError((object)$"Error in evaluation attempt {attempt + 1}: {ex.Message}");
				}
			}
			if (DebugMode.Value)
			{
				Log.LogInfo((object)$"All retries failed for instance {instanceId}, applying fallback");
			}
			ApplyFallbackStrategy(context);
			CleanupEvaluation(instanceId);
		}

		private static void CleanupEvaluation(int instanceId)
		{
			ActiveEvaluations.Remove(instanceId);
			if (ActiveEvaluations.Count <= 10)
			{
				return;
			}
			foreach (int item in (from kvp in ActiveEvaluations
				where (DateTime.UtcNow - kvp.Value.StartTime).TotalMinutes > 5.0
				select kvp.Key).ToList())
			{
				ActiveEvaluations.Remove(item);
				if (DebugMode.Value)
				{
					Log.LogInfo((object)$"Cleaned up old evaluation: {item}");
				}
			}
		}

		private static RaidEvaluationResult EvaluateRaidPosition(RaidEvaluationContext context, int attempt)
		{
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_010d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_0072: Unknown result type (might be due to invalid IL or missing references)
			//IL_0078: Unknown result type (might be due to invalid IL or missing references)
			//IL_0064: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b3: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				RandomEvent currentRandomEvent = RaidSystemPatches.GetCurrentRandomEvent(context.Instance);
				Vector3 raidSpawnPosition = RaidSystemPatches.GetRaidSpawnPosition(context.Instance, currentRandomEvent);
				if (currentRandomEvent != null)
				{
					context.RaidName = currentRandomEvent.m_name ?? "Unknown";
				}
				if (raidSpawnPosition == Vector3.zero)
				{
					RaidEvaluationResult result = default(RaidEvaluationResult);
					result.Success = false;
					result.ShouldBlock = false;
					result.Reason = "Position not available";
					result.Position = raidSpawnPosition;
					return result;
				}
				bool flag = RaidSystemPatches.EvaluateRaidProtection(RaidSystemPatches.ClassifyRaidType(currentRandomEvent, raidSpawnPosition), raidSpawnPosition, currentRandomEvent);
				RaidEvaluationResult result2 = default(RaidEvaluationResult);
				result2.Success = true;
				result2.ShouldBlock = !flag;
				result2.Reason = (flag ? "Raid allowed - no AFK players in range" : "Raid blocked - AFK players within protection radius");
				result2.Position = raidSpawnPosition;
				return result2;
			}
			catch (Exception ex)
			{
				Log.LogError((object)("Error evaluating raid position: " + ex.Message));
				RaidEvaluationResult result2 = default(RaidEvaluationResult);
				result2.Success = false;
				result2.ShouldBlock = false;
				result2.Reason = "Evaluation error: " + ex.Message;
				result2.Position = Vector3.zero;
				return result2;
			}
		}

		private static bool StopActiveRaid(RandEventSystem instance, string reason)
		{
			return RaidSystemPatches.StopActiveRaid(instance, reason);
		}

		private static void ApplyFallbackStrategy(RaidEvaluationContext context)
		{
			try
			{
				FallbackPolicyType fallbackPolicyType = ParseFallbackPolicy(FallbackPolicy.Value);
				bool flag = false;
				switch (fallbackPolicyType)
				{
				case FallbackPolicyType.Conservative:
					flag = RaidSystemPatches.HasConnectedAFKPlayersInInternalState();
					break;
				case FallbackPolicyType.Liberal:
					flag = false;
					break;
				case FallbackPolicyType.Smart:
					flag = ApplySmartFallback(context);
					break;
				case FallbackPolicyType.PlayerBased:
					flag = ApplyPlayerBasedFallback(context);
					break;
				}
				string text = (flag ? "blocked" : "allowed");
				string text2 = $"Fallback policy ({fallbackPolicyType}): {text}";
				if (LogEvents.Value)
				{
					Log.LogInfo((object)("Raid " + text + " via fallback - " + text2));
				}
				if (flag)
				{
					StopActiveRaid(context.Instance, text2);
				}
			}
			catch (Exception ex)
			{
				Log.LogError((object)("Error in fallback strategy: " + ex.Message));
				if (RaidSystemPatches.HasConnectedAFKPlayersInInternalState())
				{
					StopActiveRaid(context.Instance, "Ultimate fallback: AFK players detected");
				}
			}
		}

		private static FallbackPolicyType ParseFallbackPolicy(string policy)
		{
			if (Enum.TryParse<FallbackPolicyType>(policy, ignoreCase: true, out var result))
			{
				return result;
			}
			return FallbackPolicyType.Conservative;
		}

		private static bool ApplySmartFallback(RaidEvaluationContext context)
		{
			try
			{
				RandomEvent currentRandomEvent = RaidSystemPatches.GetCurrentRandomEvent(context.Instance);
				if (currentRandomEvent != null)
				{
					string text = currentRandomEvent.m_name?.ToLowerInvariant() ?? "";
					if ((text.Contains("horde") || text.Contains("wolves") || text.Contains("bats")) && !ProtectGlobalRaids.Value)
					{
						return false;
					}
				}
				return RaidSystemPatches.HasConnectedAFKPlayersInInternalState();
			}
			catch (Exception ex)
			{
				if (DebugMode.Value)
				{
					Log.LogError((object)("Error in smart fallback: " + ex.Message));
				}
				return RaidSystemPatches.HasConnectedAFKPlayersInInternalState();
			}
		}

		private static bool ApplyPlayerBasedFallback(RaidEvaluationContext context)
		{
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0050: Unknown result type (might be due to invalid IL or missing references)
			//IL_0055: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				List<Vector3> connectedPlayerPositions = RaidSystemPatches.GetConnectedPlayerPositions();
				if (connectedPlayerPositions.Count == 0)
				{
					return RaidSystemPatches.HasConnectedAFKPlayersInInternalState();
				}
				foreach (Vector3 item in connectedPlayerPositions)
				{
					foreach (Player connectedAFKPlayer in RaidSystemPatches.GetConnectedAFKPlayers(Player.GetAllPlayers()))
					{
						float num = Vector3.Distance(((Component)connectedAFKPlayer).transform.position, item);
						if (num <= AFKProtectionRadius.Value)
						{
							if (DebugMode.Value)
							{
								Log.LogInfo((object)$"Player-based fallback: AFK player {connectedAFKPlayer.GetPlayerName()} within {num:F1}m of potential raid target");
							}
							return true;
						}
					}
				}
				return false;
			}
			catch (Exception ex)
			{
				if (DebugMode.Value)
				{
					Log.LogError((object)("Error in player-based fallback: " + ex.Message));
				}
				return RaidSystemPatches.HasConnectedAFKPlayersInInternalState();
			}
		}
	}
	[HarmonyPatch(typeof(ZNet))]
	internal static class ZNetPatches
	{
		private static readonly Dictionary<ZNetPeer, DateTime> PendingUIDPeers = new Dictionary<ZNetPeer, DateTime>();

		[HarmonyPostfix]
		[HarmonyPatch("OnNewConnection")]
		private static void OnNewConnection(ZNetPeer peer)
		{
			try
			{
				peer.m_rpc.Register<bool>("NoAFKRaids_AFKUpdate", (Action<ZRpc, bool>)NoAFKRaids.Instance.OnClientAFKUpdate);
				peer.m_rpc.Register<bool, Vector3>("NoAFKRaids_AFKUpdateWithPosition", (Action<ZRpc, bool, Vector3>)NoAFKRaids.Instance.OnClientAFKUpdateWithPosition);
				if (!NoAFKRaids.DebugMode.Value)
				{
					return;
				}
				NoAFKRaids.Log.LogInfo((object)"=== NEW PEER CONNECTION DEBUG ===");
				NoAFKRaids.Log.LogInfo((object)$"Peer UID: {peer.m_uid}");
				NoAFKRaids.Log.LogInfo((object)("Socket Type: " + (((object)peer.m_socket)?.GetType().Name ?? "null")));
				NoAFKRaids.Log.LogInfo((object)string.Format("Is Crossplay: {0}", ((object)peer.m_socket)?.GetType().Name.Contains("PlayFab") ?? false));
				NoAFKRaids.Log.LogInfo((object)$"Registered AFK RPCs for peer UID: {peer.m_uid}");
				if (peer.m_uid == 0L)
				{
					bool flag = ((object)peer.m_socket)?.GetType().Name == "ZSteamSocket";
					NoAFKRaids.Log.LogWarning((object)$"Peer UID is 0 - Steam connection: {flag}. Will track for UID update.");
					if (flag)
					{
						PendingUIDPeers[peer] = DateTime.UtcNow;
						NoAFKRaids.Log.LogInfo((object)"Added peer to pending UID tracking list");
					}
				}
			}
			catch (Exception ex)
			{
				NoAFKRaids.Log.LogError((object)("Error registering RPC for new connection: " + ex.Message));
			}
		}

		[HarmonyPostfix]
		[HarmonyPatch("Disconnect")]
		private static void OnPlayerDisconnect(ZNetPeer peer)
		{
			try
			{
				PendingUIDPeers.Remove(peer);
				NoAFKRaids.CleanupDisconnectedPlayer(peer.m_uid);
				if (NoAFKRaids.DebugMode.Value)
				{
					NoAFKRaids.Log.LogInfo((object)$"Player disconnected, marked for cleanup: {peer.m_uid}");
				}
			}
			catch (Exception ex)
			{
				NoAFKRaids.Log.LogError((object)("Error handling player disconnect: " + ex.Message));
			}
		}

		[HarmonyPostfix]
		[HarmonyPatch("RPC_PeerInfo")]
		private static void OnPeerInfo(ZNet __instance, ZRpc rpc, ZPackage pkg)
		{
			try
			{
				ZNetPeer val = ((IEnumerable<ZNetPeer>)__instance.GetPeers()).FirstOrDefault((Func<ZNetPeer, bool>)((ZNetPeer p) => p.m_rpc == rpc));
				if (val == null || !PendingUIDPeers.ContainsKey(val))
				{
					return;
				}
				long num = 0L;
				long uid = val.m_uid;
				if (NoAFKRaids.DebugMode.Value)
				{
					NoAFKRaids.Log.LogInfo((object)"=== PEER UID UPDATED IN RPC_PeerInfo ===");
					NoAFKRaids.Log.LogInfo((object)$"Peer UID changed: {num} → {uid}");
					NoAFKRaids.Log.LogInfo((object)("Socket Type: " + (((object)val.m_socket)?.GetType().Name ?? "null")));
				}
				if (uid != 0L && uid != num)
				{
					MigratePlayerState(num, uid);
					PendingUIDPeers.Remove(val);
					if (NoAFKRaids.DebugMode.Value)
					{
						NoAFKRaids.Log.LogInfo((object)$"Successfully migrated player state from UID {num} to {uid}");
					}
				}
			}
			catch (Exception ex)
			{
				NoAFKRaids.Log.LogError((object)("Error in RPC_PeerInfo postfix: " + ex.Message));
			}
		}

		private static void MigratePlayerState(long oldUID, long newUID)
		{
			try
			{
				if (NoAFKRaids.PlayerStates.TryGetValue(oldUID, out var value))
				{
					if (NoAFKRaids.DebugMode.Value)
					{
						NoAFKRaids.Log.LogInfo((object)$"Migrating player state: {oldUID} → {newUID}");
						NoAFKRaids.Log.LogInfo((object)$"  Old state - AFK: {value.IsAFK}, Connected: {value.IsConnected}");
					}
					NoAFKRaids.PlayerStates[newUID] = value;
					NoAFKRaids.PlayerStates.Remove(oldUID);
					if (NoAFKRaids.DebugMode.Value)
					{
						NoAFKRaids.Log.LogInfo((object)$"Player state successfully migrated from UID {oldUID} to {newUID}");
					}
				}
				else if (NoAFKRaids.DebugMode.Value)
				{
					NoAFKRaids.Log.LogInfo((object)$"No existing state found for old UID {oldUID} to migrate");
				}
			}
			catch (Exception ex)
			{
				NoAFKRaids.Log.LogError((object)$"Error migrating player state from {oldUID} to {newUID}: {ex.Message}");
			}
		}
	}
	public enum RaidType
	{
		Unknown,
		Localized,
		Global
	}
	[HarmonyPatch(typeof(RandEventSystem))]
	internal static class RaidSystemPatches
	{
		public struct DistanceResult
		{
			public float Distance { get; set; }

			public bool IsValid { get; set; }

			public string ValidationMessage { get; set; }
		}

		private static RandomEvent pendingRaidEvent;

		[HarmonyPrefix]
		[HarmonyPatch("StartRandomEvent")]
		private static bool ProximityFirstRaidProtection_Prefix(RandEventSystem __instance)
		{
			//IL_007d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0082: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e3: Unknown result type (might be due to invalid IL or missing references)
			//IL_0099: 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_00f6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c9: Unknown result type (might be due to invalid IL or missing references)
			//IL_0129: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				if (NoAFKRaids.DebugMode.Value)
				{
					NoAFKRaids.Log.LogInfo((object)"=== PROXIMITY-FIRST RAID PROTECTION (PREFIX) ===");
					ManualLogSource log = NoAFKRaids.Log;
					ZNet instance = ZNet.instance;
					log.LogInfo((object)$"IsServer: {((instance != null) ? new bool?(instance.IsServer()) : null)}");
				}
				ZNet instance2 = ZNet.instance;
				if (instance2 != null && !instance2.IsServer())
				{
					return true;
				}
				CleanupStalePlayerStates();
				RandomEvent currentRandomEvent = GetCurrentRandomEvent(__instance);
				Vector3 raidSpawnPosition = GetRaidSpawnPosition(__instance, currentRandomEvent);
				if (NoAFKRaids.DebugMode.Value)
				{
					NoAFKRaids.Log.LogInfo((object)string.Format("Raid position attempt: {0}, Event: {1}", raidSpawnPosition, currentRandomEvent?.m_name ?? "null"));
					NoAFKRaids.Log.LogInfo((object)$"Position is zero: {raidSpawnPosition == Vector3.zero}");
				}
				if (raidSpawnPosition != Vector3.zero)
				{
					bool flag = EvaluateRaidProtection(ClassifyRaidType(currentRandomEvent, raidSpawnPosition), raidSpawnPosition, currentRandomEvent);
					if (NoAFKRaids.LogEvents.Value)
					{
						string arg = (flag ? "allowed" : "blocked");
						NoAFKRaids.Log.LogInfo((object)$"Raid {arg} - proximity protection applied in PREFIX (position: {raidSpawnPosition})");
					}
					return flag;
				}
				if (NoAFKRaids.DebugMode.Value)
				{
					NoAFKRaids.Log.LogInfo((object)"Position unavailable in PREFIX, deferring to POSTFIX where raid data is reliable");
				}
				return true;
			}
			catch (Exception ex)
			{
				NoAFKRaids.Log.LogError((object)("Error in proximity-first raid protection: " + ex.Message));
				return true;
			}
		}

		[HarmonyPostfix]
		[HarmonyPatch("StartRandomEvent")]
		private static void ProximityBasedRaidProtection_Postfix(RandEventSystem __instance)
		{
			//IL_009e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a3: 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_00d4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f9: 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_0107: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				if (NoAFKRaids.DebugMode.Value)
				{
					NoAFKRaids.Log.LogInfo((object)"=== PROXIMITY-BASED RAID PROTECTION (POSTFIX) ===");
					ManualLogSource log = NoAFKRaids.Log;
					ZNet instance = ZNet.instance;
					log.LogInfo((object)$"IsServer: {((instance != null) ? new bool?(instance.IsServer()) : null)}");
					NoAFKRaids.Log.LogInfo((object)$"Delayed evaluation enabled: {NoAFKRaids.UseDelayedEvaluation.Value}");
				}
				ZNet instance2 = ZNet.instance;
				if (instance2 != null && !instance2.IsServer())
				{
					return;
				}
				CleanupStalePlayerStates();
				RandomEvent currentRandomEvent = GetCurrentRandomEvent(__instance);
				Vector3 raidSpawnPosition = GetRaidSpawnPosition(__instance, currentRandomEvent);
				RaidType raidType = ClassifyRaidType(currentRandomEvent, raidSpawnPosition);
				if (NoAFKRaids.LogRaidPositions.Value || NoAFKRaids.DebugMode.Value)
				{
					NoAFKRaids.Log.LogInfo((object)string.Format("Raid detected - Type: {0}, Position: {1}, Event: {2}", raidType, raidSpawnPosition, currentRandomEvent?.m_name ?? "Unknown"));
				}
				if (raidSpawnPosition != Vector3.zero)
				{
					if (!EvaluateRaidProtection(raidType, raidSpawnPosition, currentRandomEvent))
					{
						StopActiveRaid(__instance, "Proximity protection - AFK player within protection radius");
						if (NoAFKRaids.LogEvents.Value)
						{
							NoAFKRaids.Log.LogInfo((object)$"Raid stopped via proximity protection - AFK player within {NoAFKRaids.AFKProtectionRadius.Value}m radius");
						}
					}
					else if (NoAFKRaids.LogEvents.Value)
					{
						NoAFKRaids.Log.LogInfo((object)"Raid allowed in POSTFIX - no AFK players within protection radius");
					}
				}
				else
				{
					if (NoAFKRaids.DebugMode.Value)
					{
						NoAFKRaids.Log.LogWarning((object)"Position unavailable even in POSTFIX - this is unexpected, allowing raid to proceed");
					}
					if (NoAFKRaids.LogEvents.Value)
					{
						NoAFKRaids.Log.LogInfo((object)"Raid allowed - position detection failed completely (rare case)");
					}
				}
			}
			catch (Exception ex)
			{
				NoAFKRaids.Log.LogError((object)("Error in proximity-based raid protection postfix: " + ex.Message));
			}
		}

		private static bool EvaluateSmartFallbackWithProximity(RandEventSystem instance, RandomEvent raidEvent)
		{
			//IL_00a4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ca: 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)
			try
			{
				if (NoAFKRaids.DebugMode.Value)
				{
					NoAFKRaids.Log.LogInfo((object)"=== SMART PROXIMITY FALLBACK ===");
				}
				bool flag = HasConnectedAFKPlayersInInternalState();
				if (!flag)
				{
					if (NoAFKRaids.DebugMode.Value)
					{
						NoAFKRaids.Log.LogInfo((object)"No AFK players detected - allowing raid");
					}
					return false;
				}
				List<Vector3> connectedPlayerPositions = GetConnectedPlayerPositions();
				if (connectedPlayerPositions.Count == 0)
				{
					if (NoAFKRaids.DebugMode.Value)
					{
						NoAFKRaids.Log.LogInfo((object)"No player positions available - using conservative approach");
					}
					return flag;
				}
				List<Player> connectedAFKPlayers = GetConnectedAFKPlayers(Player.GetAllPlayers());
				if (connectedAFKPlayers.Count == 0)
				{
					return EvaluateUsingStoredAFKPositions(connectedPlayerPositions);
				}
				foreach (Vector3 item in connectedPlayerPositions)
				{
					foreach (Player item2 in connectedAFKPlayers)
					{
						float num = Vector3.Distance(((Component)item2).transform.position, item);
						if (num <= NoAFKRaids.AFKProtectionRadius.Value)
						{
							if (NoAFKRaids.DebugMode.Value)
							{
								NoAFKRaids.Log.LogInfo((object)$"Smart fallback: AFK player {item2.GetPlayerName()} within {num:F1}m of potential raid target at {item}");
							}
							return true;
						}
					}
				}
				if (raidEvent != null && IsGlobalRaid(raidEvent) && !NoAFKRaids.ProtectGlobalRaids.Value)
				{
					if (NoAFKRaids.DebugMode.Value)
					{
						NoAFKRaids.Log.LogInfo((object)"Global raid detected but global protection disabled - allowing raid");
					}
					return false;
				}
				if (NoAFKRaids.DebugMode.Value)
				{
					NoAFKRaids.Log.LogInfo((object)"Smart fallback: No AFK players within protection radius of any potential raid targets");
				}
				return false;
			}
			catch (Exception ex)
			{
				NoAFKRaids.Log.LogError((object)("Error in smart proximity fallback: " + ex.Message));
				return HasConnectedAFKPlayersInInternalState();
			}
		}

		private static bool EvaluateUsingStoredAFKPositions(List<Vector3> playerPositions)
		{
			//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_0063: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: Unknown result type (might be due to invalid IL or missing references)
			//IL_0070: Unknown result type (might be due to invalid IL or missing references)
			//IL_0075: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				foreach (KeyValuePair<long, NoAFKRaids.PlayerAFKData> playerState in NoAFKRaids.PlayerStates)
				{
					if (!playerState.Value.IsAFK || !playerState.Value.IsConnected || !(playerState.Value.LastPosition != Vector3.zero))
					{
						continue;
					}
					foreach (Vector3 playerPosition in playerPositions)
					{
						float num = Vector3.Distance(playerState.Value.LastPosition, playerPosition);
						if (num <= NoAFKRaids.AFKProtectionRadius.Value)
						{
							if (NoAFKRaids.DebugMode.Value)
							{
								string arg = NoAFKRaids.GetPlayerName(playerState.Key) ?? $"Player{playerState.Key}";
								NoAFKRaids.Log.LogInfo((object)$"Stored position check: AFK player {arg} within {num:F1}m of potential raid target");
							}
							return true;
						}
					}
				}
				if (NoAFKRaids.DebugMode.Value)
				{
					NoAFKRaids.Log.LogInfo((object)"Stored position check: No AFK players within protection radius");
				}
				return false;
			}
			catch (Exception ex)
			{
				NoAFKRaids.Log.LogError((object)("Error evaluating stored AFK positions: " + ex.Message));
				return HasConnectedAFKPlayersInInternalState();
			}
		}

		private static bool IsGlobalRaid(RandomEvent raidEvent)
		{
			if (raidEvent == null || raidEvent.m_name == null)
			{
				return false;
			}
			string text = raidEvent.m_name.ToLowerInvariant();
			if (!text.Contains("horde") && !text.Contains("wolves"))
			{
				return text.Contains("bats");
			}
			return true;
		}

		internal static bool StopActiveRaid(RandEventSystem instance, string reason)
		{
			try
			{
				if (NoAFKRaids.LogEvents.Value)
				{
					NoAFKRaids.Log.LogInfo((object)("Stopping active raid: " + reason));
				}
				MethodInfo method = typeof(RandEventSystem).GetMethod("ResetRandomEvent", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
				if (method != null)
				{
					method.Invoke(instance, null);
					if (NoAFKRaids.DebugMode.Value)
					{
						NoAFKRaids.Log.LogInfo((object)"Successfully stopped active raid via ResetRandomEvent");
					}
					return true;
				}
				FieldInfo field = typeof(RandEventSystem).GetField("m_activeEvent", BindingFlags.Instance | BindingFlags.NonPublic);
				if (field != null)
				{
					field.SetValue(instance, null);
					if (NoAFKRaids.DebugMode.Value)
					{
						NoAFKRaids.Log.LogInfo((object)"Cleared active event field");
					}
					return true;
				}
				NoAFKRaids.Log.LogWarning((object)"Could not find method to stop raid");
				return false;
			}
			catch (Exception ex)
			{
				NoAFKRaids.Log.LogError((object)("Error stopping active raid: " + ex.Message));
				return false;
			}
		}

		private static void CleanupStalePlayerStates()
		{
			if (NoAFKRaids.DebugMode.Value)
			{
				NoAFKRaids.Log.LogInfo((object)$"Current player states: {NoAFKRaids.PlayerStates.Count}");
				foreach (KeyValuePair<long, NoAFKRaids.PlayerAFKData> playerState in NoAFKRaids.PlayerStates)
				{
					string text = NoAFKRaids.GetPlayerName(playerState.Key) ?? $"Player{playerState.Key}";
					TimeSpan timeSpan = DateTime.UtcNow - playerState.Value.LastUpdate;
					NoAFKRaids.Log.LogInfo((object)$"  {text} (UID: {playerState.Key}): AFK={playerState.Value.IsAFK}, Connected={playerState.Value.IsConnected}, LastUpdate={timeSpan.TotalMinutes:F1}min ago");
				}
			}
			foreach (long item in (from kvp in NoAFKRaids.PlayerStates
				where !kvp.Value.IsConnected && DateTime.UtcNow - kvp.Value.LastUpdate > TimeSpan.FromMinutes(5.0)
				select kvp.Key).ToList())
			{
				if (NoAFKRaids.DebugMode.Value)
				{
					NoAFKRaids.Log.LogInfo((object)$"Removing stale disconnected player state: {item}");
				}
				NoAFKRaids.PlayerStates.Remove(item);
			}
		}

		internal static Vector3 GetRaidSpawnPosition(RandEventSystem instance, RandomEvent raidEvent)
		{
			//IL_0174: Unknown result type (might be due to invalid IL or missing references)
			//IL_0179: Unknown result type (might be due to invalid IL or missing references)
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			//IL_017c: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ba: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bf: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c0: 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_0080: Unknown result type (might be due to invalid IL or missing references)
			//IL_0085: Unknown result type (might be due to invalid IL or missing references)
			//IL_006b: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ee: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ef: Unknown result type (might be due to invalid IL or missing references)
			//IL_00de: Unknown result type (might be due to invalid IL or missing references)
			//IL_012b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0130: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				if (NoAFKRaids.DebugMode.Value)
				{
					NoAFKRaids.Log.LogInfo((object)"=== ENHANCED RAID POSITION DETECTION ===");
					NoAFKRaids.Log.LogInfo((object)("Raid Event: " + (raidEvent?.m_name ?? "null")));
				}
				if (raidEvent != null && IsValidPosition(raidEvent.m_pos))
				{
					if (NoAFKRaids.DebugMode.Value)
					{
						NoAFKRaids.Log.LogInfo((object)$"✓ Valid raid position from event: {raidEvent.m_pos}");
					}
					return raidEvent.m_pos;
				}
				if (raidEvent != null && NoAFKRaids.DebugMode.Value)
				{
					NoAFKRaids.Log.LogInfo((object)$"✗ Invalid raid position from event: {raidEvent.m_pos}");
				}
				Vector3 val = TryGetPositionFromEventSystemEnhanced(instance);
				if (IsValidPosition(val))
				{
					if (NoAFKRaids.DebugMode.Value)
					{
						NoAFKRaids.Log.LogInfo((object)$"✓ Valid raid position from enhanced system detection: {val}");
					}
					return val;
				}
				if (NoAFKRaids.DebugMode.Value)
				{
					NoAFKRaids.Log.LogInfo((object)"✗ No valid position from enhanced system detection");
				}
				if (NoAFKRaids.DebugMode.Value)
				{
					NoAFKRaids.Log.LogInfo((object)"✗ No valid raid position found - will use configured fallback policy");
				}
				return Vector3.zero;
			}
			catch (Exception ex)
			{
				NoAFKRaids.Log.LogError((object)("Error in enhanced raid position detection: " + ex.Message));
				if (NoAFKRaids.DebugMode.Value)
				{
					NoAFKRaids.Log.LogError((object)("Stack trace: " + ex.StackTrace));
				}
				return Vector3.zero;
			}
		}

		internal static bool IsValidPosition(Vector3 position)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			//IL_0040: Unknown result type (might be due to invalid IL or missing references)
			//IL_006c: Unknown result type (might be due to invalid IL or missing references)
			if (position == Vector3.zero)
			{
				return false;
			}
			int num;
			if (Math.Abs(position.x) <= 10500f && Math.Abs(position.z) <= 10500f && position.y >= -200f)
			{
				num = ((position.y <= 1500f) ? 1 : 0);
				if (num != 0)
				{
					goto IL_007c;
				}
			}
			else
			{
				num = 0;
			}
			if (NoAFKRaids.DebugMode.Value)
			{
				NoAFKRaids.Log.LogWarning((object)$"Position validation failed: {position} (out of Valheim world bounds)");
			}
			goto IL_007c;
			IL_007c:
			return (byte)num != 0;
		}

		private static Vector3 TryGetPositionFromEventSystemEnhanced(RandEventSystem instance)
		{
			//IL_01fc: Unknown result type (might be due to invalid IL or missing references)
			//IL_0201: 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_00c4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ca: Unknown result type (might be due to invalid IL or missing references)
			//IL_01cf: Unknown result type (might be due to invalid IL or missing references)
			//IL_0104: Unknown result type (might be due to invalid IL or missing references)
			//IL_017c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0181: Unknown result type (might be due to invalid IL or missing references)
			//IL_0183: Unknown result type (might be due to invalid IL or missing references)
			//IL_013b: Unknown result type (might be due to invalid IL or missing references)
			//IL_013d: Unknown result type (might be due to invalid IL or missing references)
			//IL_012a: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ba: Unknown result type (might be due to invalid IL or missing references)
			//IL_01bc: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a9: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				if (NoAFKRaids.DebugMode.Value)
				{
					NoAFKRaids.Log.LogInfo((object)"Scanning RandEventSystem fields for position data...");
				}
				FieldInfo[] fields = typeof(RandEventSystem).GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
				string[] source = new string[6] { "pos", "position", "spawn", "target", "center", "location" };
				FieldInfo[] array = fields;
				foreach (FieldInfo fieldInfo in array)
				{
					if (!(fieldInfo.FieldType == typeof(Vector3)))
					{
						continue;
					}
					string fieldNameLower = fieldInfo.Name.ToLowerInvariant();
					bool flag = source.Any((string name) => fieldNameLower.Contains(name));
					Vector3 val = (Vector3)fieldInfo.GetValue(instance);
					if (NoAFKRaids.DebugMode.Value)
					{
						NoAFKRaids.Log.LogInfo((object)$"  Field '{fieldInfo.Name}': {val} (possible position: {flag})");
					}
					if (flag && IsValidPosition(val))
					{
						if (NoAFKRaids.DebugMode.Value)
						{
							NoAFKRaids.Log.LogInfo((object)$"✓ Found valid position in field '{fieldInfo.Name}': {val}");
						}
						return val;
					}
				}
				array = fields;
				foreach (FieldInfo fieldInfo2 in array)
				{
					if (!(fieldInfo2.FieldType == typeof(Vector3)))
					{
						continue;
					}
					Vector3 val2 = (Vector3)fieldInfo2.GetValue(instance);
					if (IsValidPosition(val2))
					{
						if (NoAFKRaids.DebugMode.Value)
						{
							NoAFKRaids.Log.LogInfo((object)$"✓ Found valid fallback position in field '{fieldInfo2.Name}': {val2}");
						}
						return val2;
					}
				}
				return Vector3.zero;
			}
			catch (Exception ex)
			{
				if (NoAFKRaids.DebugMode.Value)
				{
					NoAFKRaids.Log.LogError((object)("Error in enhanced field scanning: " + ex.Message));
				}
				return Vector3.zero;
			}
		}

		private static Vector3 TryGetRaidTargetPosition(RandEventSystem instance, RandomEvent raidEvent)
		{
			//IL_011b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0120: Unknown result type (might be due to invalid IL or missing references)
			//IL_0123: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ea: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ef: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b7: 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_00e5: 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_00d4: Unknown result type (might be due to invalid IL or missing references)
			//IL_009f: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a4: Unknown result type (might be due to invalid IL or missing references)
			//IL_0085: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				List<Player> list = (from p in Player.GetAllPlayers()
					where (Object)(object)p != (Object)null && !IsPlayerAFK(p.GetPlayerID())
					select p).ToList();
				if (list.Count > 0)
				{
					Player val = list.OrderBy((Player p) => Vector3.Distance(((Component)p).transform.position, Vector3.zero)).First();
					if (NoAFKRaids.DebugMode.Value)
					{
						NoAFKRaids.Log.LogInfo((object)$"Target-based position: Using active player {val.GetPlayerName()} at {((Component)val).transform.position}");
					}
					return ((Component)val).transform.position;
				}
				List<Vector3> connectedPlayerPositions = GetConnectedPlayerPositions();
				if (connectedPlayerPositions.Count > 0)
				{
					Vector3 centralPosition = GetCentralPosition(connectedPlayerPositions);
					if (NoAFKRaids.DebugMode.Value)
					{
						NoAFKRaids.Log.LogInfo((object)$"Target-based position: Using central position of all players: {centralPosition}");
					}
					return centralPosition;
				}
				return Vector3.zero;
			}
			catch (Exception ex)
			{
				if (NoAFKRaids.DebugMode.Value)
				{
					NoAFKRaids.Log.LogError((object)("Error in target-based position detection: " + ex.Message));
				}
				return Vector3.zero;
			}
		}

		private static List<Vector3> GetConnectedPlayerPositionsEnhanced()
		{
			//IL_0057: Unknown result type (might be due to invalid IL or missing references)
			//IL_0072: Unknown result type (might be due to invalid IL or missing references)
			//IL_0077: Unknown result type (might be due to invalid IL or missing references)
			//IL_0079: 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_00d9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00aa: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b7: Unknown result type (might be due to invalid IL or missing references)
			//IL_0203: Unknown result type (might be due to invalid IL or missing references)
			List<Vector3> list = new List<Vector3>();
			try
			{
				if (NoAFKRaids.DebugMode.Value)
				{
					NoAFKRaids.Log.LogInfo((object)"Enhanced player position detection...");
				}
				int num = 0;
				foreach (Player allPlayer in Player.GetAllPlayers())
				{
					if (allPlayer == null)
					{
						continue;
					}
					Transform transform = ((Component)allPlayer).transform;
					if (!((transform != null) ? new Vector3?(transform.position) : null).HasValue)
					{
						continue;
					}
					Vector3 position = ((Component)allPlayer).transform.position;
					if (IsValidPosition(position))
					{
						list.Add(position);
						num++;
						if (NoAFKRaids.DebugMode.Value)
						{
							NoAFKRaids.Log.LogInfo((object)$"  Player {allPlayer.GetPlayerName()}: {position} ✓");
						}
					}
					else if (NoAFKRaids.DebugMode.Value)
					{
						NoAFKRaids.Log.LogInfo((object)$"  Player {allPlayer.GetPlayerName()}: {position} ✗ (invalid)");
					}
				}
				if (NoAFKRaids.DebugMode.Value)
				{
					NoAFKRaids.Log.LogInfo((object)$"Found {num} valid player positions via GetAllPlayers()");
				}
				if (list.Count == 0 && (Object)(object)ZNet.instance != (Object)null)
				{
					if (NoAFKRaids.DebugMode.Value)
					{
						NoAFKRaids.Log.LogInfo((object)"Falling back to ZNet peer positions...");
					}
					foreach (ZNetPeer peer in ZNet.instance.GetPeers())
					{
						if (peer != null && NoAFKRaids.PlayerStates.TryGetValue(peer.m_uid, out var value) && value.IsConnected && IsValidPosition(value.LastPosition))
						{
							list.Add(value.LastPosition);
							if (NoAFKRaids.DebugMode.Value)
							{
								string arg = NoAFKRaids.GetPlayerName(peer.m_uid) ?? $"Player{peer.m_uid}";
								NoAFKRaids.Log.LogInfo((object)$"  Stored position for {arg}: {value.LastPosition} ✓");
							}
						}
					}
				}
			}
			catch (Exception ex)
			{
				NoAFKRaids.Log.LogError((object)("Error in enhanced player position detection: " + ex.Message));
			}
			return list;
		}

		private static bool IsPlayerAFK(long playerID)
		{
			if (NoAFKRaids.PlayerStates.TryGetValue(playerID, out var value) && value.IsAFK)
			{
				return value.IsConnected;
			}
			return false;
		}

		private static Vector3 GetOptimalPlayerPosition(List<Vector3> positions)
		{
			//IL_0008: 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_0044: Unknown result type (might be due to invalid IL or missing references)
			if (positions.Count == 0)
			{
				return Vector3.zero;
			}
			if (positions.Count == 1)
			{
				return positions[0];
			}
			return positions.OrderBy((Vector3 pos) => Vector3.Distance(pos, Vector3.zero)).First();
		}

		private static Vector3 GetCentralPosition(List<Vector3> positions)
		{
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: 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_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_0036: Unknown result type (might be due to invalid IL or missing references)
			//IL_0037: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0057: 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)
			if (positions.Count == 0)
			{
				return Vector3.zero;
			}
			if (positions.Count == 1)
			{
				return positions[0];
			}
			Vector3 val = Vector3.zero;
			foreach (Vector3 position in positions)
			{
				val += position;
			}
			return val / (float)positions.Count;
		}

		private static void LogPlayerPositions(List<Vector3> positions)
		{
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: 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)
			if (NoAFKRaids.DebugMode.Value)
			{
				NoAFKRaids.Log.LogInfo((object)"=== PLAYER POSITION DETAILS ===");
				for (int i = 0; i < positions.Count; i++)
				{
					Vector3 val = positions[i];
					float num = Vector3.Distance(val, Vector3.zero);
					NoAFKRaids.Log.LogInfo((object)$"  Player {i + 1}: {val} (distance from center: {num:F1}m)");
				}
			}
		}

		private static DistanceResult CalculateDistanceWithValidation(Vector3 pos1, Vector3 pos2, string entity1Name, string entity2Name)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0086: 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_006f: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				if (!IsValidPosition(pos1))
				{
					DistanceResult result = default(DistanceResult);
					result.Distance = float.MaxValue;
					result.IsValid = false;
					result.ValidationMessage = $"Invalid position for {entity1Name}: {pos1}";
					return result;
				}
				DistanceResult result2;
				if (!IsValidPosition(pos2))
				{
					result2 = default(DistanceResult);
					result2.Distance = float.MaxValue;
					result2.IsValid = false;
					result2.ValidationMessage = $"Invalid position for {entity2Name}: {pos2}";
					return result2;
				}
				float num = Vector3.Distance(pos1, pos2);
				if (float.IsNaN(num) || float.IsInfinity(num) || num < 0f)
				{
					result2 = default(DistanceResult);
					result2.Distance = float.MaxValue;
					result2.IsValid = false;
					result2.ValidationMessage = $"Invalid distance calculation result: {num}";
					return result2;
				}
				if (num > 30000f)
				{
					result2 = default(DistanceResult);
					result2.Distance = num;
					result2.IsValid = false;
					result2.ValidationMessage = $"Distance {num:F1}m exceeds maximum possible world distance";
					return result2;
				}
				if (NoAFKRaids.DebugMode.Value)
				{
					NoAFKRaids.Log.LogInfo((object)$"\ud83d\udccf Distance calculated: {entity1Name} to {entity2Name} = {num:F1}m");
				}
				result2 = default(DistanceResult);
				result2.Distance = num;
				result2.IsValid = true;
				result2.ValidationMessage = "Valid distance calculation";
				return result2;
			}
			catch (Exception ex)
			{
				DistanceResult result2 = default(DistanceResult);
				result2.Distance = float.MaxValue;
				result2.IsValid = false;
				result2.ValidationMessage = "Exception in distance calculation: " + ex.Message;
				return result2;
			}
		}

		private static void LogCoordinateDetails(Vector3 afkPos, Vector3 raidPos, float distance)
		{
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_003c: Unknown result type (might be due to invalid IL or missing references)
			//IL_005b: 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_0071: Unknown result type (might be due to invalid IL or missing references)
			//IL_0086: 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_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_0098: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ae: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e4: Unknown result type (might be due to invalid IL or missing references)
			//IL_013e: Unknown result type (might be due to invalid IL or missing references)
			//IL_013f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0186: Unknown result type (might be due to invalid IL or missing references)
			//IL_018e: Unknown result type (might be due to invalid IL or missing references)
			if (NoAFKRaids.DebugMode.Value)
			{
				NoAFKRaids.Log.LogInfo((object)"=== COORDINATE SYSTEM DEBUG ===");
				NoAFKRaids.Log.LogInfo((object)$"AFK Player Position: X={afkPos.x:F2}, Y={afkPos.y:F2}, Z={afkPos.z:F2}");
				NoAFKRaids.Log.LogInfo((object)$"Raid Position: X={raidPos.x:F2}, Y={raidPos.y:F2}, Z={raidPos.z:F2}");
				Vector3 val = raidPos - afkPos;
				NoAFKRaids.Log.LogInfo((object)$"Position Difference: ΔX={val.x:F2}, ΔY={val.y:F2}, ΔZ={val.z:F2}");
				float num = Mathf.Sqrt(val.x * val.x + val.z * val.z);
				float num2 = Mathf.Abs(val.y);
				NoAFKRaids.Log.LogInfo((object)$"Horizontal Distance (XZ plane): {num:F2}m");
				NoAFKRaids.Log.LogInfo((object)$"Vertical Distance (Y axis): {num2:F2}m");
				NoAFKRaids.Log.LogInfo((object)$"3D Euclidean Distance: {distance:F2}m");
				float num3 = Vector3.Distance(afkPos, raidPos);
				if (Math.Abs(distance - num3) > 0.01f)
				{
					NoAFKRaids.Log.LogWarning((object)$"Distance calculation mismatch! Provided: {distance:F2}m, Recalculated: {num3:F2}m");
				}
				else
				{
					NoAFKRaids.Log.LogInfo((object)"✓ Distance calculation verified");
				}
				bool flag = IsValidPosition(afkPos);
				bool flag2 = IsValidPosition(raidPos);
				NoAFKRaids.Log.LogInfo((object)$"Position Validation - AFK: {flag}, Raid: {flag2}");
			}
		}

		private static void ValidateDistanceUnits(float distance, float threshold, string context)
		{
			if (NoAFKRaids.DebugMode.Value)
			{
				NoAFKRaids.Log.LogInfo((object)("=== DISTANCE UNIT VALIDATION (" + context + ") ==="));
				NoAFKRaids.Log.LogInfo((object)$"Distance: {distance:F2}m (meters)");
				NoAFKRaids.Log.LogInfo((object)$"Threshold: {threshold:F2}m (meters)");
				NoAFKRaids.Log.LogInfo((object)$"Within threshold: {distance <= threshold}");
				if (distance <= 50f)
				{
					NoAFKRaids.Log.LogInfo((object)"Reference: Very close (within base building range)");
				}
				else if (distance <= 200f)
				{
					NoAFKRaids.Log.LogInfo((object)"Reference: Close (default protection radius)");
				}
				else if (distance <= 500f)
				{
					NoAFKRaids.Log.LogInfo((object)"Reference: Medium distance (large base range)");
				}
				else if (distance <= 1000f)
				{
					NoAFKRaids.Log.LogInfo((object)"Reference: Far (different biomes)");
				}
				else if (distance <= 5000f)
				{
					NoAFKRaids.Log.LogInfo((object)"Reference: Very far (across multiple biomes)");
				}
				else
				{
					NoAFKRaids.Log.LogInfo((object)"Reference: Extremely far (cross-world distance)");
				}
			}
		}

		private static Vector3 TryGetPositionFromEventSystem(RandEventSystem instance)
		{
			//IL_00d5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00da: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a8: 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_0052: Unknown result type (might be due to invalid IL or missing references)
			//IL_0057: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_0091: Unknown result type (might be due to invalid IL or missing references)
			//IL_0092: Unknown result type (might be due to invalid IL or missing references)
			//IL_0081: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				FieldInfo[] fields = typeof(RandEventSystem).GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
				foreach (FieldInfo fieldInfo in fields)
				{
					if (!(fieldInfo.FieldType == typeof(Vector3)) || !fieldInfo.Name.ToLowerInvariant().Contains("pos"))
					{
						continue;
					}
					Vector3 val = (Vector3)fieldInfo.GetValue(instance);
					if (val != Vector3.zero)
					{
						if (NoAFKRaids.DebugMode.Value)
						{
							NoAFKRaids.Log.LogInfo((object)$"Found position in field '{fieldInfo.Name}': {val}");
						}
						return val;
					}
				}
				return Vector3.zero;
			}
			catch (Exception ex)
			{
				if (NoAFKRaids.DebugMode.Value)
				{
					NoAFKRaids.Log.LogError((object)("Error accessing event system fields: " + ex.Message));
				}
				return Vector3.zero;
			}
		}

		internal static List<Vector3> GetConnectedPlayerPositions()
		{
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ab: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bf: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ed: Unknown result type (might be due to invalid IL or missing references)
			List<Vector3> list = new List<Vector3>();
			try
			{
				foreach (Player allPlayer in Player.GetAllPlayers())
				{
					if ((Object)(object)allPlayer != (Object)null)
					{
						list.Add(((Component)allPlayer).transform.position);
					}
				}
				if (list.Count == 0 && (Object)(object)ZNet.instance != (Object)null)
				{
					foreach (ZNetPeer peer in ZNet.instance.GetPeers())
					{
						if (peer != null && NoAFKRaids.PlayerStates.TryGetValue(peer.m_uid, out var value) && value.IsConnected && value.LastPosition != Vector3.zero)
						{
							list.Add(value.LastPosition);
							if (NoAFKRaids.DebugMode.Value)
							{
								NoAFKRaids.Log.LogInfo((object)$"Using stored position for peer {peer.m_uid}: {value.LastPosition}");
							}
						}
					}
				}
			}
			catch (Exception ex)
			{
				NoAFKRaids.Log.LogError((object)("Error getting connected player positions: " + ex.Message));
			}
			return list;
		}

		internal static RaidType ClassifyRaidType(RandomEvent raidEvent, Vector3 raidPosition)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				if (raidPosition != Vector3.zero)
				{
					return RaidType.Localized;
				}
				if (raidEvent != null)
				{
					string text = raidEvent.m_name?.ToLowerInvariant();
					if (!string.IsNullOrEmpty(text) && (text.Contains("horde") || text.Contains("wolves") || text.Contains("bats")))
					{
						return RaidType.Global;
					}
				}
				return RaidType.Localized;
			}
			catch (Exception ex)
			{
				NoAFKRaids.Log.LogError((object)("Error classifying raid type: " + ex.Message));
				return RaidType.Unknown;
			}
		}

		internal static bool EvaluateRaidProtection(RaidType raidType, Vector3 raidPosition, RandomEvent raidEvent)
		{
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_008f: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cc: 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)
			try
			{
				if (NoAFKRaids.DebugMode.Value)
				{
					NoAFKRaids.Log.LogInfo((object)"=== EVALUATING RAID PROTECTION ===");
					NoAFKRaids.Log.LogInfo((object)$"Raid Type: {raidType}, Position: {raidPosition}");
				}
				List<Player> allPlayers = Player.GetAllPlayers();
				List<Player> connectedAFKPlayers = GetConnectedAFKPlayers(allPlayers);
				if (NoAFKRaids.DebugMode.Value)
				{
					NoAFKRaids.Log.LogInfo((object)$"Total players: {allPlayers.Count}, AFK players: {connectedAFKPlayers.Count}");
				}
				if (allPlayers.Count == 0 && connectedAFKPlayers.Count == 0)
				{
					return EvaluateUsingInternalAFKState(raidType, raidPosition);
				}
				if (connectedAFKPlayers.Count == 0)
				{
					if (NoAFKRaids.LogEvents.Value)
					{
						NoAFKRaids.Log.LogInfo((object)"Raid allowed - no AFK players detected via Player.GetAllPlayers()");
					}
					return true;
				}
				switch (raidType)
				{
				case RaidType.Localized:
					return EvaluateLocalizedRaidProtection(raidPosition, connectedAFKPlayers);
				case RaidType.Global:
					return EvaluateGlobalRaidProtection(connectedAFKPlayers);
				default:
					if (NoAFKRaids.DebugMode.Value)
					{
						NoAFKRaids.Log.LogInfo((object)"Unknown raid type - using localized protection logic");
					}
					return EvaluateLocalizedRaidProtection(raidPosition, connectedAFKPlayers);
				}
			}
			catch (Exception ex)
			{
				NoAFKRaids.Log.LogError((object)("Error evaluating raid protection: " + ex.Message));
				return true;
			}
		}

		private static bool EvaluateUsingInternalAFKState(RaidType raidType, Vector3 raidPosition)
		{
			//IL_005c: 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_00a4: Unknown result type (might be due to invalid IL or missing references)
			//IL_0129: 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_0137: 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)
			try
			{
				if (NoAFKRaids.DebugMode.Value)
				{
					NoAFKRaids.Log.LogInfo((object)"Player.GetAllPlayers() returned empty - using internal state for evaluation");
				}
				List<(long, Vector3, string)> list = new List<(long, Vector3, string)>();
				foreach (KeyValuePair<long, NoAFKRaids.PlayerAFKData> playerState in NoAFKRaids.PlayerStates)
				{
					if (playerState.Value.IsAFK && playerState.Value.IsConnected && playerState.Value.LastPosition != Vector3.zero)
					{
						string item = NoAFKRaids.GetPlayerName(playerState.Key) ?? $"Player{playerState.Key}";
						list.Add((playerState.Key, playerState.Value.LastPosition, item));
					}
				}
				if (list.Count == 0)
				{
					if (NoAFKRaids.LogEvents.Value)
					{
						NoAFKRaids.Log.LogInfo((object)"Raid allowed - no AFK players with valid positions found in internal state");
					}
					return true;
				}
				float num = ((raidType == RaidType.Global) ? NoAFKRaids.GlobalRaidAFKRadius.Value : NoAFKRaids.AFKProtectionRadius.Value);
				foreach (var item4 in list)
				{
					Vector3 item2 = item4.Item2;
					string item3 = item4.Item3;
					float num2 = Vector3.Distance(item2, raidPosition);
					if (num2 <= num)
					{
						if (NoAFKRaids.LogEvents.Value)
						{
							NoAFKRaids.Log.LogInfo((object)$"Raid blocked - AFK player {item3} within {num2:F1}m of raid (internal state check)");
						}
						return false;
					}
					if (NoAFKRaids.DebugMode.Value)
					{
						NoAFKRaids.Log.LogInfo((object)$"AFK player {item3} is {num2:F1}m from raid (outside protection radius)");
					}
				}
				if (NoAFKRaids.LogEvents.Value)
				{
					NoAFKRaids.Log.LogInfo((object)$"Raid allowed - no AFK players within {num}m protection radius (internal state check)");
				}
				return true;
			}
			catch (Exception ex)
			{
				NoAFKRaids.Log.LogError((object)("Error evaluating using internal AFK state: " + ex.Message));
				return true;
			}
		}

		internal static List<Player> GetConnectedAFKPlayers(List<Player> allPlayers)
		{
			List<Player> list = new List<Player>();
			foreach (Player allPlayer in allPlayers)
			{
				if (!((Object)(object)allPlayer == (Object)null))
				{
					long playerID = allPlayer.GetPlayerID();
					if (NoAFKRaids.PlayerStates.TryGetValue(playerID, out var value) && value.IsAFK && value.IsConnected)
					{
						list.Add(allPlayer);
					}
				}
			}
			return list;
		}

		internal static bool HasConnectedAFKPlayersInInternalState()
		{
			foreach (KeyValuePair<long, NoAFKRaids.PlayerAFKData> playerState in NoAFKRaids.PlayerStates)
			{
				if (playerState.Value.IsAFK && playerState.Value.IsConnected)
				{
					return true;
				}
			}
			return false;
		}

		private static bool EvaluateLocalizedRaidProtection(Vector3 raidPosition, List<Player> afkPlayers)
		{
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0083: 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)
			float value = NoAFKRaids.AFKProtectionRadius.Value;
			foreach (Player afkPlayer in afkPlayers)
			{
				float num = Vector3.Distance(((Component)afkPlayer).transform.position, raidPosition);
				if (num <= value)
				{
					if (NoAFKRaids.LogEvents.Value)
					{
						NoAFKRaids.Log.LogInfo((object)$"Localized raid blocked - AFK player {afkPlayer.GetPlayerName()} within {num:F1}m of raid (protection radius: {value}m)");
					}
					if (NoAFKRaids.ShowProtectionRadius.Value)
					{
						NoAFKRaids.Log.LogInfo((object)$"Protection details - AFK player pos: {((Component)afkPlayer).transform.position}, Raid pos: {raidPosition}, Distance: {num:F1}m");
					}
					return false;
				}
				if (NoAFKRaids.DebugMode.Value)
				{
					NoAFKRaids.Log.LogInfo((object)$"AFK player {afkPlayer.GetPlayerName()} is {num:F1}m from raid (outside protection radius of {value}m)");
				}
			}
			if (NoAFKRaids.LogEvents.Value)
			{
				NoAFKRaids.Log.LogInfo((object)$"Localized raid allowed - no AFK players within {value}m protection radius");
			}
			return true;
		}

		private static bool EvaluateGlobalRaidProtection(List<Player> afkPlayers)
		{
			if (!NoAFKRaids.ProtectGlobalRaids.Value)
			{
				if (NoAFKRaids.LogEvents.Value)
				{
					NoAFKRaids.Log.LogInfo((object)"Global raid allowed - global raid protection disabled (ProtectGlobalRaids=false)");
				}
				return true;
			}
			if (afkPlayers.Count > 0)
			{
				if (NoAFKRaids.LogEvents.Value)
				{
					string text = string.Join(", ", afkPlayers.Select((Player p) => p.GetPlayerName()));
					NoAFKRaids.Log.LogInfo((object)("Global raid blocked - AFK players detected: " + text));
				}
				return false;
			}
			if (NoAFKRaids.LogEvents.Value)
			{
				NoAFKRaids.Log.LogInfo((object)"Global raid allowed - no AFK players detected");
			}
			return true;
		}

		internal static RandomEvent GetCurrentRandomEvent(RandEventSystem instance)
		{
			//IL_00e8: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				string[] obj = new string[3] { "m_randomEvent", "m_forcedEvent", "m_activeEvent" };
				if (NoAFKRaids.DebugMode.Value)
				{
					NoAFKRaids.Log.LogInfo((object)"Checking field values in detail:");
				}
				string[] array = obj;
				foreach (string text in array)
				{
					FieldInfo field = typeof(RandEventSystem).GetField(text, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
					if (!(field != null))
					{
						continue;
					}
					object value = field.GetValue(instance);
					RandomEvent val = (RandomEvent)((value is RandomEvent) ? value : null);
					if (NoAFKRaids.DebugMode.Value)
					{
						NoAFKRaids.Log.LogInfo((object)("Field '" + text + "': " + ((value == null) ? "null" : ("not null, type: " + value.GetType().Name))));
						if (val != null)
						{
							NoAFKRaids.Log.LogInfo((object)("  Event name: " + val.m_name));
							NoAFKRaids.Log.LogInfo((object)$"  Event pos: {val.m_pos}");
						}
					}
					if (val != null)
					{
						if (NoAFKRaids.DebugMode.Value)
						{
							NoAFKRaids.Log.LogInfo((object)("Using event from field '" + text + "': " + val.m_name));
						}
						return val;
					}
				}
				if (NoAFKRaids.DebugMode.Value)
				{
					NoAFKRaids.Log.LogInfo((object)"All event fields are null. StartRandomEvent might be called before event data is set.");
					NoAFKRaids.Log.LogInfo((object)"Since mod appears to work anyway, this might be expected behavior.");
				}
				return null;
			}
			catch (Exception ex)
			{
				NoAFKRaids.Log.LogError((object)("Error getting current random event: " + ex.Message));
				return null;
			}
		}

		private static List<Player> GetRaidTargetPlayers(RandomEvent raidEvent)
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: 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)
			try
			{
				List<Player> allPlayers = Player.GetAllPlayers();
				if (raidEvent.m_pos != Vector3.zero)
				{
					return GetPlayersNearPosition(raidEvent.m_pos, 500f, allPlayers);
				}
				return allPlayers.Where((Player p) => (Object)(object)p != (Object)null).ToList();
			}
			catch (Exception ex)
			{
				NoAFKRaids.Log.LogError((object)("Error finding raid target players: " + ex.Message));
				return new List<Player>();
			}
		}

		private static List<Player> GetPlayersNearPosition(Vector3 position, float maxDistance, List<Player> allPlayers)
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			return allPlayers.Where((Player p) => (Object)(object)p != (Object)null && Vector3.Distance(((Component)p).transform.position, position) <= maxDistance).ToList();
		}

		private static bool ApplyFallbackPolicy(string policyName, RandomEvent raidEvent)
		{
			try
			{
				NoAFKRaids.FallbackPolicyType fallbackPolicyType = NoAFKRaids.FallbackPolicyType.Conservative;
				if (Enum.TryParse<NoAFKRaids.FallbackPolicyType>(policyName, ignoreCase: true, out var result))
				{
					fallbackPolicyType = result;
				}
				return fallbackPolicyType switch
				{
					NoAFKRaids.FallbackPolicyType.Conservative => HasConnectedAFKPlayersInInternalState(), 
					NoAFKRaids.FallbackPolicyType.Liberal => false, 
					NoAFKRaids.FallbackPolicyType.Smart => ApplySmartFallbackLegacy(raidEvent), 
					NoAFKRaids.FallbackPolicyType.PlayerBased => ApplyPlayerBasedFallbackLegacy(), 
					_ => HasConnectedAFKPlayersInInternalState(), 
				};
			}
			catch (Exception ex)
			{
				NoAFKRaids.Log.LogError((object)("Error in fallback policy: " + ex.Message));
				return HasConnectedAFKPlayersInInternalState();
			}
		}

		private static bool ApplySmartFallbackLegacy(RandomEvent raidEvent)
		{
			try
			{
				if (raidEvent != null)
				{
					string text = raidEvent.m_name?.ToLowerInvariant() ?? "";
					if ((text.Contains("horde") || text.Contains("wolves") || text.Contains("bats")) && !NoAFKRaids.ProtectGlobalRaids.Value)
					{
						return false;
					}
				}
				return HasConnectedAFKPlayersInInternalState();
			}
			catch (Exception ex)
			{
				if (NoAFKRaids.DebugMode.Value)
				{
					NoAFKRaids.Log.LogError((object)("Error in smart fallback: " + ex.Message));
				}
				return HasConnectedAFKPlayersInInternalState();
			}
		}

		private static bool ApplyPlayerBasedFallbackLegacy()
		{
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0050: Unknown result type (might be due to invalid IL or missing references)
			//IL_0055: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				List<Vector3> connectedPlayerPositions = GetConnectedPlayerPositions();
				if (connectedPlayerPositions.Count == 0)
				{
					return HasConnectedAFKPlayersInInternalState();
				}
				foreach (Vector3 item in connectedPlayerPositions)
				{
					foreach (Player connectedAFKPlayer in GetConnectedAFKPlayers(Player.GetAllPlayers()))
					{
						float num = Vector3.Distance(((Component)connectedAFKPlayer).transform.position, item);
						if (num <= NoAFKRaids.AFKProtectionRadius.Value)
						{
							if (NoAFKRaids.DebugMode.Value)
							{
								NoAFKRaids.Log.LogInfo((object)$"Player-based fallback: AFK player {connectedAFKPlayer.GetPlayerName()} within {num:F1}m of potential raid target");
							}
							return true;
						}
					}
				}
				return false;
			}
			catch (Exception ex)
			{
				if (NoAFKRaids.DebugMode.Value)
				{
					NoAFKRaids.Log.LogError((object)("Error in player-based fallback: " + ex.Message));
				}
				return HasConnectedAFKPlayersInInternalState();
			}
		}
	}
}