Decompiled source of REPO Active v5.2.5

BepInEx\plugins\REPO_Active\REPO_Active.dll

Decompiled a month ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using BepInEx;
using BepInEx.Configuration;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using REPO_Active.Runtime;
using UnityEngine;
using UnityEngine.AI;
using UnityEngine.SceneManagement;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyVersion("0.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.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 REPO_Active
{
	[BepInPlugin("angelcomilk.repo_active", "REPO_Active", "5.2.5")]
	public sealed class Plugin : BaseUnityPlugin
	{
		[CompilerGenerated]
		private sealed class <AutoActivationAfterDelay>d__39 : IEnumerator<object>, IDisposable, IEnumerator
		{
			private int <>1__state;

			private object <>2__current;

			public float delay;

			public Plugin <>4__this;

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

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

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

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

			private bool MoveNext()
			{
				//IL_0032: Unknown result type (might be due to invalid IL or missing references)
				//IL_003c: Expected O, but got Unknown
				int num = <>1__state;
				Plugin plugin = <>4__this;
				switch (num)
				{
				default:
					return false;
				case 0:
					<>1__state = -1;
					if (delay > 0f)
					{
						<>2__current = (object)new WaitForSeconds(delay);
						<>1__state = 1;
						return true;
					}
					break;
				case 1:
					<>1__state = -1;
					break;
				}
				plugin._autoCoroutine = null;
				if (!plugin._autoActivate.Value || !plugin._levelReady)
				{
					return false;
				}
				plugin.CaptureReferenceAndDiscovery();
				if (!plugin._autoPrimed)
				{
					plugin.PrimeFirstPointIfAlreadyActivated();
					plugin._autoPrimed = true;
				}
				plugin.ActivateNearest(manual: false);
				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 <DeferredMarkActivated>d__44 : IEnumerator<object>, IDisposable, IEnumerator
		{
			private int <>1__state;

			private object <>2__current;

			public ExtractionPoint point;

			public Plugin <>4__this;

			public int id;

			private float[] <waits>5__2;

			private int <i>5__3;

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

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

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

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

			private bool MoveNext()
			{
				//IL_0070: Unknown result type (might be due to invalid IL or missing references)
				//IL_007a: Expected O, but got Unknown
				bool result;
				try
				{
					int num = <>1__state;
					Plugin plugin = <>4__this;
					if (num == 0)
					{
						<>1__state = -1;
						<>1__state = -3;
						if (!Object.op_Implicit((Object)(object)point))
						{
							result = false;
							goto IL_0115;
						}
						<waits>5__2 = new float[5] { 0.15f, 0.25f, 0.35f, 0.35f, 0.4f };
						<i>5__3 = 0;
						goto IL_00f3;
					}
					if (num == 1)
					{
						<>1__state = -3;
						if (!Object.op_Implicit((Object)(object)point))
						{
							result = false;
						}
						else
						{
							State? state = plugin._scanner.ReadState(point);
							if (!state.HasValue || ExtractionPointScanner.IsIdleLikeState(state) || ExtractionPointScanner.IsCompletedLikeState(state))
							{
								<i>5__3++;
								goto IL_00f3;
							}
							plugin._scanner.MarkActivated(point);
							result = false;
						}
						goto IL_0115;
					}
					result = false;
					goto end_IL_0000;
					IL_00f3:
					if (<i>5__3 < <waits>5__2.Length)
					{
						<>2__current = (object)new WaitForSeconds(<waits>5__2[<i>5__3]);
						<>1__state = 1;
						result = true;
					}
					else
					{
						<waits>5__2 = null;
						<>m__Finally1();
						result = false;
					}
					goto end_IL_0000;
					IL_0115:
					<>m__Finally1();
					end_IL_0000:;
				}
				catch
				{
					//try-fault
					((IDisposable)this).Dispose();
					throw;
				}
				return result;
			}

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

			private void <>m__Finally1()
			{
				<>1__state = -1;
				<>4__this._deferredMarking.Remove(id);
			}

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

		public const string PluginGuid = "angelcomilk.repo_active";

		public const string PluginName = "REPO_Active";

		public const string PluginVersion = "5.2.5";

		private const bool SkipActivated = true;

		private const float DiscoverRadius = 20f;

		private const float AutoReadyBuffer = 30f;

		private const float AutoEventDelay = 0.35f;

		private static readonly string[] KeyOptions = BuildKeyOptions();

		private ConfigEntry<bool> _autoActivate;

		private ConfigEntry<string> _keyActivateNearest;

		private ConfigEntry<bool> _discoverAllPoints;

		private readonly HashSet<int> _deferredMarking = new HashSet<int>();

		private readonly List<PlayerAvatar> _playerCache = new List<PlayerAvatar>();

		private readonly List<Vector3> _playerLastPos = new List<Vector3>();

		private ExtractionPointScanner _scanner;

		private Harmony? _harmony;

		private Coroutine? _autoCoroutine;

		private KeyCode _activateKey = (KeyCode)284;

		private float _autoReadyAt = -1f;

		private bool _levelReady;

		private bool _autoPrimed;

		private int _playerCacheHash;

		internal static Plugin? Instance { get; private set; }

		internal ExtractionPointStateTracker StateTracker { get; } = new ExtractionPointStateTracker();


		private void Awake()
		{
			//IL_0058: Unknown result type (might be due to invalid IL or missing references)
			//IL_0062: Expected O, but got Unknown
			//IL_00cd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d7: Expected O, but got Unknown
			MigrateLegacyConfigIfNeeded(out bool defaultAutoActivate, out bool defaultDiscoverAll, out string defaultKey);
			_autoActivate = ((BaseUnityPlugin)this).Config.Bind<bool>("Auto", "AutoActivate", defaultAutoActivate, "Auto activate when idle.");
			_keyActivateNearest = ((BaseUnityPlugin)this).Config.Bind<string>("Keybinds", "ActivateNearestKey", SanitizeKeyName(defaultKey), new ConfigDescription("Press to activate next extraction point.", (AcceptableValueBase)(object)new AcceptableValueList<string>(KeyOptions), Array.Empty<object>()));
			_discoverAllPoints = ((BaseUnityPlugin)this).Config.Bind<bool>("Discovery", "DiscoverAllPoints", defaultDiscoverAll, "If true, treat all extraction points as discovered.");
			_keyActivateNearest.SettingChanged += delegate
			{
				RefreshActivateKey();
			};
			RefreshActivateKey();
			((BaseUnityPlugin)this).Config.Save();
			Instance = this;
			_scanner = new ExtractionPointScanner(StateTracker);
			_harmony = new Harmony("angelcomilk.repo_active");
			_harmony.PatchAll(typeof(Plugin).Assembly);
			SceneManager.sceneLoaded += OnSceneLoaded;
		}

		private void OnDestroy()
		{
			try
			{
				SceneManager.sceneLoaded -= OnSceneLoaded;
			}
			catch
			{
			}
			try
			{
				Harmony? harmony = _harmony;
				if (harmony != null)
				{
					harmony.UnpatchSelf();
				}
				_harmony = null;
			}
			catch
			{
			}
			if (Instance == this)
			{
				Instance = null;
			}
		}

		private void Update()
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			if ((int)_activateKey != 0 && Input.GetKeyDown(_activateKey))
			{
				ActivateNearest(manual: true);
			}
		}

		private void OnSceneLoaded(Scene scene, LoadSceneMode mode)
		{
			ResetRoundState();
		}

		private void ResetRoundState()
		{
			_levelReady = false;
			_autoReadyAt = -1f;
			_autoPrimed = false;
			if (_autoCoroutine != null)
			{
				((MonoBehaviour)this).StopCoroutine(_autoCoroutine);
				_autoCoroutine = null;
			}
			StateTracker.ResetForNewRound();
			_scanner.ResetForNewRound();
			_deferredMarking.Clear();
			ClearPlayerCache();
		}

		private void HandleLevelGenerated()
		{
			if (!_levelReady)
			{
				_levelReady = true;
				_autoReadyAt = Time.realtimeSinceStartup + 30f;
				RefreshCachedPlayers();
				CaptureReferenceAndDiscovery();
				ScheduleAutoActivation(30f);
			}
		}

		private void HandleExtractionPointStarted(ExtractionPoint point)
		{
			if (Object.op_Implicit((Object)(object)point))
			{
				_scanner.RegisterPoint(point);
				CaptureReferenceAndDiscovery();
				if (_levelReady)
				{
					ScheduleAutoActivation(GetAutoReadyDelay());
				}
			}
		}

		private void HandleExtractionPointStateChanged(ExtractionPoint point, State state)
		{
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: 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_006b: Unknown result type (might be due to invalid IL or missing references)
			if (!Object.op_Implicit((Object)(object)point))
			{
				return;
			}
			_scanner.RegisterPoint(point);
			StateTracker.Record(point, state);
			if (ExtractionPointScanner.IsBlockingState(state))
			{
				_scanner.MarkActivated(point);
				return;
			}
			if (ExtractionPointScanner.IsCompletedLikeState(state))
			{
				_scanner.MarkActivated(point);
			}
			if (_levelReady && _autoActivate.Value && IsAutoContinueState(state))
			{
				ScheduleAutoActivation(Math.Max(GetAutoReadyDelay(), 0.35f));
			}
		}

		private void HandleRoomPopulationChangedEvent()
		{
			ClearPlayerCache();
			RefreshCachedPlayers();
		}

		private void ScheduleAutoActivation(float delay)
		{
			if (_autoActivate.Value && _levelReady && _autoCoroutine == null)
			{
				float delay2 = Math.Max(delay, GetAutoReadyDelay());
				_autoCoroutine = ((MonoBehaviour)this).StartCoroutine(AutoActivationAfterDelay(delay2));
			}
		}

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

		private float GetAutoReadyDelay()
		{
			if (_autoReadyAt < 0f)
			{
				return 0f;
			}
			float num = _autoReadyAt - Time.realtimeSinceStartup;
			if (!(num > 0f))
			{
				return 0f;
			}
			return num;
		}

		private void ActivateNearest(bool manual)
		{
			//IL_002e: 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_003a: 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_004b: 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_008e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bb: 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_00da: Unknown result type (might be due to invalid IL or missing references)
			List<ExtractionPoint> allPoints = _scanner.GetAllPoints();
			if (allPoints.Count == 0 || _scanner.TryGetActivatingInfo(allPoints, out string _, out int _))
			{
				return;
			}
			Vector3 referencePos = _scanner.GetReferencePos();
			_scanner.CaptureSpawnPosIfNeeded(referencePos);
			Vector3 spawnPos = _scanner.GetSpawnPos();
			if (_discoverAllPoints.Value)
			{
				_scanner.MarkAllDiscovered(allPoints);
			}
			else
			{
				UpdateDiscoveredFromCachedPlayers(referencePos);
			}
			List<ExtractionPoint> eligible = (List<ExtractionPoint>)(_discoverAllPoints.Value ? ((IList)allPoints) : ((IList)_scanner.FilterDiscovered(allPoints)));
			List<ExtractionPoint> allPoints2 = BuildPlanInputWithoutEarlyTail(allPoints, eligible, spawnPos);
			List<ExtractionPoint> list = (_discoverAllPoints.Value ? _scanner.BuildPlanDiscoverAllFixedAnchors(allPoints, spawnPos, skipActivated: true) : _scanner.BuildStage1PlannedList(allPoints2, spawnPos, skipActivated: true));
			if (list.Count == 0)
			{
				return;
			}
			ExtractionPoint val = list[0];
			if (!ShouldHoldTailPointActivation(allPoints, spawnPos, list, val))
			{
				try
				{
					val.OnClick();
				}
				catch
				{
					return;
				}
				State? state = _scanner.ReadState(val);
				if (state.HasValue && !ExtractionPointScanner.IsIdleLikeState(state) && !ExtractionPointScanner.IsCompletedLikeState(state))
				{
					_scanner.MarkActivated(val);
				}
				else
				{
					TryDeferredMarkActivated(val);
				}
			}
		}

		private List<ExtractionPoint> BuildPlanInputWithoutEarlyTail(List<ExtractionPoint> allPoints, List<ExtractionPoint> eligible, Vector3 spawnPos)
		{
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			if (_discoverAllPoints.Value || eligible.Count <= 1 || !_scanner.TryGetGlobalAnchorsNoCache(allPoints, spawnPos, out ExtractionPoint _, out ExtractionPoint tailAnchor) || (Object)(object)tailAnchor == (Object)null || !Object.op_Implicit((Object)(object)tailAnchor))
			{
				return eligible;
			}
			int tailId = ((Object)tailAnchor).GetInstanceID();
			if (!eligible.Any((ExtractionPoint point) => Object.op_Implicit((Object)(object)point) && ((Object)point).GetInstanceID() == tailId))
			{
				return eligible;
			}
			List<ExtractionPoint> list = new List<ExtractionPoint>();
			int num = 0;
			for (int i = 0; i < eligible.Count; i++)
			{
				ExtractionPoint val = eligible[i];
				if (Object.op_Implicit((Object)(object)val) && ((Object)val).GetInstanceID() != tailId)
				{
					list.Add(val);
					if (!ExtractionPointScanner.IsCompletedLikeState(_scanner.ReadState(val)))
					{
						num++;
					}
				}
			}
			if (list.Count <= 0 || num <= 0)
			{
				return eligible;
			}
			return list;
		}

		private void TryDeferredMarkActivated(ExtractionPoint point)
		{
			if (Object.op_Implicit((Object)(object)point))
			{
				int instanceID = ((Object)point).GetInstanceID();
				if (_deferredMarking.Add(instanceID))
				{
					((MonoBehaviour)this).StartCoroutine(DeferredMarkActivated(point, instanceID));
				}
			}
		}

		[IteratorStateMachine(typeof(<DeferredMarkActivated>d__44))]
		private IEnumerator DeferredMarkActivated(ExtractionPoint point, int id)
		{
			//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
			return new <DeferredMarkActivated>d__44(0)
			{
				<>4__this = this,
				point = point,
				id = id
			};
		}

		private void PrimeFirstPointIfAlreadyActivated()
		{
			//IL_001b: 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_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_004e: Unknown result type (might be due to invalid IL or missing references)
			//IL_007c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0081: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a6: Unknown result type (might be due to invalid IL or missing references)
			//IL_0096: Unknown result type (might be due to invalid IL or missing references)
			List<ExtractionPoint> allPoints = _scanner.GetAllPoints();
			if (allPoints.Count == 0)
			{
				return;
			}
			Vector3 referencePos = _scanner.GetReferencePos();
			_scanner.CaptureSpawnPosIfNeeded(referencePos);
			if (_discoverAllPoints.Value)
			{
				_scanner.MarkAllDiscovered(allPoints);
			}
			else
			{
				_scanner.UpdateDiscovered(referencePos, 20f);
			}
			List<ExtractionPoint> allPoints2 = (List<ExtractionPoint>)(_discoverAllPoints.Value ? ((IList)allPoints) : ((IList)_scanner.FilterDiscovered(allPoints)));
			Vector3 spawnPos = _scanner.GetSpawnPos();
			List<ExtractionPoint> list = (_discoverAllPoints.Value ? _scanner.BuildPlanDiscoverAllFixedAnchors(allPoints, spawnPos, skipActivated: true) : _scanner.BuildStage1PlannedList(allPoints2, spawnPos, skipActivated: true));
			if (list.Count != 0)
			{
				State? state = _scanner.ReadState(list[0]);
				if (state.HasValue && !ExtractionPointScanner.IsIdleLikeState(state))
				{
					_scanner.MarkActivated(list[0]);
				}
			}
		}

		private void CaptureReferenceAndDiscovery()
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_0045: Unknown result type (might be due to invalid IL or missing references)
			Vector3 referencePos = _scanner.GetReferencePos();
			_scanner.CaptureSpawnPosIfNeeded(referencePos);
			List<ExtractionPoint> allPoints = _scanner.GetAllPoints();
			if (_discoverAllPoints.Value)
			{
				_scanner.MarkAllDiscovered(allPoints);
				return;
			}
			RefreshCachedPlayers();
			UpdateDiscoveredFromCachedPlayers(referencePos);
		}

		private void RefreshCachedPlayers()
		{
			if (!_discoverAllPoints.Value)
			{
				_ = TryGetAllPlayerPositionsHost().Count;
			}
		}

		private List<Vector3> TryGetAllPlayerPositionsHost()
		{
			//IL_0102: Unknown result type (might be due to invalid IL or missing references)
			//IL_015e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0163: Unknown result type (might be due to invalid IL or missing references)
			//IL_0166: Unknown result type (might be due to invalid IL or missing references)
			//IL_0175: Unknown result type (might be due to invalid IL or missing references)
			List<Vector3> list = new List<Vector3>();
			try
			{
				if (!SemiFunc.IsMasterClientOrSingleplayer())
				{
					return list;
				}
				List<PlayerAvatar> list2 = SemiFunc.PlayerGetList();
				if (list2 == null || list2.Count == 0)
				{
					return list;
				}
				int num = 17;
				List<PlayerAvatar> list3 = new List<PlayerAvatar>(list2.Count);
				for (int i = 0; i < list2.Count; i++)
				{
					PlayerAvatar val = list2[i];
					if (Object.op_Implicit((Object)(object)val) && Object.op_Implicit((Object)(object)((Component)val).transform))
					{
						list3.Add(val);
						num = num * 31 + ((Object)val).GetInstanceID();
					}
				}
				if (list3.Count == 0)
				{
					return list;
				}
				if (num != _playerCacheHash || _playerCache.Count != list3.Count)
				{
					_playerCacheHash = num;
					_playerCache.Clear();
					_playerCache.AddRange(list3);
					_playerLastPos.Clear();
					for (int j = 0; j < _playerCache.Count; j++)
					{
						_playerLastPos.Add(((Component)_playerCache[j]).transform.position);
					}
				}
				for (int k = 0; k < _playerCache.Count; k++)
				{
					PlayerAvatar val2 = _playerCache[k];
					if (!Object.op_Implicit((Object)(object)val2) || !Object.op_Implicit((Object)(object)((Component)val2).transform))
					{
						ClearPlayerCache();
						return list;
					}
					Vector3 position = ((Component)val2).transform.position;
					list.Add(position);
					_playerLastPos[k] = position;
				}
				return list;
			}
			catch
			{
				return list;
			}
		}

		private void UpdateDiscoveredFromCachedPlayers(Vector3 fallbackPos)
		{
			//IL_005f: 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)
			if (_playerCache.Count > 0 && _playerLastPos.Count == _playerCache.Count)
			{
				for (int i = 0; i < _playerLastPos.Count; i++)
				{
					_scanner.UpdateDiscovered(_playerLastPos[i], 20f);
				}
			}
			else
			{
				_scanner.UpdateDiscovered(fallbackPos, 20f);
			}
		}

		private bool ShouldHoldTailPointActivation(List<ExtractionPoint> allPoints, Vector3 spawnPos, List<ExtractionPoint> plan, ExtractionPoint next)
		{
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			if (_discoverAllPoints.Value || !Object.op_Implicit((Object)(object)next))
			{
				return false;
			}
			if (!_scanner.TryGetGlobalAnchorsNoCache(allPoints, spawnPos, out ExtractionPoint firstAnchor, out ExtractionPoint tailAnchor) || (Object)(object)tailAnchor == (Object)null || !Object.op_Implicit((Object)(object)tailAnchor))
			{
				return false;
			}
			int num = (((Object)(object)firstAnchor != (Object)null && Object.op_Implicit((Object)(object)firstAnchor)) ? ((Object)firstAnchor).GetInstanceID() : int.MinValue);
			int instanceID = ((Object)tailAnchor).GetInstanceID();
			bool flag = ((Object)next).GetInstanceID() == instanceID;
			int num2 = 0;
			for (int i = 0; i < allPoints.Count; i++)
			{
				ExtractionPoint val = allPoints[i];
				if (Object.op_Implicit((Object)(object)val))
				{
					int instanceID2 = ((Object)val).GetInstanceID();
					if (instanceID2 != num && instanceID2 != instanceID && !ExtractionPointScanner.IsCompletedLikeState(_scanner.ReadState(val)))
					{
						num2++;
					}
				}
			}
			if (flag)
			{
				return num2 > 0;
			}
			return false;
		}

		private void ClearPlayerCache()
		{
			_playerCache.Clear();
			_playerLastPos.Clear();
			_playerCacheHash = 0;
		}

		private void RefreshActivateKey()
		{
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			_activateKey = ParseKeyCode(_keyActivateNearest.Value);
		}

		private void MigrateLegacyConfigIfNeeded(out bool defaultAutoActivate, out bool defaultDiscoverAll, out string defaultKey)
		{
			defaultAutoActivate = false;
			defaultDiscoverAll = false;
			defaultKey = "F3";
			string configFilePath = ((BaseUnityPlugin)this).Config.ConfigFilePath;
			if (string.IsNullOrWhiteSpace(configFilePath) || !File.Exists(configFilePath))
			{
				return;
			}
			string text;
			try
			{
				text = File.ReadAllText(configFilePath);
			}
			catch
			{
				return;
			}
			if (TryReadConfigValue(text, "AutoActivate", out string value) && bool.TryParse(value, out var result))
			{
				defaultAutoActivate = result;
			}
			if (TryReadConfigValue(text, "DiscoverAllPoints", out string value2) && bool.TryParse(value2, out var result2))
			{
				defaultDiscoverAll = result2;
			}
			if (TryReadConfigValue(text, "ActivateNearestKey", out string value3) || TryReadConfigValue(text, "ActivateNearestShortcut", out value3) || TryReadConfigValue(text, "ActivateNearest", out value3))
			{
				defaultKey = SanitizeKeyName(ExtractPrimaryKeyName(value3));
			}
			if (text.IndexOf("ActivateNearestShortcut", StringComparison.OrdinalIgnoreCase) < 0 && text.IndexOf("Setting type: KeyCode", StringComparison.OrdinalIgnoreCase) < 0 && text.IndexOf("Setting type: KeyboardShortcut", StringComparison.OrdinalIgnoreCase) < 0 && text.IndexOf("BuildQueueAndRun", StringComparison.OrdinalIgnoreCase) < 0 && text.IndexOf("EnforceHostAuthority", StringComparison.OrdinalIgnoreCase) < 0)
			{
				return;
			}
			try
			{
				string destFileName = configFilePath + ".bak." + DateTime.Now.ToString("yyyyMMddHHmmss");
				File.Copy(configFilePath, destFileName, overwrite: false);
			}
			catch
			{
			}
			try
			{
				((BaseUnityPlugin)this).Config.Clear();
				File.Delete(configFilePath);
				((BaseUnityPlugin)this).Config.Reload();
			}
			catch
			{
			}
		}

		private static bool TryReadConfigValue(string text, string key, out string value)
		{
			value = "";
			using (StringReader stringReader = new StringReader(text))
			{
				string text2;
				while ((text2 = stringReader.ReadLine()) != null)
				{
					string text3 = text2.Trim();
					if (text3.Length != 0 && text3[0] != '#')
					{
						int num = text3.IndexOf('=');
						if (num > 0 && string.Equals(text3.Substring(0, num).Trim(), key, StringComparison.OrdinalIgnoreCase))
						{
							value = text3.Substring(num + 1).Trim();
							return true;
						}
					}
				}
			}
			return false;
		}

		private static bool IsAutoContinueState(State state)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0003: Unknown result type (might be due to invalid IL or missing references)
			//IL_0005: Invalid comparison between Unknown and I4
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_0009: Invalid comparison between Unknown and I4
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_000d: Invalid comparison between Unknown and I4
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Invalid comparison between Unknown and I4
			if ((int)state != 0 && (int)state != 1 && (int)state != 3 && (int)state != 7)
			{
				return (int)state == 5;
			}
			return true;
		}

		private static KeyCode ParseKeyCode(string value)
		{
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			if (Enum.TryParse<KeyCode>(value, ignoreCase: true, out KeyCode result))
			{
				return result;
			}
			return (KeyCode)284;
		}

		private static string SanitizeKeyName(string value)
		{
			string b = ExtractPrimaryKeyName(value);
			for (int i = 0; i < KeyOptions.Length; i++)
			{
				if (string.Equals(KeyOptions[i], b, StringComparison.OrdinalIgnoreCase))
				{
					return KeyOptions[i];
				}
			}
			return "F3";
		}

		private static string ExtractPrimaryKeyName(string value)
		{
			if (string.IsNullOrWhiteSpace(value))
			{
				return "F3";
			}
			string text = value.Trim();
			int num = text.IndexOf('+');
			if (num >= 0)
			{
				text = text.Substring(0, num).Trim();
			}
			int num2 = text.IndexOf(',');
			if (num2 >= 0)
			{
				text = text.Substring(0, num2).Trim();
			}
			if (text.Length != 0)
			{
				return text;
			}
			return "F3";
		}

		private static string[] BuildKeyOptions()
		{
			List<string> list = new List<string> { "None" };
			for (int i = 1; i <= 12; i++)
			{
				list.Add("F" + i);
			}
			for (char c = 'A'; c <= 'Z'; c = (char)(c + 1))
			{
				list.Add(c.ToString());
			}
			for (int j = 0; j <= 9; j++)
			{
				list.Add("Alpha" + j);
			}
			list.Add("Mouse3");
			list.Add("Mouse4");
			list.Add("Mouse5");
			return list.ToArray();
		}

		internal static void NotifyRoomPopulationChanged()
		{
			Instance?.HandleRoomPopulationChangedEvent();
		}

		internal static void NotifyLevelGenerated()
		{
			Instance?.HandleLevelGenerated();
		}

		internal static void NotifyExtractionPointStarted(ExtractionPoint point)
		{
			Instance?.HandleExtractionPointStarted(point);
		}

		internal static void NotifyExtractionPointState(ExtractionPoint point, State state)
		{
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			Instance?.HandleExtractionPointStateChanged(point, state);
		}
	}
	[HarmonyPatch(typeof(NetworkManager), "OnPlayerEnteredRoom")]
	internal static class NetworkManagerOnPlayerEnteredRoomPatch
	{
		private static void Postfix()
		{
			Plugin.NotifyRoomPopulationChanged();
		}
	}
	[HarmonyPatch(typeof(NetworkManager), "OnPlayerLeftRoom")]
	internal static class NetworkManagerOnPlayerLeftRoomPatch
	{
		private static void Postfix()
		{
			Plugin.NotifyRoomPopulationChanged();
		}
	}
	[HarmonyPatch(typeof(LevelGenerator), "GenerateDone")]
	internal static class LevelGeneratorGenerateDonePatch
	{
		private static void Postfix()
		{
			Plugin.NotifyLevelGenerated();
		}
	}
	[HarmonyPatch(typeof(SemiFunc), "OnLevelGenDone")]
	internal static class SemiFuncOnLevelGenDonePatch
	{
		private static void Postfix()
		{
			Plugin.NotifyLevelGenerated();
		}
	}
	[HarmonyPatch(typeof(ExtractionPoint), "Start")]
	internal static class ExtractionPointStartPatch
	{
		private static void Postfix(ExtractionPoint __instance)
		{
			Plugin.NotifyExtractionPointStarted(__instance);
		}
	}
	[HarmonyPatch(typeof(ExtractionPoint), "StateSetRPC")]
	internal static class ExtractionPointStateSetRpcPatch
	{
		private static void Postfix(ExtractionPoint __instance, State state)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			Plugin.NotifyExtractionPointState(__instance, state);
		}
	}
}
namespace REPO_Active.Runtime
{
	internal sealed class ExtractionPointScanner
	{
		private readonly ExtractionPointStateTracker _stateTracker;

