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 HarmonyLib;
using Microsoft.CodeAnalysis;
using REPO_Active.Reflection;
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: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("REPO_Active")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("5.1.0.0")]
[assembly: AssemblyInformationalVersion("5.1.0+fd2a9afffcbc228da2de632ea7f5cf7cb58a1c3c")]
[assembly: AssemblyProduct("REPO_Active")]
[assembly: AssemblyTitle("REPO_Active")]
[assembly: AssemblyVersion("5.1.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.1.0")]
public sealed class Plugin : BaseUnityPlugin
{
public const string PluginGuid = "angelcomilk.repo_active";
public const string PluginName = "REPO_Active";
public const string PluginVersion = "5.1.0";
private ConfigEntry<bool> _autoActivate;
private ConfigEntry<KeyCode> _keyActivateNearest;
private ConfigEntry<bool> _discoverAllPoints;
private ExtractionPointScanner _scanner;
private ExtractionPointInvoker _invoker;
private Harmony? _harmony;
private static Plugin? _instance;
private float _autoTimer;
private float _discoverTimer;
private float _autoReadyTime = -1f;
private float _discoverReadyTime = -1f;
private bool _autoPrimed;
private readonly HashSet<int> _deferredMarking = new HashSet<int>();
private readonly List<Component> _playerCache = new List<Component>();
private readonly List<Vector3> _playerLastPos = new List<Vector3>();
private int _playerCacheHash;
private int _playerListEmptyStreak;
private int _lastPlayerCount = -1;
private float _lastBaseInterval = 0.5f;
private int _lastHostPosCount = -1;
private int _lastAutoBufferBucket = int.MinValue;
private int _lastDiscoverBufferBucket = int.MinValue;
private string _lastBusyInfo = "";
private int _lastBusyCount = -1;
private float _lastBusyLogTime = -1f;
private bool? _lastTailHoldState;
private const float RESCAN_COOLDOWN = 0.6f;
private const bool SKIP_ACTIVATED = true;
private const float AUTO_INTERVAL = 5f;
private const float DISCOVER_INTERVAL_BASE = 0.5f;
private const float DISCOVER_INTERVAL_4_6 = 1f;
private const float DISCOVER_INTERVAL_7_9 = 1.5f;
private const float DISCOVER_INTERVAL_10_12 = 2f;
private const float DISCOVER_INTERVAL_MAX = 3f;
private const float DISCOVER_RADIUS = 20f;
private const float AUTO_READY_BUFFER = 30f;
private void Awake()
{
_autoActivate = ((BaseUnityPlugin)this).Config.Bind<bool>("Auto", "AutoActivate", false, "Auto activate when idle.");
_keyActivateNearest = ((BaseUnityPlugin)this).Config.Bind<KeyCode>("Keybinds", "ActivateNearest", (KeyCode)284, "Press to activate next extraction point (uses OnClick via reflection).");
_discoverAllPoints = ((BaseUnityPlugin)this).Config.Bind<bool>("Discovery", "DiscoverAllPoints", false, "If true, treat all extraction points as discovered.");
_invoker = new ExtractionPointInvoker();
_scanner = new ExtractionPointScanner(0.6f);
_instance = this;
InstallEventPatches();
SceneManager.sceneLoaded += OnSceneLoaded;
}
private void OnDestroy()
{
try
{
SceneManager.sceneLoaded -= OnSceneLoaded;
}
catch
{
}
try
{
UninstallEventPatches();
}
catch
{
}
if (_instance == this)
{
_instance = null;
}
}
private void Update()
{
//IL_0006: 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)
//IL_009b: Unknown result type (might be due to invalid IL or missing references)
//IL_00a7: 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_00bd: Unknown result type (might be due to invalid IL or missing references)
if (Input.GetKeyDown(_keyActivateNearest.Value) && !_autoActivate.Value)
{
ActivateNearest();
}
_discoverTimer += Time.deltaTime;
float discoveryInterval = GetDiscoveryInterval();
if (_discoverTimer >= discoveryInterval)
{
_discoverTimer = 0f;
DiscoveryTick();
}
if (!_autoActivate.Value)
{
return;
}
if (_autoReadyTime < 0f)
{
if (_scanner.EnsureReady())
{
List<Component> list = _scanner.ScanAndGetAllPoints();
Vector3 referencePos = _scanner.GetReferencePos();
if (list.Count > 0 && referencePos != Vector3.zero)
{
_scanner.CaptureSpawnPosIfNeeded(referencePos);
_autoReadyTime = Time.realtimeSinceStartup;
_autoTimer = 0f;
}
}
return;
}
if (Time.realtimeSinceStartup - _autoReadyTime >= 30f)
{
_lastAutoBufferBucket = int.MinValue;
if (!_autoPrimed)
{
PrimeFirstPointIfAlreadyActivated();
_autoPrimed = true;
}
_autoTimer += Time.deltaTime;
if (_autoTimer >= 5f)
{
_autoTimer = 0f;
AutoActivateIfIdle();
}
return;
}
float num = 30f - (Time.realtimeSinceStartup - _autoReadyTime);
if (num > 0f)
{
int num2 = (int)(num / 5f);
if (num2 != _lastAutoBufferBucket)
{
_lastAutoBufferBucket = num2;
}
}
}
private void OnSceneLoaded(Scene scene, LoadSceneMode mode)
{
_autoReadyTime = -1f;
_discoverReadyTime = Time.realtimeSinceStartup;
_autoPrimed = false;
_autoTimer = 0f;
_discoverTimer = 0f;
_lastTailHoldState = null;
_scanner.ResetForNewRound();
_lastPlayerCount = -1;
_lastBaseInterval = 0.5f;
RefreshDiscoveryIntervalFromCurrentPlayerCount("scene init", invalidateCache: true);
}
private void DiscoveryTick()
{
//IL_0020: Unknown result type (might be due to invalid IL or missing references)
//IL_0025: Unknown result type (might be due to invalid IL or missing references)
//IL_002c: 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)
//IL_010e: Unknown result type (might be due to invalid IL or missing references)
if (!_scanner.EnsureReady())
{
return;
}
List<Component> list = _scanner.ScanAndGetAllPoints();
Vector3 referencePos = _scanner.GetReferencePos();
_scanner.CaptureSpawnPosIfNeeded(referencePos);
if (list.Count == 0)
{
return;
}
if (_discoverAllPoints.Value)
{
_scanner.MarkAllDiscovered(list);
return;
}
if (_discoverReadyTime < 0f)
{
_discoverReadyTime = Time.realtimeSinceStartup;
}
if (Time.realtimeSinceStartup - _discoverReadyTime < 30f)
{
int num = (int)((30f - (Time.realtimeSinceStartup - _discoverReadyTime)) / 5f);
if (num != _lastDiscoverBufferBucket)
{
_lastDiscoverBufferBucket = num;
}
return;
}
_lastDiscoverBufferBucket = int.MinValue;
if (_scanner.DiscoveredCount >= list.Count)
{
return;
}
List<Vector3> list2 = TryGetAllPlayerPositionsHost();
if (list2.Count == 0)
{
_playerListEmptyStreak++;
_scanner.UpdateDiscovered(referencePos, 20f);
return;
}
_playerListEmptyStreak = 0;
for (int i = 0; i < list2.Count; i++)
{
_scanner.UpdateDiscovered(list2[i], 20f);
}
if (list2.Count != _lastHostPosCount)
{
_lastHostPosCount = list2.Count;
}
}
private void AutoActivateIfIdle()
{
if (_scanner.EnsureReady())
{
ActivateNearest();
}
}
private void ActivateNearest()
{
//IL_0077: 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_0083: 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_0094: Unknown result type (might be due to invalid IL or missing references)
//IL_00b2: Unknown result type (might be due to invalid IL or missing references)
//IL_0203: Unknown result type (might be due to invalid IL or missing references)
//IL_01f2: Unknown result type (might be due to invalid IL or missing references)
//IL_00fe: Unknown result type (might be due to invalid IL or missing references)
//IL_0230: Unknown result type (might be due to invalid IL or missing references)
if (!_scanner.EnsureReady())
{
return;
}
List<Component> list = _scanner.ScanAndGetAllPoints();
if (_scanner.TryGetActivatingInfo(list, out string info, out int busyCount))
{
float realtimeSinceStartup = Time.realtimeSinceStartup;
if (info != _lastBusyInfo || busyCount != _lastBusyCount || realtimeSinceStartup - _lastBusyLogTime > 2f)
{
_lastBusyInfo = info;
_lastBusyCount = busyCount;
_lastBusyLogTime = realtimeSinceStartup;
}
return;
}
Vector3 referencePos = _scanner.GetReferencePos();
_scanner.CaptureSpawnPosIfNeeded(referencePos);
Vector3 spawnPos = _scanner.GetSpawnPos();
if (_discoverAllPoints.Value)
{
_scanner.MarkAllDiscovered(list);
}
else
{
UpdateDiscoveredFromCachedPlayers(referencePos);
}
List<Component> list2 = (List<Component>)(_discoverAllPoints.Value ? ((IList)list) : ((IList)_scanner.FilterDiscovered(list)));
List<Component> allPoints = list2;
if (!_discoverAllPoints.Value && list2.Count > 1 && _scanner.TryGetGlobalAnchorsNoCache(list, spawnPos, out Component _, out Component tailAnchor) && (Object)(object)tailAnchor != (Object)null)
{
int instanceID = ((Object)tailAnchor).GetInstanceID();
bool flag = false;
for (int i = 0; i < list2.Count; i++)
{
if (Object.op_Implicit((Object)(object)list2[i]) && ((Object)list2[i]).GetInstanceID() == instanceID)
{
flag = true;
break;
}
}
if (flag)
{
List<Component> list3 = new List<Component>();
int num = 0;
for (int j = 0; j < list2.Count; j++)
{
Component val = list2[j];
if (Object.op_Implicit((Object)(object)val) && ((Object)val).GetInstanceID() != instanceID)
{
list3.Add(val);
if (!ExtractionPointScanner.IsCompletedLikeState(_scanner.ReadStateName(val)))
{
num++;
}
}
}
if (list3.Count > 0 && num > 0)
{
allPoints = list3;
}
}
}
List<Component> list4 = (_discoverAllPoints.Value ? _scanner.BuildPlanDiscoverAllFixedAnchors(list, spawnPos, skipActivated: true) : _scanner.BuildStage1PlannedList(allPoints, spawnPos, skipActivated: true));
if (list4.Count == 0)
{
return;
}
Component val2 = list4[0];
if ((_discoverAllPoints.Value || !ShouldHoldTailPointActivation(list, spawnPos, list4, val2, out string _)) && _invoker.InvokeOnClick(val2))
{
string text = _scanner.ReadStateName(val2);
if (!string.IsNullOrEmpty(text) && !ExtractionPointScanner.IsIdleLikeState(text) && !ExtractionPointScanner.IsCompletedLikeState(text))
{
_scanner.MarkActivated(val2);
}
else
{
TryDeferredMarkActivated(val2);
}
}
}
private void TryDeferredMarkActivated(Component ep)
{
if (!((Object)(object)ep == (Object)null))
{
int instanceID = ((Object)ep).GetInstanceID();
if (_deferredMarking.Add(instanceID))
{
((MonoBehaviour)this).StartCoroutine(DeferredMarkActivated(ep, instanceID));
}
}
}
private IEnumerator DeferredMarkActivated(Component ep, int id)
{
try
{
if ((Object)(object)ep == (Object)null)
{
yield break;
}
float[] waits = new float[5] { 0.15f, 0.25f, 0.35f, 0.35f, 0.4f };
for (int i = 0; i < waits.Length; i++)
{
if (waits[i] > 0f)
{
yield return (object)new WaitForSeconds(waits[i]);
}
if ((Object)(object)ep == (Object)null)
{
break;
}
string text = _scanner.ReadStateName(ep);
if (!string.IsNullOrEmpty(text) && !ExtractionPointScanner.IsIdleLikeState(text) && !ExtractionPointScanner.IsCompletedLikeState(text))
{
_scanner.MarkActivated(ep);
break;
}
if (i == 0)
{
yield return null;
if ((Object)(object)ep == (Object)null)
{
break;
}
string text2 = _scanner.ReadStateName(ep);
if (!string.IsNullOrEmpty(text2))
{
}
if (!string.IsNullOrEmpty(text2) && !ExtractionPointScanner.IsIdleLikeState(text2) && !ExtractionPointScanner.IsCompletedLikeState(text2))
{
_scanner.MarkActivated(ep);
break;
}
}
}
}
finally
{
_deferredMarking.Remove(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<Component> list = _scanner.ScanAndGetAllPoints();
if (list.Count == 0)
{
return;
}
Vector3 referencePos = _scanner.GetReferencePos();
_scanner.CaptureSpawnPosIfNeeded(referencePos);
if (_discoverAllPoints.Value)
{
_scanner.MarkAllDiscovered(list);
}
else
{
_scanner.UpdateDiscovered(referencePos, 20f);
}
List<Component> allPoints = (List<Component>)(_discoverAllPoints.Value ? ((IList)list) : ((IList)_scanner.FilterDiscovered(list)));
Vector3 spawnPos = _scanner.GetSpawnPos();
List<Component> list2 = (_discoverAllPoints.Value ? _scanner.BuildPlanDiscoverAllFixedAnchors(list, spawnPos, skipActivated: true) : _scanner.BuildStage1PlannedList(allPoints, spawnPos, skipActivated: true));
if (list2.Count != 0)
{
Component ep = list2[0];
string text = _scanner.ReadStateName(ep);
if (!string.IsNullOrEmpty(text) && !ExtractionPointScanner.IsIdleLikeState(text))
{
_scanner.MarkActivated(ep);
}
}
}
private List<Vector3> TryGetAllPlayerPositionsHost()
{
//IL_0290: Unknown result type (might be due to invalid IL or missing references)
//IL_0305: Unknown result type (might be due to invalid IL or missing references)
//IL_030a: Unknown result type (might be due to invalid IL or missing references)
//IL_030d: Unknown result type (might be due to invalid IL or missing references)
//IL_031c: Unknown result type (might be due to invalid IL or missing references)
List<Vector3> list = new List<Vector3>();
try
{
Type type = Type.GetType("Photon.Pun.PhotonNetwork, PhotonUnityNetworking");
if (type == null)
{
return list;
}
PropertyInfo property = type.GetProperty("InRoom");
PropertyInfo property2 = type.GetProperty("IsMasterClient");
bool flag = default(bool);
int num;
if (property != null)
{
object value = property.GetValue(null);
if (value is bool)
{
flag = (bool)value;
num = 1;
}
else
{
num = 0;
}
}
else
{
num = 0;
}
int num2 = num & (flag ? 1 : 0);
bool flag2 = default(bool);
int num3;
if (property2 != null)
{
object value = property2.GetValue(null);
if (value is bool)
{
flag2 = (bool)value;
num3 = 1;
}
else
{
num3 = 0;
}
}
else
{
num3 = 0;
}
bool flag3 = (byte)((uint)num3 & (flag2 ? 1u : 0u)) != 0;
if (num2 == 0 || !flag3)
{
return list;
}
Type type2 = Type.GetType("GameDirector, Assembly-CSharp");
if (type2 == null)
{
return list;
}
object obj = null;
PropertyInfo property3 = type2.GetProperty("instance", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
if (property3 != null)
{
obj = property3.GetValue(null, null);
}
if (obj == null)
{
FieldInfo field = type2.GetField("instance", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
if (field != null)
{
obj = field.GetValue(null);
}
}
if (obj == null)
{
return list;
}
object obj2 = null;
PropertyInfo property4 = type2.GetProperty("PlayerList", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
if (property4 != null)
{
obj2 = property4.GetValue(obj, null);
}
if (obj2 == null)
{
FieldInfo field2 = type2.GetField("PlayerList", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
if (field2 != null)
{
obj2 = field2.GetValue(obj);
}
}
if (obj2 == null)
{
return list;
}
if (!(obj2 is IEnumerable enumerable))
{
return list;
}
List<Component> list2 = new List<Component>();
int num4 = 17;
foreach (object item in enumerable)
{
if (item != null)
{
Component val = ExtractPlayerComponent(item);
if (!((Object)(object)val == (Object)null) && !((Object)(object)val.transform == (Object)null))
{
list2.Add(val);
num4 = num4 * 31 + ((Object)val).GetInstanceID();
}
}
}
if (list2.Count == 0)
{
return list;
}
if (num4 != _playerCacheHash || _playerCache.Count != list2.Count)
{
_playerCacheHash = num4;
_playerCache.Clear();
_playerCache.AddRange(list2);
_playerLastPos.Clear();
for (int i = 0; i < _playerCache.Count; i++)
{
_playerLastPos.Add(_playerCache[i].transform.position);
}
}
for (int j = 0; j < _playerCache.Count; j++)
{
Component val2 = _playerCache[j];
if ((Object)(object)val2 == (Object)null || (Object)(object)val2.transform == (Object)null)
{
_playerCache.Clear();
_playerLastPos.Clear();
_playerCacheHash = 0;
return list;
}
Vector3 position = val2.transform.position;
list.Add(position);
_playerLastPos[j] = position;
}
return list;
}
catch
{
return list;
}
}
private Component? ExtractPlayerComponent(object p)
{
Component val = (Component)((p is Component) ? p : null);
if (val != null && (Object)(object)val.transform != (Object)null)
{
return val;
}
Type type = p.GetType();
object obj = null;
PropertyInfo property = type.GetProperty("PlayerAvatar", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
if (property != null)
{
obj = property.GetValue(p, null);
}
if (obj == null)
{
FieldInfo field = type.GetField("PlayerAvatar", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
if (field != null)
{
obj = field.GetValue(p);
}
}
if (obj == null)
{
return null;
}
Component val2 = (Component)((obj is Component) ? obj : null);
if (val2 != null && (Object)(object)val2.transform != (Object)null)
{
return val2;
}
PropertyInfo property2 = obj.GetType().GetProperty("transform", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
if (!(property2 != null))
{
return null;
}
object? value = property2.GetValue(obj, null);
return (Component?)((value is Transform) ? value : null);
}
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<Component> allPoints, Vector3 spawnPos, List<Component> plan, Component next, out string reason)
{
//IL_002a: Unknown result type (might be due to invalid IL or missing references)
reason = "";
if (_discoverAllPoints.Value)
{
return false;
}
if ((Object)(object)next == (Object)null)
{
return false;
}
if (!_scanner.TryGetGlobalAnchorsNoCache(allPoints, spawnPos, out Component firstAnchor, out Component tailAnchor))
{
return false;
}
if ((Object)(object)tailAnchor == (Object)null)
{
return false;
}
int num = (((Object)(object)firstAnchor != (Object)null) ? ((Object)firstAnchor).GetInstanceID() : int.MinValue);
int instanceID = ((Object)tailAnchor).GetInstanceID();
bool flag = ((Object)next).GetInstanceID() == instanceID;
List<string> list = new List<string>();
for (int i = 0; i < allPoints.Count; i++)
{
Component val = allPoints[i];
if (!Object.op_Implicit((Object)(object)val))
{
continue;
}
int instanceID2 = ((Object)val).GetInstanceID();
if (instanceID2 != num && instanceID2 != instanceID)
{
string text = _scanner.ReadStateName(val);
if (!ExtractionPointScanner.IsCompletedLikeState(text))
{
list.Add($"{((Object)val.gameObject).name}#{((Object)val).GetInstanceID()}({text})");
}
}
}
bool flag2 = flag && list.Count > 0;
string arg = ((plan == null || plan.Count == 0) ? "-" : string.Join(" -> ", from x in plan
where (Object)(object)x != (Object)null
select $"{((Object)x.gameObject).name}#{((Object)x).GetInstanceID()}"));
_lastTailHoldState = flag2;
if (!flag2)
{
return false;
}
reason = string.Format("tail point locked, pendingOthers={0}, pending=[{1}], queue={2}", list.Count, string.Join(", ", list), arg);
return true;
}
private void HandleRoomPopulationChangedEvent(string reason)
{
RefreshDiscoveryIntervalFromCurrentPlayerCount(reason, invalidateCache: true);
}
private void RefreshDiscoveryIntervalFromCurrentPlayerCount(string reason, bool invalidateCache)
{
int num = GetPlayerCountHost();
if (num < 1)
{
num = 1;
}
if (num != _lastPlayerCount)
{
_lastPlayerCount = num;
_lastBaseInterval = ComputeDiscoveryInterval(num);
}
if (invalidateCache)
{
_playerCache.Clear();
_playerLastPos.Clear();
_playerCacheHash = 0;
}
}
private float GetDiscoveryInterval()
{
if (_discoverAllPoints.Value)
{
return 0.5f;
}
if (_lastPlayerCount < 1)
{
RefreshDiscoveryIntervalFromCurrentPlayerCount("lazy init", invalidateCache: false);
}
float lastBaseInterval = _lastBaseInterval;
if (_playerListEmptyStreak <= 0)
{
return lastBaseInterval;
}
float num = 1f + (float)Math.Min(_playerListEmptyStreak, 10) * 0.2f;
float num2 = lastBaseInterval * num;
if (!(num2 > 3f))
{
return num2;
}
return 3f;
}
private float ComputeDiscoveryInterval(int players)
{
if (players <= 3)
{
return 0.5f;
}
if (players <= 6)
{
return 1f;
}
if (players <= 9)
{
return 1.5f;
}
return 2f;
}
private static void OnPlayerEnteredRoomPostfix()
{
_instance?.HandleRoomPopulationChangedEvent("player entered");
}
private static void OnPlayerLeftRoomPostfix()
{
_instance?.HandleRoomPopulationChangedEvent("player left");
}
private void InstallEventPatches()
{
//IL_0006: Unknown result type (might be due to invalid IL or missing references)
//IL_0010: Expected O, but got Unknown
//IL_0056: Unknown result type (might be due to invalid IL or missing references)
//IL_0063: Expected O, but got Unknown
//IL_009f: Unknown result type (might be due to invalid IL or missing references)
//IL_00ac: Expected O, but got Unknown
try
{
_harmony = new Harmony("angelcomilk.repo_active.population");
Type type = AccessTools.TypeByName("NetworkManager");
MethodInfo methodInfo = ((type != null) ? AccessTools.DeclaredMethod(type, "OnPlayerEnteredRoom", (Type[])null, (Type[])null) : null);
if (methodInfo != null)
{
_harmony.Patch((MethodBase)methodInfo, (HarmonyMethod)null, new HarmonyMethod(typeof(Plugin), "OnPlayerEnteredRoomPostfix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
}
MethodInfo methodInfo2 = ((type != null) ? AccessTools.DeclaredMethod(type, "OnPlayerLeftRoom", (Type[])null, (Type[])null) : null);
if (methodInfo2 != null)
{
_harmony.Patch((MethodBase)methodInfo2, (HarmonyMethod)null, new HarmonyMethod(typeof(Plugin), "OnPlayerLeftRoomPostfix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
}
}
catch (Exception)
{
}
}
private void UninstallEventPatches()
{
try
{
Harmony? harmony = _harmony;
if (harmony != null)
{
harmony.UnpatchSelf();
}
_harmony = null;
}
catch
{
}
}
private int GetPlayerCountHost()
{
try
{
Type type = Type.GetType("Photon.Pun.PhotonNetwork, PhotonUnityNetworking");
if (type == null)
{
return 1;
}
PropertyInfo property = type.GetProperty("InRoom");
PropertyInfo property2 = type.GetProperty("IsMasterClient");
PropertyInfo property3 = type.GetProperty("PlayerList");
bool flag = default(bool);
int num;
if (property != null)
{
object value = property.GetValue(null);
if (value is bool)
{
flag = (bool)value;
num = 1;
}
else
{
num = 0;
}
}
else
{
num = 0;
}
int num2 = num & (flag ? 1 : 0);
bool flag2 = default(bool);
int num3;
if (property2 != null)
{
object value = property2.GetValue(null);
if (value is bool)
{
flag2 = (bool)value;
num3 = 1;
}
else
{
num3 = 0;
}
}
else
{
num3 = 0;
}
bool flag3 = (byte)((uint)num3 & (flag2 ? 1u : 0u)) != 0;
if (num2 == 0 || !flag3)
{
return 1;
}
if (property3 != null && property3.GetValue(null) is Array array && array.Length > 0)
{
return array.Length;
}
}
catch
{
}
return 1;
}
}
}
namespace REPO_Active.Runtime
{
public sealed class ExtractionPointScanner
{
private Type? _epType;
private readonly List<Component> _cached = new List<Component>();
private float _lastScanRealtime;
private int _lastScanCount = -1;
private Vector3? _spawnPos;
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 int? _firstAnchorId;
private int? _lastAnchorId;
private static readonly Dictionary<string, bool> _idleCache = new Dictionary<string, bool>(StringComparer.OrdinalIgnoreCase);
private static readonly Dictionary<string, bool> _completeCache = new Dictionary<string, bool>(StringComparer.OrdinalIgnoreCase);
public float RescanCooldown { get; set; }
public int CachedCount => _cached.Count;
public int DiscoveredCount => _discovered.Count;
public ExtractionPointScanner(float rescanCooldown)
{
RescanCooldown = rescanCooldown;
}
public bool EnsureReady()
{
if (_epType != null)
{
return true;
}
_epType = AppDomain.CurrentDomain.GetAssemblies().SelectMany(delegate(Assembly a)
{
try
{
return a.GetTypes();
}
catch
{
return Array.Empty<Type>();
}
}).FirstOrDefault((Type t) => t != null && t.Name == "ExtractionPoint");
return _epType != null;
}
public void ScanIfNeeded(bool force)
{
try
{
float realtimeSinceStartup = Time.realtimeSinceStartup;
float num = realtimeSinceStartup;
if (!force && num - _lastScanRealtime < RescanCooldown)
{
return;
}
_lastScanRealtime = num;
if (EnsureReady())
{
Object[] source = Object.FindObjectsOfType(_epType);
_cached.Clear();
_cached.AddRange(from c in source.OfType<Component>()
where (Object)(object)c != (Object)null
select c);
_ = Time.realtimeSinceStartup;
if (_lastScanCount != _cached.Count)
{
_lastScanCount = _cached.Count;
}
}
}
catch (Exception)
{
}
}
public Vector3 GetReferencePos()
{
//IL_0017: 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)
//IL_004c: 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_003f: 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)
try
{
if ((Object)(object)Camera.main != (Object)null)
{
return ((Component)Camera.main).transform.position;
}
}
catch
{
}
try
{
GameObject val = GameObject.FindWithTag("Player");
if ((Object)(object)val != (Object)null)
{
return val.transform.position;
}
}
catch
{
}
return Vector3.zero;
}
public void MarkAllDiscovered(List<Component> allPoints)
{
int count = _discovered.Count;
for (int i = 0; i < allPoints.Count; i++)
{
Component val = allPoints[i];
if (Object.op_Implicit((Object)(object)val))
{
_discovered.Add(((Object)val).GetInstanceID());
}
}
_ = _discovered.Count - count;
_ = 0;
}
public void UpdateDiscovered(Vector3 refPos, float radius)
{
//IL_0001: Unknown result type (might be due to invalid IL or missing references)
UpdateDiscoveredDetailed(refPos, radius, null);
}
public int UpdateDiscoveredDetailed(Vector3 refPos, float radius, List<Component>? newly)
{
//IL_0049: 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)
//IL_005a: Unknown result type (might be due to invalid IL or missing references)
if (_cached.Count == 0)
{
return 0;
}
int count = _discovered.Count;
for (int i = 0; i < _cached.Count; i++)
{
Component val = _cached[i];
if (!Object.op_Implicit((Object)(object)val))
{
continue;
}
int instanceID = ((Object)val).GetInstanceID();
if (!_discovered.Contains(instanceID))
{
Vector3 val2 = refPos - val.transform.position;
if (((Vector3)(ref val2)).sqrMagnitude <= radius * radius)
{
_discovered.Add(instanceID);
newly?.Add(val);
}
}
}
int num = _discovered.Count - count;
if (num > 0)
{
}
return num;
}
public List<Component> FilterDiscovered(List<Component> allPoints)
{
List<Component> list = new List<Component>();
for (int i = 0; i < allPoints.Count; i++)
{
Component 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_000e: Unknown result type (might be due to invalid IL or missing references)
//IL_000f: Unknown result type (might be due to invalid IL or missing references)
//IL_001d: Unknown result type (might be due to invalid IL or missing references)
if (!_spawnPos.HasValue && !(refPos == Vector3.zero))
{
_spawnPos = refPos;
}
}
public List<Component> ScanAndGetAllPoints()
{
ScanIfNeeded(force: true);
return _cached.Where((Component c) => (Object)(object)c != (Object)null).ToList();
}
public bool TryGetRoundAnchors(List<Component> allPoints, Vector3 spawnPos, out Component? firstAnchor, out Component? 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<Component> allPoints, Vector3 spawnPos, out Component? firstAnchor, out Component? tailAnchor)
{
//IL_0014: Unknown result type (might be due to invalid IL or missing references)
//IL_0015: Unknown result type (might be due to invalid IL or missing references)
//IL_0044: Unknown result type (might be due to invalid IL or missing references)
firstAnchor = null;
tailAnchor = null;
if (allPoints == null || allPoints.Count == 0)
{
return false;
}
if (spawnPos == Vector3.zero)
{
return false;
}
List<(Component, int, float)> list2 = new List<(Component, int, float)>();
for (int i = 0; i < allPoints.Count; i++)
{
Component val = allPoints[i];
if (Object.op_Implicit((Object)(object)val) && TryGetSpawnPathLength(val, spawnPos, _spawnPathCache, _spawnPathInvalid, out var length))
{
list2.Add((val, ((Object)val).GetInstanceID(), length));
}
}
if (list2.Count == 0)
{
return false;
}
(Component, int, float) tuple = PickByMinSpawn(list2);
firstAnchor = tuple.Item1;
List<(Component, int, float)> list3 = new List<(Component, int, float)>();
for (int j = 0; j < list2.Count; j++)
{
if (list2[j].Item2 != tuple.Item2)
{
list3.Add(list2[j]);
}
}
if (list3.Count == 0)
{
return true;
}
(tailAnchor, _, _) = PickByMinSpawn(list3);
return true;
static (Component ep, int id, float spawnPath) PickByMinSpawn(List<(Component ep, int id, float spawnPath)> list)
{
(Component, int, float) result = list[0];
for (int k = 1; k < list.Count; k++)
{
(Component, int, float) tuple3 = list[k];
if (tuple3.Item3 + 0.0001f < result.Item3 || (Mathf.Abs(tuple3.Item3 - result.Item3) <= 0.0001f && tuple3.Item2 < result.Item2))
{
result = tuple3;
}
}
return result;
}
}
public void ResetForNewRound()
{
_cached.Clear();
_activatedIds.Clear();
_discovered.Clear();
_spawnPos = null;
_spawnPathCache.Clear();
_spawnPathInvalid.Clear();
_edgePathCache.Clear();
_edgePathInvalid.Clear();
_firstAnchorId = null;
_lastAnchorId = null;
_lastScanRealtime = 0f;
_lastScanCount = -1;
}
public void MarkActivated(Component ep)
{
if (!((Object)(object)ep == (Object)null))
{
_activatedIds.Add(((Object)ep).GetInstanceID());
}
}
private bool IsMarkedActivated(Component ep)
{
if ((Object)(object)ep == (Object)null)
{
return false;
}
return _activatedIds.Contains(((Object)ep).GetInstanceID());
}
public bool ReconcileActivatedMarks(List<Component> allPoints)
{
if (allPoints == null || allPoints.Count == 0)
{
if (_activatedIds.Count == 0)
{
return false;
}
_activatedIds.Clear();
return true;
}
HashSet<int> liveActive = new HashSet<int>();
for (int i = 0; i < allPoints.Count; i++)
{
Component val = allPoints[i];
if (Object.op_Implicit((Object)(object)val))
{
string text = ReadStateName(val);
if (!string.IsNullOrEmpty(text) && !IsIdleLikeState(text) && !IsCompletedLikeState(text))
{
liveActive.Add(((Object)val).GetInstanceID());
}
}
}
bool result = false;
if (_activatedIds.Count > 0)
{
List<int> list = _activatedIds.Where((int id) => !liveActive.Contains(id)).ToList();
if (list.Count > 0)
{
for (int j = 0; j < list.Count; j++)
{
_activatedIds.Remove(list[j]);
}
result = true;
}
}
foreach (int item in liveActive)
{
if (_activatedIds.Add(item))
{
result = true;
}
}
return result;
}
public bool IsAnyExtractionPointActivating(List<Component> allPoints)
{
string info;
int busyCount;
return TryGetActivatingInfo(allPoints, out info, out busyCount);
}
public bool TryGetActivatingInfo(List<Component> allPoints, out string info, out int busyCount)
{
info = "";
busyCount = 0;
if (allPoints == null || allPoints.Count == 0)
{
return false;
}
for (int i = 0; i < allPoints.Count; i++)
{
Component val = allPoints[i];
if (!Object.op_Implicit((Object)(object)val))
{
continue;
}
try
{
Type type = ((object)val).GetType();
FieldInfo field = type.GetField("currentState", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
PropertyInfo property = type.GetProperty("currentState", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
object obj = null;
if (property != null)
{
obj = property.GetValue(val, null);
}
if (obj == null && field != null)
{
obj = field.GetValue(val);
}
if (obj == null)
{
continue;
}
string text = obj.ToString() ?? "";
if (text.Length != 0 && !IsIdleLikeState(text) && !IsCompletedLikeState(text))
{
busyCount++;
if (string.IsNullOrEmpty(info))
{
info = ((Object)val.gameObject).name + " state=" + text;
}
}
}
catch
{
if (busyCount == 0)
{
busyCount = 1;
}
if (string.IsNullOrEmpty(info))
{
info = "state read failed";
}
return true;
}
}
return busyCount > 0;
}
internal static bool IsIdleLikeState(string stateName)
{
if (string.IsNullOrEmpty(stateName))
{
return false;
}
if (_idleCache.TryGetValue(stateName, out var value))
{
return value;
}
bool flag = stateName.IndexOf("Idle", StringComparison.OrdinalIgnoreCase) >= 0;
_idleCache[stateName] = flag;
return flag;
}
internal static bool IsCompletedLikeState(string stateName)
{
if (string.IsNullOrEmpty(stateName))
{
return false;
}
if (_completeCache.TryGetValue(stateName, out var value))
{
return value;
}
string text = stateName.ToLowerInvariant();
bool flag = text.Contains("success") || text.Contains("complete") || text.Contains("submitted") || text.Contains("finish") || text.Contains("done");
_completeCache[stateName] = flag;
return flag;
}
public string ReadStateName(Component ep)
{
if (!Object.op_Implicit((Object)(object)ep))
{
return "";
}
try
{
Type type = ((object)ep).GetType();
FieldInfo field = type.GetField("currentState", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
PropertyInfo property = type.GetProperty("currentState", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
object obj = null;
if (property != null)
{
obj = property.GetValue(ep, null);
}
if (obj == null && field != null)
{
obj = field.GetValue(ep);
}
if (obj == null)
{
return "";
}
return obj.ToString() ?? "";
}
catch
{
return "";
}
}
public List<Component> BuildStage1PlannedList(List<Component> allPoints, Vector3 spawnPos, bool skipActivated)
{
//IL_0021: Unknown result type (might be due to invalid IL or missing references)
//IL_0022: 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)
float realtimeSinceStartup = Time.realtimeSinceStartup;
List<Component> list2 = new List<Component>();
if (allPoints == null || allPoints.Count == 0)
{
return list2;
}
if (spawnPos == Vector3.zero)
{
return list2;
}
List<Component> list3 = new List<Component>(allPoints.Count);
for (int i = 0; i < allPoints.Count; i++)
{
Component val = allPoints[i];
if (Object.op_Implicit((Object)(object)val) && !IsCompletedLikeState(ReadStateName(val)) && (!skipActivated || !IsMarkedActivated(val)))
{
list3.Add(val);
}
}
if (list3.Count == 0)
{
return list2;
}
List<(Component, int, float)> list4 = new List<(Component, int, float)>();
for (int j = 0; j < list3.Count; j++)
{
Component val2 = list3[j];
if (TryGetSpawnPathLength(val2, spawnPos, _spawnPathCache, _spawnPathInvalid, out var length))
{
list4.Add((val2, ((Object)val2).GetInstanceID(), length));
}
}
if (list4.Count == 0)
{
return list2;
}
List<(Component, int, float)> list5 = new List<(Component, int, float)>(list4);
int num = -1;
if (_firstAnchorId.HasValue)
{
num = FindIndexById(list5, _firstAnchorId.Value);
}
var (val3, num2, _) = ((num >= 0) ? list5[num] : PickByMinSpawn(list5));
if (!_firstAnchorId.HasValue)
{
_firstAnchorId = num2;
}
List<(Component, int, float)> list6 = new List<(Component, int, float)>();
for (int k = 0; k < list4.Count; k++)
{
if (list4[k].Item2 != num2)
{
list6.Add(list4[k]);
}
}
list2.Add(val3);
if (list6.Count == 0)
{
_ = Time.realtimeSinceStartup;
return list2;
}
int num3 = -1;
if (_lastAnchorId.HasValue)
{
num3 = FindIndexById(list6, _lastAnchorId.Value);
}
var (last, num4, _) = ((num3 >= 0) ? list6[num3] : PickByMinSpawn(list6));
if (!_lastAnchorId.HasValue)
{
_lastAnchorId = num4;
}
List<Component> middleCandidates = new List<Component>();
for (int l = 0; l < list6.Count; l++)
{
if (list6[l].Item2 != num4)
{
middleCandidates.Add(list6[l].Item1);
}
}
List<Component> bestMiddle = null;
float bestTotal = float.MaxValue;
bool[] used;
List<Component> curOrder;
if (middleCandidates.Count == 0)
{
if (TryGetEdgePathLength(val3, last, _edgePathCache, _edgePathInvalid, out var length2))
{
bestTotal = length2;
bestMiddle = new List<Component>();
}
}
else
{
used = new bool[middleCandidates.Count];
curOrder = new List<Component>(middleCandidates.Count);
Dfs(val3, 0f);
}
if (bestMiddle == null)
{
return new List<Component>();
}
for (int m = 0; m < bestMiddle.Count; m++)
{
list2.Add(bestMiddle[m]);
}
list2.Add(last);
_ = Time.realtimeSinceStartup;
return list2;
void Dfs(Component prev, float costSoFar)
{
if (!(costSoFar > bestTotal + 0.0001f))
{
if (curOrder.Count == middleCandidates.Count)
{
if (TryGetEdgePathLength(prev, last, _edgePathCache, _edgePathInvalid, out var length3))
{
float num6 = costSoFar + length3;
if (num6 + 0.0001f < bestTotal || (Mathf.Abs(num6 - bestTotal) <= 0.0001f && IsBetterSameCostOrder(curOrder, bestMiddle)))
{
bestTotal = num6;
bestMiddle = new List<Component>(curOrder);
}
}
}
else
{
for (int num7 = 0; num7 < middleCandidates.Count; num7++)
{
if (!used[num7])
{
Component val4 = middleCandidates[num7];
if (TryGetEdgePathLength(prev, val4, _edgePathCache, _edgePathInvalid, out var length4))
{
used[num7] = true;
curOrder.Add(val4);
Dfs(val4, costSoFar + length4);
curOrder.RemoveAt(curOrder.Count - 1);
used[num7] = false;
}
}
}
}
}
}
static int FindIndexById(List<(Component ep, int id, float spawnPath)> list, int id)
{
for (int num9 = 0; num9 < list.Count; num9++)
{
if (list[num9].id == id)
{
return num9;
}
}
return -1;
}
static bool IsBetterSameCostOrder(List<Component> current, List<Component>? best)
{
if (best == null)
{
return true;
}
int num5 = Math.Min(current.Count, best.Count);
for (int n = 0; n < num5; n++)
{
int instanceID = ((Object)current[n]).GetInstanceID();
int instanceID2 = ((Object)best[n]).GetInstanceID();
if (instanceID != instanceID2)
{
return instanceID < instanceID2;
}
}
return current.Count < best.Count;
}
static (Component ep, int id, float spawnPath) PickByMinSpawn(List<(Component ep, int id, float spawnPath)> list)
{
(Component, int, float) result = list[0];
for (int num8 = 1; num8 < list.Count; num8++)
{
(Component, int, float) tuple3 = list[num8];
if (tuple3.Item3 + 0.0001f < result.Item3 || (Mathf.Abs(tuple3.Item3 - result.Item3) <= 0.0001f && tuple3.Item2 < result.Item2))
{
result = tuple3;
}
}
return result;
}
}
public List<Component> BuildPlanDiscoverAllFixedAnchors(List<Component> allPoints, Vector3 spawnPos, bool skipActivated)
{
//IL_0026: 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_0037: Unknown result type (might be due to invalid IL or missing references)
//IL_00cd: Unknown result type (might be due to invalid IL or missing references)
float realtimeSinceStartup = Time.realtimeSinceStartup;
List<Component> list2 = new List<Component>();
if (allPoints == null || allPoints.Count == 0)
{
return list2;
}
if (spawnPos == Vector3.zero)
{
return list2;
}
if (!TryGetGlobalAnchorsNoCache(allPoints, spawnPos, out Component firstAnchor, out Component tailAnchor) || (Object)(object)firstAnchor == (Object)null)
{
return list2;
}
List<Component> list3 = new List<Component>(allPoints.Count);
for (int i = 0; i < allPoints.Count; i++)
{
Component val = allPoints[i];
if (Object.op_Implicit((Object)(object)val) && !IsCompletedLikeState(ReadStateName(val)) && (!skipActivated || !IsMarkedActivated(val)))
{
list3.Add(val);
}
}
if (list3.Count == 0)
{
return list2;
}
List<(Component, int, float)> list4 = new List<(Component, int, float)>();
for (int j = 0; j < list3.Count; j++)
{
Component val2 = list3[j];
if (TryGetSpawnPathLength(val2, spawnPos, _spawnPathCache, _spawnPathInvalid, out var length))
{
list4.Add((val2, ((Object)val2).GetInstanceID(), length));
}
}
if (list4.Count == 0)
{
return list2;
}
int globalFirstId = ((Object)firstAnchor).GetInstanceID();
int globalTailId = (((Object)(object)tailAnchor != (Object)null) ? ((Object)tailAnchor).GetInstanceID() : int.MinValue);
bool num = list4.Any<(Component, int, float)>(((Component ep, int id, float spawnPath) x) => x.id == globalFirstId);
bool flag = (Object)(object)tailAnchor != (Object)null && globalTailId != globalFirstId && list4.Any<(Component, int, float)>(((Component ep, int id, float spawnPath) x) => x.id == globalTailId);
(Component, int, float)? tuple = null;
if (num)
{
tuple = list4.First<(Component, int, float)>(((Component ep, int id, float spawnPath) x) => x.id == globalFirstId);
}
else
{
List<(Component, int, float)> list5 = (flag ? list4.Where<(Component, int, float)>(((Component ep, int id, float spawnPath) x) => x.id != globalTailId).ToList() : list4);
if (list5.Count == 0)
{
list5 = list4;
}
tuple = PickByMinSpawn(list5);
}
Component item = tuple.Value.Item1;
int item2 = tuple.Value.Item2;
list2.Add(item);
bool flag2 = flag && globalTailId != item2;
List<Component> middleCandidates = new List<Component>();
for (int k = 0; k < list4.Count; k++)
{
(Component, int, float) tuple2 = list4[k];
if (tuple2.Item2 != item2 && (!flag2 || tuple2.Item2 != globalTailId))
{
middleCandidates.Add(tuple2.Item1);
}
}
Component tail = (flag2 ? list4.First<(Component, int, float)>(((Component ep, int id, float spawnPath) x) => x.id == globalTailId).Item1 : null);
List<Component> bestMiddle = null;
float bestTotal = float.MaxValue;
bool[] used;
List<Component> curOrder;
if (middleCandidates.Count == 0)
{
float length2;
if ((Object)(object)tail == (Object)null)
{
bestTotal = 0f;
bestMiddle = new List<Component>();
}
else if (TryGetEdgePathLength(item, tail, _edgePathCache, _edgePathInvalid, out length2))
{
bestTotal = length2;
bestMiddle = new List<Component>();
}
}
else
{
used = new bool[middleCandidates.Count];
curOrder = new List<Component>(middleCandidates.Count);
Dfs(item, 0f);
}
if (bestMiddle == null)
{
return new List<Component>();
}
for (int l = 0; l < bestMiddle.Count; l++)
{
list2.Add(bestMiddle[l]);
}
if ((Object)(object)tail != (Object)null)
{
list2.Add(tail);
}
string.Join(" -> ", from x in list2
where (Object)(object)x != (Object)null
select ((Object)x.gameObject).name);
if ((Object)(object)tail != (Object)null)
{
_ = ((Object)tail.gameObject).name;
}
_ = Time.realtimeSinceStartup;
return list2;
void Dfs(Component prev, float costSoFar)
{
if (!(costSoFar > bestTotal + 0.0001f))
{
if (curOrder.Count == middleCandidates.Count)
{
float num3 = costSoFar;
if ((Object)(object)tail != (Object)null)
{
if (!TryGetEdgePathLength(prev, tail, _edgePathCache, _edgePathInvalid, out var length3))
{
return;
}
num3 += length3;
}
if (num3 + 0.0001f < bestTotal || (Mathf.Abs(num3 - bestTotal) <= 0.0001f && IsBetterSameCostOrder(curOrder, bestMiddle)))
{
bestTotal = num3;
bestMiddle = new List<Component>(curOrder);
}
}
else
{
for (int n = 0; n < middleCandidates.Count; n++)
{
if (!used[n])
{
Component val3 = middleCandidates[n];
if (TryGetEdgePathLength(prev, val3, _edgePathCache, _edgePathInvalid, out var length4))
{
used[n] = true;
curOrder.Add(val3);
Dfs(val3, costSoFar + length4);
curOrder.RemoveAt(curOrder.Count - 1);
used[n] = false;
}
}
}
}
}
}
static bool IsBetterSameCostOrder(List<Component> current, List<Component>? best)
{
if (best == null)
{
return true;
}
int num2 = Math.Min(current.Count, best.Count);
for (int m = 0; m < num2; m++)
{
int instanceID = ((Object)current[m]).GetInstanceID();
int instanceID2 = ((Object)best[m]).GetInstanceID();
if (instanceID != instanceID2)
{
return instanceID < instanceID2;
}
}
return current.Count < best.Count;
}
static (Component ep, int id, float spawnPath) PickByMinSpawn(List<(Component ep, int id, float spawnPath)> list)
{
(Component, int, float) result = list[0];
for (int num4 = 1; num4 < list.Count; num4++)
{
(Component, int, float) tuple3 = list[num4];
if (tuple3.Item3 + 0.0001f < result.Item3 || (Mathf.Abs(tuple3.Item3 - result.Item3) <= 0.0001f && tuple3.Item2 < result.Item2))
{
result = tuple3;
}
}
return result;
}
}
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_0019: Unknown result type (might be due to invalid IL or missing references)
//IL_002b: Unknown result type (might be due to invalid IL or missing references)
//IL_0031: Expected O, but got Unknown
//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_0042: 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_008e: Unknown result type (might be due to invalid IL or missing references)
length = 0f;
try
{
if (!TrySampleNavPoint(from, out var sampled))
{
return false;
}
if (!TrySampleNavPoint(to, out var sampled2))
{
return false;
}
NavMeshPath val = new NavMeshPath();
if (!NavMesh.CalculatePath(sampled, sampled2, -1, val))
{
return false;
}
if ((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(Component ep, 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)ep))
{
return false;
}
int instanceID = ((Object)ep).GetInstanceID();
if (cache.TryGetValue(instanceID, out length))
{
return true;
}
if (invalid.Contains(instanceID))
{
return false;
}
if (TryGetPathLength(spawnPos, ep.transform.position, out length))
{
cache[instanceID] = length;
return true;
}
invalid.Add(instanceID);
return false;
}
private bool TryGetEdgePathLength(Component from, Component 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(from.transform.position, to.transform.position, out length))
{
cache[num] = length;
return true;
}
invalid.Add(num);
return false;
}
}
}
namespace REPO_Active.Reflection
{
public sealed class ExtractionPointInvoker
{
public bool InvokeOnClick(Component ep)
{
if ((Object)(object)ep == (Object)null)
{
return false;
}
try
{
MethodInfo method = ((object)ep).GetType().GetMethod("OnClick", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
if (method == null)
{
return false;
}
object[] parameters = BuildDefaultArgs(method);
method.Invoke(ep, parameters);
return true;
}
catch (Exception)
{
return false;
}
}
private static object[]? BuildDefaultArgs(MethodInfo mi)
{
try
{
ParameterInfo[] parameters = mi.GetParameters();
if (parameters == null || parameters.Length == 0)
{
return null;
}
object[] array = new object[parameters.Length];
for (int i = 0; i < parameters.Length; i++)
{
ParameterInfo parameterInfo = parameters[i];
if (parameterInfo.HasDefaultValue)
{
array[i] = parameterInfo.DefaultValue;
continue;
}
Type type = parameterInfo.ParameterType;
if (type.IsByRef)
{
type = type.GetElementType() ?? type;
}
if (!type.IsValueType)
{
array[i] = null;
continue;
}
try
{
array[i] = Activator.CreateInstance(type);
}
catch
{
array[i] = null;
}
}
return array;
}
catch
{
return null;
}
}
}
}