		private readonly List<ExtractionPoint> _cached = new List<ExtractionPoint>();

		private readonly HashSet<int> _cachedIds = new HashSet<int>();

		private readonly HashSet<int> _activatedIds = new HashSet<int>();

		private readonly HashSet<int> _discovered = new HashSet<int>();

		private readonly Dictionary<int, float> _spawnPathCache = new Dictionary<int, float>();

		private readonly HashSet<int> _spawnPathInvalid = new HashSet<int>();

		private readonly Dictionary<long, float> _edgePathCache = new Dictionary<long, float>();

		private readonly HashSet<long> _edgePathInvalid = new HashSet<long>();

		private Vector3? _spawnPos;

		private int? _firstAnchorId;

		private int? _lastAnchorId;

		public int CachedCount => _cached.Count;

		public int DiscoveredCount => _discovered.Count;

		public ExtractionPointScanner(ExtractionPointStateTracker stateTracker)
		{
			_stateTracker = stateTracker;
		}

		public bool RegisterPoint(ExtractionPoint point)
		{
			if (!Object.op_Implicit((Object)(object)point))
			{
				return false;
			}
			PruneInvalidCachedPoints();
			int instanceID = ((Object)point).GetInstanceID();
			if (_cachedIds.Contains(instanceID))
			{
				return false;
			}
			_cachedIds.Add(instanceID);
			_cached.Add(point);
			return true;
		}

		public List<ExtractionPoint> GetAllPoints()
		{
			PruneInvalidCachedPoints();
			return new List<ExtractionPoint>(_cached);
		}

		public Vector3 GetReferencePos()
		{
			//IL_0079: 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_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_007f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0045: 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_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)
			try
			{
				PlayerAvatar val = SemiFunc.PlayerAvatarLocal();
				if (Object.op_Implicit((Object)(object)val) && Object.op_Implicit((Object)(object)((Component)val).transform))
				{
					return ((Component)val).transform.position;
				}
			}
			catch
			{
			}
			try
			{
				if (Object.op_Implicit((Object)(object)Camera.main))
				{
					return ((Component)Camera.main).transform.position;
				}
			}
			catch
			{
			}
			try
			{
				GameObject val2 = GameObject.FindWithTag("Player");
				if (Object.op_Implicit((Object)(object)val2))
				{
					return val2.transform.position;
				}
			}
			catch
			{
			}
			return Vector3.zero;
		}

		public void MarkAllDiscovered(List<ExtractionPoint> allPoints)
		{
			for (int i = 0; i < allPoints.Count; i++)
			{
				ExtractionPoint val = allPoints[i];
				if (Object.op_Implicit((Object)(object)val))
				{
					_discovered.Add(((Object)val).GetInstanceID());
				}
			}
		}

		public void UpdateDiscovered(Vector3 refPos, float radius)
		{
			//IL_0040: 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_004c: 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)
			if (_cached.Count == 0)
			{
				return;
			}
			float num = radius * radius;
			for (int i = 0; i < _cached.Count; i++)
			{
				ExtractionPoint val = _cached[i];
				if (!Object.op_Implicit((Object)(object)val))
				{
					continue;
				}
				int instanceID = ((Object)val).GetInstanceID();
				if (!_discovered.Contains(instanceID))
				{
					Vector3 val2 = refPos - ((Component)val).transform.position;
					if (((Vector3)(ref val2)).sqrMagnitude <= num)
					{
						_discovered.Add(instanceID);
					}
				}
			}
		}

		public List<ExtractionPoint> FilterDiscovered(List<ExtractionPoint> allPoints)
		{
			List<ExtractionPoint> list = new List<ExtractionPoint>();
			for (int i = 0; i < allPoints.Count; i++)
			{
				ExtractionPoint val = allPoints[i];
				if (Object.op_Implicit((Object)(object)val) && _discovered.Contains(((Object)val).GetInstanceID()))
				{
					list.Add(val);
				}
			}
			return list;
		}

		public Vector3 GetSpawnPos()
		{
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			return (Vector3)(((??)_spawnPos) ?? Vector3.zero);
		}

		public void CaptureSpawnPosIfNeeded(Vector3 refPos)
		{
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			if (!_spawnPos.HasValue && !(refPos == Vector3.zero))
			{
				_spawnPos = refPos;
			}
		}

		public bool TryGetRoundAnchors(List<ExtractionPoint> allPoints, Vector3 spawnPos, out ExtractionPoint? firstAnchor, out ExtractionPoint? tailAnchor)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			return TryGetGlobalAnchorsNoCache(allPoints, spawnPos, out firstAnchor, out tailAnchor);
		}

		public bool TryGetGlobalAnchorsNoCache(List<ExtractionPoint> allPoints, Vector3 spawnPos, out ExtractionPoint? firstAnchor, out ExtractionPoint? tailAnchor)
		{
			//IL_0018: 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_0046: Unknown result type (might be due to invalid IL or missing references)
			firstAnchor = null;
			tailAnchor = null;
			if (allPoints == null || allPoints.Count == 0 || spawnPos == Vector3.zero)
			{
				return false;
			}
			List<(ExtractionPoint, int, float)> list = new List<(ExtractionPoint, int, float)>();
			for (int i = 0; i < allPoints.Count; i++)
			{
				ExtractionPoint val = allPoints[i];
				if (Object.op_Implicit((Object)(object)val) && TryGetSpawnPathLength(val, spawnPos, _spawnPathCache, _spawnPathInvalid, out var length))
				{
					list.Add((val, ((Object)val).GetInstanceID(), length));
				}
			}
			if (list.Count == 0)
			{
				return false;
			}
			(ExtractionPoint point, int id, float spawnPath) firstPick = PickByMinSpawn(list);
			firstAnchor = firstPick.point;
			List<(ExtractionPoint, int, float)> list2 = list.Where<(ExtractionPoint, int, float)>(((ExtractionPoint point, int id, float spawnPath) item) => item.id != firstPick.id).ToList();
			if (list2.Count == 0)
			{
				return true;
			}
			tailAnchor = PickByMinSpawn(list2).point;
			return true;
		}

		public void ResetForNewRound()
		{
			_cached.Clear();
			_cachedIds.Clear();
			_activatedIds.Clear();
			_discovered.Clear();
			_spawnPos = null;
			_spawnPathCache.Clear();
			_spawnPathInvalid.Clear();
			_edgePathCache.Clear();
			_edgePathInvalid.Clear();
			_firstAnchorId = null;
			_lastAnchorId = null;
		}

		public void MarkActivated(ExtractionPoint point)
		{
			if (Object.op_Implicit((Object)(object)point))
			{
				_activatedIds.Add(((Object)point).GetInstanceID());
			}
		}

		public State? ReadState(ExtractionPoint point)
		{
			return _stateTracker.TryGetState(point);
		}

		public string ReadStateName(ExtractionPoint point)
		{
			return _stateTracker.ReadStateName(point);
		}

		private void PruneInvalidCachedPoints()
		{
			for (int num = _cached.Count - 1; num >= 0; num--)
			{
				if (!Object.op_Implicit((Object)(object)_cached[num]))
				{
					_cached.RemoveAt(num);
				}
			}
			if (_cachedIds.Count == _cached.Count)
			{
				return;
			}
			_cachedIds.Clear();
			for (int i = 0; i < _cached.Count; i++)
			{
				ExtractionPoint val = _cached[i];
				if (Object.op_Implicit((Object)(object)val))
				{
					_cachedIds.Add(((Object)val).GetInstanceID());
				}
			}
		}

		public bool TryGetActivatingInfo(List<ExtractionPoint> allPoints, out string info, out int busyCount)
		{
			//IL_003e: 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)
			info = "";
			busyCount = 0;
			if (allPoints == null || allPoints.Count == 0)
			{
				return false;
			}
			for (int i = 0; i < allPoints.Count; i++)
			{
				ExtractionPoint val = allPoints[i];
				if (!Object.op_Implicit((Object)(object)val))
				{
					continue;
				}
				State? val2 = ReadState(val);
				if (val2.HasValue && IsBlockingState(val2.Value))
				{
					busyCount++;
					if (string.IsNullOrEmpty(info))
					{
						info = $"{((Object)((Component)val).gameObject).name} state={val2.Value}";
					}
				}
			}
			return busyCount > 0;
		}

		internal static bool IsIdleLikeState(State? state)
		{
			//IL_0003: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Invalid comparison between Unknown and I4
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: Invalid comparison between Unknown and I4
			if (state != (State?)0 && (int)state.GetValueOrDefault() != 1)
			{
				return (int)state.GetValueOrDefault() == 5;
			}
			return true;
		}

		internal static bool IsCompletedLikeState(State? state)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: Invalid comparison between Unknown and I4
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0012: Invalid comparison between Unknown and I4
			if ((int)state.GetValueOrDefault() != 3)
			{
				return (int)state.GetValueOrDefault() == 7;
			}
			return true;
		}

		internal static bool IsBlockingState(State? state)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: Invalid comparison between Unknown and I4
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0012: Invalid comparison between Unknown and I4
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: Invalid comparison between Unknown and I4
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: Invalid comparison between Unknown and I4
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: Invalid comparison between Unknown and I4
			if ((int)state.GetValueOrDefault() != 2 && (int)state.GetValueOrDefault() != 4 && (int)state.GetValueOrDefault() != 6 && (int)state.GetValueOrDefault() != 8)
			{
				return (int)state.GetValueOrDefault() == 9;
			}
			return true;
		}

		public List<ExtractionPoint> BuildStage1PlannedList(List<ExtractionPoint> allPoints, Vector3 spawnPos, bool skipActivated)
		{
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_003b: Unknown result type (might be due to invalid IL or missing references)
			List<ExtractionPoint> list = new List<ExtractionPoint>();
			if (allPoints == null || allPoints.Count == 0 || spawnPos == Vector3.zero)
			{
				return list;
			}
			List<ExtractionPoint> list2 = BuildEligibleCandidates(allPoints, skipActivated);
			if (list2.Count == 0)
			{
				return list;
			}
			List<(ExtractionPoint, int, float)> reachableFromSpawn = GetReachableFromSpawn(list2, spawnPos);
			if (reachableFromSpawn.Count == 0)
			{
				return list;
			}
			int num = FindIndexById(reachableFromSpawn, _firstAnchorId);
			(ExtractionPoint point, int id, float spawnPath) firstPick = ((num >= 0) ? reachableFromSpawn[num] : PickByMinSpawn(reachableFromSpawn));
			if (!_firstAnchorId.HasValue)
			{
				_firstAnchorId = firstPick.id;
			}
			list.Add(firstPick.point);
			List<(ExtractionPoint, int, float)> list3 = reachableFromSpawn.Where<(ExtractionPoint, int, float)>(((ExtractionPoint point, int id, float spawnPath) item) => item.id != firstPick.id).ToList();
			if (list3.Count == 0)
			{
				return list;
			}
			int num2 = FindIndexById(list3, _lastAnchorId);
			(ExtractionPoint point, int id, float spawnPath) lastPick = ((num2 >= 0) ? list3[num2] : PickByMinSpawn(list3));
			if (!_lastAnchorId.HasValue)
			{
				_lastAnchorId = lastPick.id;
			}
			List<ExtractionPoint> middleCandidates = (from item in list3
				where item.id != lastPick.id
				select item.point).ToList();
			List<ExtractionPoint> list4 = FindBestMiddleOrder(firstPick.point, middleCandidates, lastPick.point);
			if (list4 == null)
			{
				return new List<ExtractionPoint>();
			}
			list.AddRange(list4);
			list.Add(lastPick.point);
			return list;
		}

		public List<ExtractionPoint> BuildPlanDiscoverAllFixedAnchors(List<ExtractionPoint> allPoints, Vector3 spawnPos, bool skipActivated)
		{
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: 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)
			List<ExtractionPoint> list = new List<ExtractionPoint>();
			if (allPoints == null || allPoints.Count == 0 || spawnPos == Vector3.zero)
			{
				return list;
			}
			if (!TryGetGlobalAnchorsNoCache(allPoints, spawnPos, out ExtractionPoint firstAnchor, out ExtractionPoint tailAnchor) || (Object)(object)firstAnchor == (Object)null || !Object.op_Implicit((Object)(object)firstAnchor))
			{
				return list;
			}
			List<ExtractionPoint> list2 = BuildEligibleCandidates(allPoints, skipActivated);
			if (list2.Count == 0)
			{
				return list;
			}
			List<(ExtractionPoint, int, float)> reachableFromSpawn = GetReachableFromSpawn(list2, spawnPos);
			if (reachableFromSpawn.Count == 0)
			{
				return list;
			}
			int globalFirstId = ((Object)firstAnchor).GetInstanceID();
			int globalTailId = (((Object)(object)tailAnchor != (Object)null && Object.op_Implicit((Object)(object)tailAnchor)) ? ((Object)tailAnchor).GetInstanceID() : int.MinValue);
			bool num = reachableFromSpawn.Any<(ExtractionPoint, int, float)>(((ExtractionPoint point, int id, float spawnPath) item) => item.id == globalFirstId);
			bool flag = (Object)(object)tailAnchor != (Object)null && Object.op_Implicit((Object)(object)tailAnchor) && globalTailId != globalFirstId && reachableFromSpawn.Any<(ExtractionPoint, int, float)>(((ExtractionPoint point, int id, float spawnPath) item) => item.id == globalTailId);
			(ExtractionPoint point, int id, float spawnPath) firstEntry;
			if (num)
			{
				firstEntry = reachableFromSpawn.First<(ExtractionPoint, int, float)>(((ExtractionPoint point, int id, float spawnPath) item) => item.id == globalFirstId);
			}
			else
			{
				List<(ExtractionPoint, int, float)> list3 = (flag ? reachableFromSpawn.Where<(ExtractionPoint, int, float)>(((ExtractionPoint point, int id, float spawnPath) item) => item.id != globalTailId).ToList() : reachableFromSpawn);
				if (list3.Count == 0)
				{
					list3 = reachableFromSpawn;
				}
				firstEntry = PickByMinSpawn(list3);
			}
			list.Add(firstEntry.point);
			bool tailUsable = flag && globalTailId != firstEntry.id;
			ExtractionPoint val = (tailUsable ? reachableFromSpawn.First<(ExtractionPoint, int, float)>(((ExtractionPoint point, int id, float spawnPath) item) => item.id == globalTailId).Item1 : null);
			List<ExtractionPoint> middleCandidates = (from item in reachableFromSpawn
				where item.id != firstEntry.id
				where !tailUsable || item.id != globalTailId
				select item.point).ToList();
			List<ExtractionPoint> list4 = FindBestMiddleOrder(firstEntry.point, middleCandidates, val);
			if (list4 == null)
			{
				return new List<ExtractionPoint>();
			}
			list.AddRange(list4);
			if ((Object)(object)val != (Object)null && Object.op_Implicit((Object)(object)val))
			{
				list.Add(val);
			}
			return list;
		}

		private List<ExtractionPoint> BuildEligibleCandidates(List<ExtractionPoint> allPoints, bool skipActivated)
		{
			List<ExtractionPoint> list = new List<ExtractionPoint>(allPoints.Count);
			for (int i = 0; i < allPoints.Count; i++)
			{
				ExtractionPoint val = allPoints[i];
				if (Object.op_Implicit((Object)(object)val) && !IsCompletedLikeState(ReadState(val)) && (!skipActivated || !IsMarkedActivated(val)))
				{
					list.Add(val);
				}
			}
			return list;
		}

		private bool IsMarkedActivated(ExtractionPoint point)
		{
			if (Object.op_Implicit((Object)(object)point))
			{
				return _activatedIds.Contains(((Object)point).GetInstanceID());
			}
			return false;
		}

		private List<(ExtractionPoint point, int id, float spawnPath)> GetReachableFromSpawn(List<ExtractionPoint> candidates, Vector3 spawnPos)
		{
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			List<(ExtractionPoint, int, float)> list = new List<(ExtractionPoint, int, float)>();
			for (int i = 0; i < candidates.Count; i++)
			{
				ExtractionPoint val = candidates[i];
				if (Object.op_Implicit((Object)(object)val) && TryGetSpawnPathLength(val, spawnPos, _spawnPathCache, _spawnPathInvalid, out var length))
				{
					list.Add((val, ((Object)val).GetInstanceID(), length));
				}
			}
			return list;
		}

		private List<ExtractionPoint>? FindBestMiddleOrder(ExtractionPoint first, List<ExtractionPoint> middleCandidates, ExtractionPoint? tail)
		{
			List<ExtractionPoint> middleCandidates2 = middleCandidates;
			ExtractionPoint tail2 = tail;
			if (!Object.op_Implicit((Object)(object)first))
			{
				return null;
			}
			if (middleCandidates2.Count == 0)
			{
				if ((Object)(object)tail2 == (Object)null || !Object.op_Implicit((Object)(object)tail2))
				{
					return new List<ExtractionPoint>();
				}
				if (!TryGetEdgePathLength(first, tail2, _edgePathCache, _edgePathInvalid, out var _))
				{
					return null;
				}
				return new List<ExtractionPoint>();
			}
			bool[] used = new bool[middleCandidates2.Count];
			List<ExtractionPoint> current = new List<ExtractionPoint>(middleCandidates2.Count);
			List<ExtractionPoint> best = null;
			float bestTotal = float.MaxValue;
			Search(first, 0f);
			return best;
			void Search(ExtractionPoint previous, float costSoFar)
			{
				if (!(costSoFar > bestTotal + 0.0001f))
				{
					if (current.Count == middleCandidates2.Count)
					{
						float num = costSoFar;
						if ((Object)(object)tail2 != (Object)null && Object.op_Implicit((Object)(object)tail2))
						{
							if (!TryGetEdgePathLength(previous, tail2, _edgePathCache, _edgePathInvalid, out var length2))
							{
								return;
							}
							num += length2;
						}
						if (num + 0.0001f < bestTotal || (Mathf.Abs(num - bestTotal) <= 0.0001f && IsBetterSameCostOrder(current, best)))
						{
							bestTotal = num;
							best = new List<ExtractionPoint>(current);
						}
					}
					else
					{
						for (int i = 0; i < middleCandidates2.Count; i++)
						{
							if (!used[i])
							{
								ExtractionPoint val = middleCandidates2[i];
								if (Object.op_Implicit((Object)(object)val) && TryGetEdgePathLength(previous, val, _edgePathCache, _edgePathInvalid, out var length3))
								{
									used[i] = true;
									current.Add(val);
									Search(val, costSoFar + length3);
									current.RemoveAt(current.Count - 1);
									used[i] = false;
								}
							}
						}
					}
				}
			}
		}

		private static bool IsBetterSameCostOrder(List<ExtractionPoint> current, List<ExtractionPoint>? best)
		{
			if (best == null)
			{
				return true;
			}
			int num = Math.Min(current.Count, best.Count);
			for (int i = 0; i < num; i++)
			{
				int instanceID = ((Object)current[i]).GetInstanceID();
				int instanceID2 = ((Object)best[i]).GetInstanceID();
				if (instanceID != instanceID2)
				{
					return instanceID < instanceID2;
				}
			}
			return current.Count < best.Count;
		}

		private static (ExtractionPoint point, int id, float spawnPath) PickByMinSpawn(List<(ExtractionPoint point, int id, float spawnPath)> list)
		{
			(ExtractionPoint, int, float) result = list[0];
			for (int i = 1; i < list.Count; i++)
			{
				(ExtractionPoint, int, float) tuple = list[i];
				if (tuple.Item3 + 0.0001f < result.Item3 || (Mathf.Abs(tuple.Item3 - result.Item3) <= 0.0001f && tuple.Item2 < result.Item2))
				{
					result = tuple;
				}
			}
			return result;
		}

		private static int FindIndexById(List<(ExtractionPoint point, int id, float spawnPath)> list, int? id)
		{
			if (!id.HasValue)
			{
				return -1;
			}
			for (int i = 0; i < list.Count; i++)
			{
				if (list[i].id == id.Value)
				{
					return i;
				}
			}
			return -1;
		}

		private static long MakeDirectedKey(int fromId, int toId)
		{
			return (long)(((ulong)(uint)fromId << 32) | (uint)toId);
		}

		private bool TryGetPathLength(Vector3 from, Vector3 to, out float length)
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: Expected O, but got Unknown
			//IL_0029: 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_0035: 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_0081: Unknown result type (might be due to invalid IL or missing references)
			length = 0f;
			try
			{
				if (!TrySampleNavPoint(from, out var sampled) || !TrySampleNavPoint(to, out var sampled2))
				{
					return false;
				}
				NavMeshPath val = new NavMeshPath();
				if (!NavMesh.CalculatePath(sampled, sampled2, -1, val) || (int)val.status != 0)
				{
					return false;
				}
				Vector3[] corners = val.corners;
				if (corners == null || corners.Length == 0)
				{
					return false;
				}
				if (corners.Length == 1)
				{
					length = 0f;
					return true;
				}
				float num = 0f;
				for (int i = 1; i < corners.Length; i++)
				{
					num += Vector3.Distance(corners[i - 1], corners[i]);
				}
				length = num;
				return true;
			}
			catch
			{
				return false;
			}
		}

		private static bool TrySampleNavPoint(Vector3 pos, out Vector3 sampled)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_001a: 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_0039: Unknown result type (might be due to invalid IL or missing references)
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			sampled = pos;
			NavMeshHit val = default(NavMeshHit);
			if (NavMesh.SamplePosition(pos, ref val, 3f, -1))
			{
				sampled = ((NavMeshHit)(ref val)).position;
				return true;
			}
			if (NavMesh.SamplePosition(pos, ref val, 10f, -1))
			{
				sampled = ((NavMeshHit)(ref val)).position;
				return true;
			}
			return false;
		}

		private bool TryGetSpawnPathLength(ExtractionPoint point, Vector3 spawnPos, Dictionary<int, float> cache, HashSet<int> invalid, out float length)
		{
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			//IL_003a: Unknown result type (might be due to invalid IL or missing references)
			length = 0f;
			if (!Object.op_Implicit((Object)(object)point))
			{
				return false;
			}
			int instanceID = ((Object)point).GetInstanceID();
			if (cache.TryGetValue(instanceID, out length))
			{
				return true;
			}
			if (invalid.Contains(instanceID))
			{
				return false;
			}
			if (TryGetPathLength(spawnPos, ((Component)point).transform.position, out length))
			{
				cache[instanceID] = length;
				return true;
			}
			invalid.Add(instanceID);
			return false;
		}

		private bool TryGetEdgePathLength(ExtractionPoint from, ExtractionPoint to, Dictionary<long, float> cache, HashSet<long> invalid, out float length)
		{
			//IL_005e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0069: Unknown result type (might be due to invalid IL or missing references)
			length = 0f;
			if (!Object.op_Implicit((Object)(object)from) || !Object.op_Implicit((Object)(object)to))
			{
				return false;
			}
			int instanceID = ((Object)from).GetInstanceID();
			int instanceID2 = ((Object)to).GetInstanceID();
			if (instanceID == instanceID2)
			{
				length = 0f;
				return true;
			}
			long num = MakeDirectedKey(instanceID, instanceID2);
			if (cache.TryGetValue(num, out length))
			{
				return true;
			}
			if (invalid.Contains(num))
			{
				return false;
			}
			if (TryGetPathLength(((Component)from).transform.position, ((Component)to).transform.position, out length))
			{
				cache[num] = length;
				return true;
			}
			invalid.Add(num);
			return false;
		}
	}
	internal sealed class ExtractionPointStateTracker
	{
		private static readonly FieldInfo? CurrentStateField = typeof(ExtractionPoint).GetField("currentState", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);

		private readonly Dictionary<int, State> _states = new Dictionary<int, State>();

		public void ResetForNewRound()
		{
			_states.Clear();
		}

		public void Record(ExtractionPoint point, State state)
		{
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			if (Object.op_Implicit((Object)(object)point))
			{
				_states[((Object)point).GetInstanceID()] = state;
			}
		}

		public State? TryGetState(ExtractionPoint point)
		{
			//IL_0029: 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)
			if (!Object.op_Implicit((Object)(object)point))
			{
				return null;
			}
			int instanceID = ((Object)point).GetInstanceID();
			if (_states.TryGetValue(instanceID, out var value))
			{
				return value;
			}
			State? result = TryReadInitialState(point);
			if (result.HasValue)
			{
				_states[instanceID] = result.Value;
			}
			return result;
		}

		public string ReadStateName(ExtractionPoint point)
		{
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			State? val = TryGetState(point);
			object obj;
			if (!val.HasValue)
			{
				obj = null;
			}
			else
			{
				State valueOrDefault = val.GetValueOrDefault();
				obj = ((object)(State)(ref valueOrDefault)).ToString();
			}
			if (obj == null)
			{
				obj = "";
			}
			return (string)obj;
		}

		private static State? TryReadInitialState(ExtractionPoint point)
		{
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_003a: Unknown result type (might be due to invalid IL or missing references)
			//IL_003b: Unknown result type (might be due to invalid IL or missing references)
			if (!Object.op_Implicit((Object)(object)point) || CurrentStateField == null)
			{
				return null;
			}
			try
			{
				object value = CurrentStateField.GetValue(point);
				if (value is State)
				{
					return (State)value;
				}
			}
			catch
			{
				return null;
			}
			return null;
		}
	}
}