Decompiled source of SuperScanner v1.2.3

Zichen-SuperScanner-1.2.3.dll

Decompiled a day ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Text.RegularExpressions;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using TMPro;
using UnityEngine;
using UnityEngine.InputSystem;
using UnityEngine.SceneManagement;

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

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
public enum DisplayLanguage
{
	中文,
	English
}
[BepInPlugin("zichen.superscanner", "Super Scanner", "1.2.3")]
public class ZichenSuperScannerPlugin : BaseUnityPlugin
{
	private sealed class EnemyLabelInfo
	{
		public Enemy Enemy;

		public string Name = string.Empty;

		public Transform ReferenceTransform;

		public float LabelYOffset;

		public float DistanceSquared;

		public int CachedDistanceMeters = -1;

		public bool CachedShowDistance;

		public bool CachedIsMasked;

		public string PlainText = string.Empty;

		public string RichText = string.Empty;

		public float NextRuntimeRefreshTime;

		public int CachedLayoutFontSize = int.MinValue;

		public Vector2 CachedLayoutSize;
	}

	private struct EnemyFrameState
	{
		public bool IsUsable;

		public bool IsAliveAndSpawned;

		public Transform ReferenceTransform;

		public Vector3 ReferencePosition;
	}

	private enum TeamShareMode
	{
		None,
		Valuable,
		LotteryCoinBox
	}

	private sealed class ScanLabel
	{
		public Component Target;

		public PhysGrabObject PhysGrabObject;

		public Renderer[] Renderers = Array.Empty<Renderer>();

		public string DisplayName = string.Empty;

		public bool IsValuable;

		public bool IsItem;

		public bool IsCart;

		public bool IsLotteryCoinBox;

		public bool IsSmallCart;

		public bool IsVehicle;

		public bool IsRacingVehicle;

		public bool IsTeammate;

		public bool IsDeadTeammate;

		public string ColorHex = "#62d8ff";

		public Vector3 Position;

		public Vector3 LastAnchorPosition;

		public bool HasAnchorPosition;

		public string PlainText = string.Empty;

		public string RichText = string.Empty;

		public float DistanceSquared;

		public int DistanceMeters;

		public int CachedTextDistanceMeters = int.MinValue;

		public int CachedTextValue = int.MinValue;

		public bool CachedShowDistanceMeters;

		public bool CachedShowValuableNames;

		public bool CachedShowValuablePrices;

		public bool CachedIsMasked;

		public TeamShareMode ShareMode;

		public bool SharedWithTeam;

		public float NextRuntimeRefreshTime;

		public int CachedLayoutFontSize = int.MinValue;

		public Vector2 CachedLayoutSize;
	}

	private struct CartScanInfo
	{
		public bool IsCart;

		public bool IsSmallCart;
	}

	internal sealed class CfgI18N
	{
		public string SectionCN;

		public string SectionEN;

		public string KeyCN;

		public string KeyEN;

		public string DisplayEN;

		public string DescCN;

		public string DescEN;

		public ConfigurationManagerAttributes Attrs;

		public string ValueEN;

		public string ValueCN;

		public ConfigEntry<string> ReadOnlyEntry;

		public ConfigEntryBase Entry;
	}

	internal sealed class LiveLabel
	{
		public WeakReference<TextMeshProUGUI> Tmp;

		public CfgI18N I18N;

		public bool IsSection;
	}

	internal sealed class LiveValue
	{
		public WeakReference<Object> InputField;

		public CfgI18N I18N;
	}

	internal sealed class LiveSliderOptions
	{
		public WeakReference<Object> Slider;

		public CfgI18N I18N;

		public string[] OptionsCN;

		public string[] OptionsEN;
	}

	internal sealed class LiveToggleButtons
	{
		public WeakReference<TextMeshProUGUI> LeftTmp;

		public WeakReference<TextMeshProUGUI> RightTmp;
	}

	[CompilerGenerated]
	private sealed class <GetComponentTypeNames>d__411 : IEnumerable<string>, IEnumerable, IEnumerator<string>, IDisposable, IEnumerator
	{
		private int <>1__state;

		private string <>2__current;

		private int <>l__initialThreadId;

		private GameObject gameObject;

		public GameObject <>3__gameObject;

		private Component[] <components>5__2;

		private int <i>5__3;

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

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

		[DebuggerHidden]
		public <GetComponentTypeNames>d__411(int <>1__state)
		{
			this.<>1__state = <>1__state;
			<>l__initialThreadId = Environment.CurrentManagedThreadId;
		}

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

		private bool MoveNext()
		{
			int num = <>1__state;
			if (num != 0)
			{
				if (num != 1)
				{
					return false;
				}
				<>1__state = -1;
				goto IL_0079;
			}
			<>1__state = -1;
			if ((Object)(object)gameObject == (Object)null)
			{
				return false;
			}
			<components>5__2 = gameObject.GetComponents<Component>();
			<i>5__3 = 0;
			goto IL_0089;
			IL_0079:
			<i>5__3++;
			goto IL_0089;
			IL_0089:
			if (<i>5__3 < <components>5__2.Length)
			{
				Component val = <components>5__2[<i>5__3];
				if (!((Object)(object)val == (Object)null))
				{
					<>2__current = ((object)val).GetType().Name;
					<>1__state = 1;
					return true;
				}
				goto IL_0079;
			}
			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();
		}

		[DebuggerHidden]
		IEnumerator<string> IEnumerable<string>.GetEnumerator()
		{
			<GetComponentTypeNames>d__411 <GetComponentTypeNames>d__;
			if (<>1__state == -2 && <>l__initialThreadId == Environment.CurrentManagedThreadId)
			{
				<>1__state = 0;
				<GetComponentTypeNames>d__ = this;
			}
			else
			{
				<GetComponentTypeNames>d__ = new <GetComponentTypeNames>d__411(0);
			}
			<GetComponentTypeNames>d__.gameObject = <>3__gameObject;
			return <GetComponentTypeNames>d__;
		}

		[DebuggerHidden]
		IEnumerator IEnumerable.GetEnumerator()
		{
			return ((IEnumerable<string>)this).GetEnumerator();
		}
	}

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

		private object <>2__current;

		public ZichenSuperScannerPlugin <>4__this;

		private float <startTime>5__2;

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

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

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

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

		private bool MoveNext()
		{
			//IL_0056: Unknown result type (might be due to invalid IL or missing references)
			//IL_0060: Expected O, but got Unknown
			int num = <>1__state;
			ZichenSuperScannerPlugin zichenSuperScannerPlugin = <>4__this;
			switch (num)
			{
			default:
				return false;
			case 0:
				<>1__state = -1;
				<startTime>5__2 = Time.unscaledTime;
				break;
			case 1:
				<>1__state = -1;
				break;
			}
			if (!AreResourceDumpSourcesReady())
			{
				if (Time.unscaledTime - <startTime>5__2 >= 30f)
				{
					((BaseUnityPlugin)zichenSuperScannerPlugin).Logger.LogWarning((object)"[NameDump] Timed out waiting for item and level resources.");
					return false;
				}
				<>2__current = (object)new WaitForSecondsRealtime(1f);
				<>1__state = 1;
				return true;
			}
			zichenSuperScannerPlugin.DumpItemResources();
			zichenSuperScannerPlugin.DumpValuableResources();
			((BaseUnityPlugin)zichenSuperScannerPlugin).Logger.LogInfo((object)"[NameDump] Completed item and valuable resource dump.");
			return false;
		}

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

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

	public const string PluginGuid = "zichen.superscanner";

	public const string PluginVersion = "1.2.3";

	public const string PluginName = "Super Scanner";

	private static ZichenSuperScannerPlugin Instance;

	private const string LotteryCoinBoxNameZh = "装饰箱";

	private const string LotteryCoinBoxNameEn = "Decor Box";

	private const int MinimumScanIntervalSeconds = 1;

	private const int MaximumScanIntervalSeconds = 5;

	private const int FixedScanHoldSeconds = 5;

	private const int MinimumScanDistanceMeters = 1;

	private const int MaximumScanDistanceMeters = 100;

	private const int TeamShareMaxDistanceMeters = 15;

	private const float ContainmentRefreshIntervalSeconds = 0.12f;

	private const int FarFontShrinkPercent = 30;

	private const float FontScaleDistanceMeters = 30f;

	private const float EnemyRefreshIntervalSeconds = 0.25f;

	private const float EnemyProximityRefreshIntervalSeconds = 0.12f;

	private const float EnemyLabelRefreshIntervalSeconds = 0.12f;

	private const float EnemyListCleanupIntervalSeconds = 1f;

	private const float ValuableValueRefreshIntervalSeconds = 0.12f;

	private const float LocalPlayerRefreshIntervalSeconds = 0.25f;

	private const float ScanLabelRefreshIntervalSeconds = 0.08f;

	private static readonly bool EnableStartupResourceNameDump = false;

	private static readonly bool EnableScanDebugLogging = false;

	private static readonly FieldInfo ValuableCurrentValueField = typeof(ValuableObject).GetField("dollarValueCurrent", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);

	private static readonly FieldInfo ValuableValueSetField = typeof(ValuableObject).GetField("dollarValueSet", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);

	private static readonly FieldInfo ValuablePhysGrabObjectField = typeof(ValuableObject).GetField("physGrabObject", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);

	private static readonly FieldInfo ItemNameField = typeof(ItemAttributes).GetField("itemName", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);

	private static readonly FieldInfo ItemPhysGrabObjectField = typeof(ItemAttributes).GetField("physGrabObject", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);

	private static readonly FieldInfo ItemShopItemField = typeof(ItemAttributes).GetField("shopItem", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);

	private static readonly FieldInfo ItemPromptNameField = typeof(ItemAttributes).GetField("promptName", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);

	private static readonly FieldInfo ItemAssetNameField = typeof(ItemAttributes).GetField("itemAssetName", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);

	private static readonly FieldInfo ItemInstanceNameField = typeof(ItemAttributes).GetField("instanceName", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);

	private static readonly FieldInfo ItemTagField = typeof(ItemAttributes).GetField("itemTag", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);

	private static readonly FieldInfo ItemTypeField = typeof(ItemAttributes).GetField("itemType", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);

	private static readonly FieldInfo ItemEquippableField = typeof(ItemAttributes).GetField("itemEquippable", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);

	private static readonly FieldInfo PhysGrabObjectDeadField = typeof(PhysGrabObject).GetField("dead", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);

	private static readonly FieldInfo PhysGrabObjectIsHiddenField = typeof(PhysGrabObject).GetField("isHidden", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);

	private static readonly FieldInfo PhysGrabObjectImpactDetectorField = typeof(PhysGrabObject).GetField("impactDetector", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);

	private static readonly FieldInfo PhysGrabObjectPlayerGrabbingField = typeof(PhysGrabObject).GetField("playerGrabbing", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);

	private static readonly FieldInfo PhysGrabObjectImpactDetectorInCartField = typeof(PhysGrabObjectImpactDetector).GetField("inCart", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);

	private static readonly FieldInfo PhysGrabberGrabbedPhysGrabObjectField = typeof(PhysGrabber).GetField("grabbedPhysGrabObject", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);

	private static readonly FieldInfo PhysGrabberGrabbedField = typeof(PhysGrabber).GetField("grabbed", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);

	private static readonly FieldInfo PhysGrabberPlayerAvatarField = typeof(PhysGrabber).GetField("playerAvatar", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);

	private static readonly FieldInfo PhysGrabCartItemsInCartField = typeof(PhysGrabCart).GetField("itemsInCart", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);

	private static readonly FieldInfo PhysGrabCartInCartField = typeof(PhysGrabCart).GetField("physGrabInCart", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);

	private static readonly FieldInfo PhysGrabCartIsSmallField = typeof(PhysGrabCart).GetField("isSmallCart", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);

	private static readonly FieldInfo PhysGrabInCartObjectsField = typeof(PhysGrabInCart).GetField("inCartObjects", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);

	private static readonly FieldInfo PhysGrabInCartCartObjectPhysGrabObjectField = typeof(PhysGrabInCart).GetNestedType("CartObject", BindingFlags.Public | BindingFlags.NonPublic)?.GetField("physGrabObject", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);

	private static readonly FieldInfo RoundDirectorInstanceField = typeof(RoundDirector).GetField("instance", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);

	private static readonly FieldInfo RoundDirectorDollarHaulListField = typeof(RoundDirector).GetField("dollarHaulList", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);

	private static readonly FieldInfo RoundDirectorValuableBoxHaulListField = typeof(RoundDirector).GetField("valuableBoxHaulList", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);

	private static readonly FieldInfo ValuableDiscoverCustomPhysGrabObjectField = typeof(ValuableDiscoverCustom).GetField("physGrabObject", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);

	private static readonly FieldInfo ValuableDiscoverCustomColorCornerField = typeof(ValuableDiscoverCustom).GetField("colorCorner", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);

	private static readonly FieldInfo ValuableObjectDiscoveredField = typeof(ValuableObject).GetField("discovered", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);

	private static readonly FieldInfo ValuableDiscoverCustomDiscoveredField = typeof(ValuableDiscoverCustom).GetField("discovered", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);

	private static readonly FieldInfo EnemyParentField = typeof(Enemy).GetField("EnemyParent", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);

	private static readonly FieldInfo EnemyParentEnemyField = typeof(EnemyParent).GetField("Enemy", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);

	private static readonly FieldInfo EnemyParentNameField = typeof(EnemyParent).GetField("enemyName", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);

	private static readonly FieldInfo EnemyParentLocalizedNameField = typeof(EnemyParent).GetField("enemyNameLocalized", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);

	private static readonly MethodInfo LocalizedAssetGetStringMethod = typeof(LocalizedAsset).GetMethod("GetLocalizedString", Type.EmptyTypes);

	private static readonly FieldInfo EnemyParentSpawnedField = typeof(EnemyParent).GetField("Spawned", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);

	private static readonly FieldInfo EnemyHealthField = typeof(Enemy).GetField("Health", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);

	private static readonly FieldInfo EnemyHealthDeadField = typeof(EnemyHealth).GetField("dead", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);

	private static readonly FieldInfo EnemyCenterTransformField = typeof(Enemy).GetField("CenterTransform", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);

	private static readonly FieldInfo EnemyTypeField = typeof(Enemy).GetField("Type", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);

	private static readonly FieldInfo PlayerIsLocalField = typeof(PlayerAvatar).GetField("isLocal", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);

	private static readonly FieldInfo PlayerTransformField = typeof(PlayerAvatar).GetField("playerTransform", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);

	private static readonly FieldInfo PlayerDeadSetField = typeof(PlayerAvatar).GetField("deadSet", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);

	private static readonly FieldInfo PlayerSpectatingField = typeof(PlayerAvatar).GetField("spectating", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);

	private static readonly FieldInfo PlayerIsDisabledField = typeof(PlayerAvatar).GetField("isDisabled", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);

	private static readonly FieldInfo ItemVehicleIsRacingField = typeof(ItemVehicle).GetField("isRacingVehicle", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);

	private static readonly FieldInfo PlayerNameField = typeof(PlayerAvatar).GetField("playerName", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);

	private static readonly FieldInfo PlayerDeathHeadField = typeof(PlayerAvatar).GetField("playerDeathHead", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);

	private static readonly FieldInfo DeathHeadPhysGrabObjectField = typeof(PlayerDeathHead).GetField("physGrabObject", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);

	private static readonly FieldInfo DeathHeadTriggeredPositionField = typeof(PlayerDeathHead).GetField("triggeredPosition", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);

	private static readonly FieldInfo DeathHeadOverridePositionTransformField = typeof(PlayerDeathHead).GetField("overridePositionTransform", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);

	private static readonly FieldInfo PlayerLastNavmeshPositionField = typeof(PlayerAvatar).GetField("LastNavmeshPosition", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);

	private readonly List<ScanLabel> labels = new List<ScanLabel>();

	private readonly Stack<ScanLabel> scanLabelPool = new Stack<ScanLabel>();

	private readonly Dictionary<int, GUIStyle> labelStyleCache = new Dictionary<int, GUIStyle>();

	private readonly Dictionary<int, GUIStyle> enemyLabelStyleCache = new Dictionary<int, GUIStyle>();

	private readonly Dictionary<int, Renderer[]> objectRendererCache = new Dictionary<int, Renderer[]>();

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

	private readonly Dictionary<int, PhysGrabObject> objectPhysGrabCache = new Dictionary<int, PhysGrabObject>();

	private readonly Dictionary<int, bool> itemHasValuableCache = new Dictionary<int, bool>();

	private readonly Dictionary<int, bool> itemShopItemCache = new Dictionary<int, bool>();

	private readonly Dictionary<int, CartScanInfo> itemCartInfoCache = new Dictionary<int, CartScanInfo>();

	private readonly Dictionary<int, bool> itemShouldScanCache = new Dictionary<int, bool>();

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

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

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

	private readonly Dictionary<int, bool> physGrabHiddenOrDeadFrameCache = new Dictionary<int, bool>();

	private readonly Dictionary<int, EnemyFrameState> enemyFrameStateCache = new Dictionary<int, EnemyFrameState>();

	private readonly Dictionary<int, bool> objectIsVehicleCache = new Dictionary<int, bool>();

	private readonly GUIContent labelContent = new GUIContent();

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

	private readonly HashSet<object> cartObjectSet = new HashSet<object>(ReferenceObjectComparer.Instance);

	private readonly HashSet<object> haulObjectSet = new HashSet<object>(ReferenceObjectComparer.Instance);

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

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

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

	private readonly HashSet<PhysGrabObject> localHeldPhysGrabObjects = new HashSet<PhysGrabObject>();

	private readonly Dictionary<int, bool> localHeldStateCache = new Dictionary<int, bool>();

	private readonly Dictionary<Type, FieldInfo> playerAvatarFieldCache = new Dictionary<Type, FieldInfo>();

	private ConfigEntry<string> moduleNameInfo;

	private ConfigEntry<string> moduleVersionInfo;

	private ConfigEntry<DisplayLanguage> displayLanguage;

	private ConfigEntry<bool> scannerEnabled;

	private ConfigEntry<bool> shareScansWithTeam;

	private ConfigEntry<bool> scanExploreMode;

	private ConfigEntry<bool> showDistanceMeters;

	private ConfigEntry<bool> alwaysTriggerShare;

	private ConfigEntry<bool> showValuables;

	private ConfigEntry<bool> showValuableNames;

	private ConfigEntry<bool> showValuablePrices;

	private ConfigEntry<bool> showTeammates;

	private ConfigEntry<bool> showAliveTeammates;

	private ConfigEntry<bool> showDeadTeammates;

	private ConfigEntry<bool> showItems;

	private ConfigEntry<bool> showItemNames;

	private ConfigEntry<bool> showLotteryCoinBoxes;

	private ConfigEntry<bool> showCarts;

	private ConfigEntry<bool> showBigCarts;

	private ConfigEntry<bool> showSmallCarts;

	private ConfigEntry<bool> showVehicles;

	private ConfigEntry<bool> showCargoVehicles;

	private ConfigEntry<bool> showRacingVehicles;

	private ConfigEntry<string> scanKey;

	private ConfigEntry<int> scanIntervalSeconds;

	private ConfigEntry<int> scanDistanceMeters;

	private ConfigEntry<int> fontSize;

	private ConfigEntry<bool> enemyOverlayEnabled;

	private ConfigEntry<bool> enemyProximityAutoShowEnabled;

	private ConfigEntry<int> enemyProximityAutoShowDistance;

	private ConfigEntry<bool> enemyNicknameEnabled;

	private ConfigEntry<bool> modEnabled;

	private float visibleTimer;

	private float scanCooldownTimer;

	private int containmentSetFrame = -1;

	private float enemyVisibleTimer;

	private float enemyProximityVisibleTimer;

	private readonly List<EnemyLabelInfo> enemyLabels = new List<EnemyLabelInfo>();

	private readonly Stack<EnemyLabelInfo> enemyLabelPool = new Stack<EnemyLabelInfo>();

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

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

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

	private readonly List<int> enemyProximityTimerKeys = new List<int>();

	private readonly List<int> expiredEnemyProximityKeys = new List<int>();

	private readonly Dictionary<int, Renderer[]> enemyRendererCache = new Dictionary<int, Renderer[]>();

	private readonly Dictionary<int, Collider[]> enemyColliderCache = new Dictionary<int, Collider[]>();

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

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

	private readonly Dictionary<int, Transform> enemyCenterTransformCache = new Dictionary<int, Transform>();

	private const float ProximityAutoShowLingerSeconds = 5f;

	private const float EnemyProximityPopSeconds = 1.2f;

	private const float EnemyProximityPopFontMultiplier = 2f;

	private DisplayLanguage enemyDisplayNameCacheLanguage;

	private bool enemyDisplayNameCacheNicknames = true;

	private float nextEnemyProximityRefreshTime;

	private float nextEnemyLabelRefreshTime;

	private float nextEnemyListCleanupTime;

	private float nextContainmentRefreshTime;

	private int cachedLocalPositionFrame = -1;

	private Vector3 cachedLocalPosition;

	private Camera cachedCamera;

	private int cachedGuiScaleFrame = -1;

	private Camera cachedGuiScaleCamera;

	private float cachedGuiScaleX = 1f;

	private float cachedGuiScaleY = 1f;

	private int cachedPhysGrabStateFrame = -1;

	private int cachedEnemyStateFrame = -1;

	private int cachedScanSettingsFrame = -1;

	private int cachedScanLocalPlayerFrame = -1;

	private bool cachedScanLocalPlayerReady;

	private PlayerAvatar cachedScanLocalPlayer;

	private int cachedScanDistanceMeters = 15;

	private float cachedScanDistanceSquared = 225f;

	private int cachedScanFontSize = 28;

	private bool cachedScanExploreMode;

	private bool cachedShowDistanceMeters;

	private bool cachedShowValuableNames = true;

	private bool cachedShowValuablePrices = true;

	private PlayerAvatar cachedLocalPlayer;

	private bool cachedLocalPlayerIsLocal;

	private readonly List<PhysGrabber> grabberObjectsCache = new List<PhysGrabber>();

	private float nextGrabberRefreshTime;

	private float nextLocalHeldRefreshTime;

	private float nextLocalPlayerRefreshTime;

	private DisplayLanguage objectDisplayNameCacheLanguage;

	private Harmony harmony;

	private static readonly List<ValuableObject> trackedValuables = new List<ValuableObject>();

	private static readonly HashSet<ValuableObject> trackedValuableSet = new HashSet<ValuableObject>();

	private static readonly List<ItemAttributes> trackedItems = new List<ItemAttributes>();

	private static readonly HashSet<ItemAttributes> trackedItemSet = new HashSet<ItemAttributes>();

	private static readonly List<Enemy> trackedEnemies = new List<Enemy>();

	private static readonly HashSet<Enemy> trackedEnemySet = new HashSet<Enemy>();

	private static readonly List<PhysGrabCart> trackedCarts = new List<PhysGrabCart>();

	private static readonly HashSet<PhysGrabCart> trackedCartSet = new HashSet<PhysGrabCart>();

	private static readonly List<ItemVehicle> trackedVehicles = new List<ItemVehicle>();

	private static readonly HashSet<ItemVehicle> trackedVehicleSet = new HashSet<ItemVehicle>();

	private static readonly List<ValuableDiscoverCustom> trackedDiscoverCustoms = new List<ValuableDiscoverCustom>();

	private static readonly HashSet<ValuableDiscoverCustom> trackedDiscoverCustomSet = new HashSet<ValuableDiscoverCustom>();

	private static readonly List<PhysGrabber> trackedGrabbers = new List<PhysGrabber>();

	private static readonly HashSet<PhysGrabber> trackedGrabberSet = new HashSet<PhysGrabber>();

	private static float nextEnemyDirectorSyncTime;

	private const int ScanInputKeyValue = 329;

	private static readonly InputKey ScanInputKey = (InputKey)329;

	private static string lastAppliedScanKey;

	private bool resourceNameDumpStarted;

	private static readonly string[] AvailableKeybinds = new string[55]
	{
		"A", "B", "C", "D", "E", "F", "G", "H", "I", "J",
		"K", "L", "M", "N", "O", "P", "Q", "R", "S", "T",
		"U", "V", "W", "X", "Y", "Z", "0", "1", "2", "3",
		"4", "5", "6", "7", "8", "9", "F1", "F2", "F3", "F4",
		"F5", "F6", "F7", "F8", "F9", "F10", "F11", "F12", "Space", "Enter",
		"Tab", "LeftShift", "RightShift", "LeftControl", "RightControl"
	};

	private static string cachedOfficialGreenHex;

	private static int officialColorCacheFrame = -1;

	private static readonly Regex WhitespaceRegex = new Regex("\\s+", RegexOptions.Compiled);

	private static readonly string[] ItemKeywords = new string[22]
	{
		"weapon", "gun", "melee", "tool", "grenade", "mine", "drone", "tracker", "medkit", "health",
		"flashlight", "orb", "upgrade", "cart", "pistol", "shotgun", "revolver", "sword", "bat", "hammer",
		"spear", "mace"
	};

	private static bool inputActionsRegistered;

	private static InputManager registeredInputManager;

	private static Dictionary<InputKey, InputAction> registeredInputActions;

	private const float ResourceDumpRetryIntervalSeconds = 1f;

	private const float ResourceDumpTimeoutSeconds = 30f;

	internal static readonly Dictionary<string, CfgI18N> _cfgByEnSection = new Dictionary<string, CfgI18N>(StringComparer.Ordinal);

	internal static readonly Dictionary<string, CfgI18N> _cfgByEnKey = new Dictionary<string, CfgI18N>(StringComparer.Ordinal);

	internal static readonly Dictionary<string, List<CfgI18N>> _cfgByKeyOnly = new Dictionary<string, List<CfgI18N>>(StringComparer.Ordinal);

	private static readonly List<CfgI18N> _cfgI18Ns = new List<CfgI18N>(64);

	private static readonly string[] _chineseModKeywords = new string[6] { "chinese", "简体", "繁體", "繁体", "汉化", "中文" };

	private static readonly string[] _chineseEnvironmentPluginGuids = new string[1] { "gravydevsupreme.xunity.autotranslator" };

	private static readonly List<LiveLabel> _liveLabels = new List<LiveLabel>(64);

	private static readonly List<LiveValue> _liveValues = new List<LiveValue>(8);

	private static readonly List<LiveSliderOptions> _liveSliderOptions = new List<LiveSliderOptions>(4);

	private static readonly List<LiveToggleButtons> _liveToggleButtons = new List<LiveToggleButtons>(16);

	private static readonly Dictionary<Type, FieldInfo> _labelTmpFieldCache = new Dictionary<Type, FieldInfo>(8);

	private static readonly Dictionary<Type, PropertyInfo> _sliderStringOptionsPropCache = new Dictionary<Type, PropertyInfo>(4);

	private static readonly Dictionary<Type, FieldInfo> _toggleLeftTmpCache = new Dictionary<Type, FieldInfo>(4);

	private static readonly Dictionary<Type, FieldInfo> _toggleRightTmpCache = new Dictionary<Type, FieldInfo>(4);

	private static readonly Dictionary<string, int> _pendingKeyMatchIndex = new Dictionary<string, int>(StringComparer.Ordinal);

	internal static string _currentRenderingConfigFilePath;

	internal static bool _createModEntriesPatchInstalled;

	private static readonly Dictionary<Type, FieldInfo> _inputStringSystemFieldCache = new Dictionary<Type, FieldInfo>(4);

	private static readonly Dictionary<Type, MethodInfo> _inputStringSystemSetValueCache = new Dictionary<Type, MethodInfo>(4);

	private static readonly Dictionary<string, string> _enumNameCNtoEN = new Dictionary<string, string>(StringComparer.Ordinal)
	{
		["中文"] = "Chinese",
		["文字显示"] = "Text Mode",
		["原生UI显示"] = "Native UI"
	};

	private static readonly Dictionary<string, string> _enumNameENtoCN = new Dictionary<string, string>(StringComparer.Ordinal)
	{
		["English"] = "英语",
		["Chinese"] = "中文"
	};

	private static DisplayLanguage InstanceLanguage
	{
		get
		{
			if (!((Object)(object)Instance == (Object)null) && Instance.displayLanguage != null)
			{
				return Instance.displayLanguage.Value;
			}
			return DisplayLanguage.中文;
		}
	}

	private void Awake()
	{
		//IL_008a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0094: Expected O, but got Unknown
		DetachFromManager();
		Instance = this;
		ResetConfigIfVersionChanged();
		BindConfig();
		scanKey.SettingChanged += delegate
		{
			RebindScanKey();
		};
		if (displayLanguage != null)
		{
			displayLanguage.SettingChanged += delegate
			{
				RefreshAllI18N();
			};
		}
		((BaseUnityPlugin)this).Logger.LogInfo((object)"zichen-superscanner loaded.");
		harmony = new Harmony("zichen.superscanner");
		ApplyHarmonyPatches();
		TryHookREPOConfig(harmony);
		if (EnableStartupResourceNameDump)
		{
			StartResourceNameDump();
		}
	}

	private void DetachFromManager()
	{
		try
		{
			((Component)this).transform.parent = null;
			((Object)((Component)this).gameObject).hideFlags = (HideFlags)61;
			Object.DontDestroyOnLoad((Object)(object)((Component)this).gameObject);
		}
		catch (Exception ex)
		{
			((BaseUnityPlugin)this).Logger.LogWarning((object)("Failed to mark plugin host persistent: " + ex.GetType().Name + ": " + ex.Message));
		}
	}

	private bool IsModEnabled()
	{
		if (modEnabled != null)
		{
			return modEnabled.Value;
		}
		return true;
	}

	private static bool IsStaticModEnabled()
	{
		ZichenSuperScannerPlugin instance = Instance;
		if (!((Object)(object)instance == (Object)null))
		{
			return instance.IsModEnabled();
		}
		return true;
	}

	private void LogScanDebug(string message)
	{
		if (EnableScanDebugLogging)
		{
			((BaseUnityPlugin)this).Logger.LogInfo((object)message);
		}
	}

	internal static string GetOfficialValueColorHex()
	{
		//IL_0035: Unknown result type (might be due to invalid IL or missing references)
		if (officialColorCacheFrame == Time.frameCount && cachedOfficialGreenHex != null)
		{
			return cachedOfficialGreenHex;
		}
		officialColorCacheFrame = Time.frameCount;
		try
		{
			if ((Object)(object)WorldSpaceUIValue.instance != (Object)null)
			{
				cachedOfficialGreenHex = ColorUtility.ToHtmlStringRGB(WorldSpaceUIValue.instance.colorValue);
				return cachedOfficialGreenHex;
			}
		}
		catch
		{
		}
		cachedOfficialGreenHex = "00C832";
		return cachedOfficialGreenHex;
	}

	private void BindConfig()
	{
		displayLanguage = BindI18N("A.Mod Info", "A.模组信息", "SuperScannerLanguage", "语言", "Switch display language.", "切换显示语言。", DetectDefaultLanguage(), null, 1010, null, "Language");
		moduleNameInfo = BindReadOnlyI18N("A.Mod Info", "A.模组信息", "SuperScannerModName", "模组名称", "Super Scanner", "超级扫描仪", 1000, DrawInfo, "Mod Name");
		moduleVersionInfo = BindReadOnlyI18N("A.Mod Info", "A.模组信息", "SuperScannerModVersion", "模组版本号", "1.2.3", "1.2.3", 990, DrawInfo, "Mod Version");
		modEnabled = BindI18N("B.Global", "B.全局设置", "ModEnabled", "模组启用", "If disabled, all scans and overlays are turned off.", "关闭后整个模组所有扫描和显示功能都不生效。默认开启。", defaultVal: true, null, 1005);
		enemyNicknameEnabled = BindI18N("B.Global", "B.全局设置", "EnemyNicknameEnabled", "敌人名字优化", "Enable community nicknames (e.g. Big Eye) for enemies. If disabled, standard Chinese names are shown.", "开启后怪物显示社区昵称(如 大眼哥 等)。关闭后显示标准中文名。默认开启。", defaultVal: true, null, 995);
		scannerEnabled = BindI18N("C.Scanner Settings", "C.扫描设置", "ScannerEnabled", "启用", "If disabled, scanning label display will not take effect.", "关闭后整个扫描显示都不生效。", defaultVal: true, null, 900);
		shareScansWithTeam = BindI18N("C.Scanner Settings", "C.扫描设置", "ShareScansWithTeam", "信息共享队友", "Only trigger discovery sync when you active scan targets within 15 meters.", "开启后,只有你主动按扫描键时,且目标距离自己不超过 15 米的贵重品 and 装饰箱,才会走游戏原生发现同步,队友不装这个模组也能收到发现效果。默认开启;若扫描探索模式开启,则会等目标解除 ? 后才触发一次同步。默认解锁距离为:贵重品 4 米、其他扫描目标 6 米、怪物 20 米。", defaultVal: true, null, 895);
		scanExploreMode = BindI18N("C.Scanner Settings", "C.扫描设置", "ScanExploreMode", "扫描探索模式", "Labels show ? until target enters unlock range.", "开启后扫描标签会先显示 ?,只有目标第一次进入解锁距离后才会显示正常名称、价格和米数。默认解锁距离为:贵重品 4 米、其他扫描目标 6 米、怪物 20 米;贵重品与装饰箱的信息共享也会等到解除 ? 后才触发一次。默认关闭。", defaultVal: false, null, 890);
		showDistanceMeters = BindI18N("C.Scanner Settings", "C.扫描设置", "ShowDistanceMeters", "显示米数", "If enabled, show distance in meters on scan labels.", "开启后扫描标签显示距离米数;关闭后物品、贵重品、装饰箱、推车和怪物都不显示米数。默认开启。", defaultVal: true, null, 875);
		alwaysTriggerShare = BindI18N("C.Scanner Settings", "C.扫描设置", "AlwaysTriggerShare", "触发方框显示", "If enabled, items within 15 meters will always show discover frames every time you scan, ignoring once-per-level limit.", "开启后,每次按下扫描,只要距离自己在 15 米以内的物品都会再次触发游戏原生的发现方框,无视每局仅触发一次的限制。默认开启。", defaultVal: true, null, 874);
		fontSize = BindI18N("C.Scanner Settings", "C.扫描设置", "FontSize", "字体大小", "Font size of in-game scan labels.", "局内物品和怪物扫描标签的字体大小。", 26, (AcceptableValueBase)(object)new AcceptableValueRange<int>(8, 48), 873);
		scanKey = BindI18N("C.Scanner Settings", "C.扫描设置", "ScanKey", "扫描按键", "Key to activate scanner. Displays for 5 seconds.", "按下这个按键后显示附近贵重品、装备、推车、装饰箱和怪物,固定显示5秒。", "F", (AcceptableValueBase)(object)new AcceptableValueList<string>(AvailableKeybinds), 870);
		scanIntervalSeconds = BindI18N("C.Scanner Settings", "C.扫描设置", "ScanCooldownSeconds", "扫描冷却/秒", "Scanner cooldown in seconds.", "按下扫描按键后,多少秒内再次按下不会重新显示。范围1-5秒,每次调整1秒。", 1, (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 5), 860);
		scanDistanceMeters = BindI18N("C.Scanner Settings", "C.扫描设置", "ScanDistanceMeters", "扫描距离/米", "Scanning range in meters.", "按下扫描按键时,只扫描并显示距离自己多少米以内的物品和怪物。范围1-100米,每次调整1米。默认15米。", 15, (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 100), 850);
		showValuables = BindI18N("D.Valuables Scan", "D.贵重品扫描", "ShowValuables", "启用", "Show recoverable valuables.", "显示可回收贵重品。", defaultVal: true, null, 890);
		showValuableNames = BindI18N("D.Valuables Scan", "D.贵重品扫描", "ShowValuableNames", "显示名称", "If enabled, show valuable names on scan labels.", "开启后贵重品扫描标签显示物品名称。默认开启。", defaultVal: true, null, 889);
		showValuablePrices = BindI18N("D.Valuables Scan", "D.贵重物品扫描", "ShowValuablePrices", "显示价格", "If enabled, show valuable prices on scan labels.", "开启后贵重品扫描标签显示当前价格。默认关闭。", defaultVal: false, null, 888);
		showTeammates = BindI18N("E.Teammates Scan", "E.队友扫描", "ShowTeammates", "启用", "Show teammate positions on scanner.", "在扫描仪上显示队友的位置。默认开启。", defaultVal: true, null, 885);
		showAliveTeammates = BindI18N("E.Teammates Scan", "E.队友扫描", "ShowAliveTeammates", "存活队友", "Show alive teammates on scanner.", "在扫描仪上显示存活的队友。默认关闭。", defaultVal: false, null, 884);
		showDeadTeammates = BindI18N("E.Teammates Scan", "E.队友扫描", "ShowDeadTeammates", "死亡队友", "Show dead teammates on scanner.", "在扫描仪上显示死亡的队友。默认开启。", defaultVal: true, null, 883);
		showItems = BindI18N("F.Items Scan", "F.装备武器扫描", "ShowItems", "启用", "Show guns, melee weapons, medkits, grenades, etc.", "显示枪、近战、血包、手雷等装备/武器。", defaultVal: true, null, 880);
		showItemNames = BindI18N("F.Items Scan", "F.装备武器扫描", "ShowItemNames", "显示名称", "If enabled, show item names on labels.", "开启后装备武器标签显示名称。默认开启。", defaultVal: true, null, 879);
		showLotteryCoinBoxes = BindI18N("G.Decor Boxes Scan", "G.装饰箱扫描", "ShowLotteryCoinBoxes", "启用", "Show coin machines, token boxes, and decor boxes in levels.", "显示关卡中的投币机、硬币宝箱、代币箱和装饰箱。不同类型用不同颜色区分。默认开启。", defaultVal: true, null, 870);
		showCarts = BindI18N("H.Carts Scan", "H.推车扫描", "ShowCarts", "启用", "Master toggle for cart scans.", "推车扫描总开关。关闭后大推车和小推车都不会显示。默认关闭。", defaultVal: false, null, 865);
		showBigCarts = BindI18N("H.Carts Scan", "H.推车扫描", "ShowBigCarts", "显示推车", "If enabled, show large carts.", "开启后扫描时显示推车。默认开启。", defaultVal: true, null, 860);
		showSmallCarts = BindI18N("H.Carts Scan", "H.推车扫描", "ShowSmallCarts", "显示小推车", "If enabled, show small carts.", "开启后扫描时显示小推车。默认开启。", defaultVal: true, null, 859);
		showVehicles = BindI18N("I.Vehicles Scan", "I.车辆扫描", "ShowVehicles", "启用", "Master toggle for vehicle scans.", "车辆扫描总开关。关闭后载货车 and 赛车都不会显示。默认关闭。", defaultVal: false, null, 855);
		showRacingVehicles = BindI18N("I.Vehicles Scan", "I.车辆扫描", "ShowRacingVehicles", "显示赛车", "If enabled, show racing vehicles.", "开启后扫描时显示赛车。默认开启。", defaultVal: true, null, 850);
		showCargoVehicles = BindI18N("I.Vehicles Scan", "I.车辆扫描", "ShowCargoVehicles", "显示载货车", "If enabled, show cargo vehicles.", "开启后扫描时显示载货车。默认开启。", defaultVal: true, null, 849);
		enemyOverlayEnabled = BindI18N("J.Enemy Scan", "J.怪物扫描", "EnemyOverlayEnabled", "启用", "If disabled, enemy labels are turned off.", "关闭后不再显示怪物局内标签;显示按键、扫描距离、字体大小和米数显示同步使用 B.扫描设置 的设置。默认开启。", defaultVal: true, null, 800);
		enemyProximityAutoShowEnabled = BindI18N("J.Enemy Scan", "J.怪物扫描", "EnemyProximityAutoShowEnabled", "启用靠近自动显示", "Temporarily show enemy label when close, disappears after 5 seconds of leaving.", "怪物进入靠近自动显示距离时,会临时显示怪物标签;怪物离开范围后5秒恢复。靠近自动显示距离可独立大于 B.扫描设置 的扫描距离。", defaultVal: true, null, 790);
		enemyProximityAutoShowDistance = BindI18N("J.Enemy Scan", "J.怪物扫描", "EnemyProximityAutoShowDistance", "靠近自动显示距离/米", "Proximity auto-show range in meters.", "怪物距离你多少米以内时自动临时显示。这个距离可以独立大于 B.扫描设置 的扫描距离。默认30米。", 30, (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 100), 780);
	}

	private void ResetConfigIfVersionChanged()
	{
		try
		{
			string configFilePath = ((BaseUnityPlugin)this).Config.ConfigFilePath;
			string text = ReadConfigPluginVersion(configFilePath);
			if (!string.IsNullOrWhiteSpace(text) && !(text == "1.2.3"))
			{
				ResetConfigFileToDefaults(configFilePath);
				((BaseUnityPlugin)this).Logger.LogWarning((object)"Config version changed. Old config was reset to defaults.");
			}
		}
		catch (Exception ex)
		{
			((BaseUnityPlugin)this).Logger.LogWarning((object)("Failed to reset config by version: " + ex.Message));
		}
	}

	private static string ReadConfigPluginVersion(string configPath)
	{
		if (!File.Exists(configPath))
		{
			return null;
		}
		string input = File.ReadAllText(configPath);
		Match match = Regex.Match(input, "(?m)^SuperScannerModVersion\\s*=\\s*(.+?)\\s*$");
		if (!match.Success)
		{
			match = Regex.Match(input, "(?m)^模组版本号\\s*=\\s*(.+?)\\s*$");
		}
		if (!match.Success)
		{
			return null;
		}
		return match.Groups[1].Value.Trim();
	}

	private void ResetConfigFileToDefaults(string configPath)
	{
		((BaseUnityPlugin)this).Config.Clear();
		if (File.Exists(configPath))
		{
			File.Delete(configPath);
		}
		((BaseUnityPlugin)this).Config.Reload();
	}

	private static void DrawInfo(ConfigEntryBase entry)
	{
		GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
		GUILayout.Label(entry.Definition.Key, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.ExpandWidth(true) });
		GUILayout.Label(entry.BoxedValue?.ToString() ?? string.Empty, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(160f) });
		GUILayout.EndHorizontal();
	}

	private void Update()
	{
		//IL_0108: Unknown result type (might be due to invalid IL or missing references)
		try
		{
			if (!IsModEnabled())
			{
				visibleTimer = 0f;
				scanCooldownTimer = 0f;
				ClearScanLabels();
				ClearEnemyLabels();
				ClearEnemyProximityTracking();
				enemyVisibleTimer = 0f;
				enemyProximityVisibleTimer = 0f;
				return;
			}
			if ((Object)(object)InputManager.instance != (Object)null && (!inputActionsRegistered || registeredInputManager != InputManager.instance))
			{
				EnsureInputActionsRegistered();
			}
			if (!CanUseLocalScan())
			{
				visibleTimer = 0f;
				scanCooldownTimer = 0f;
				ClearScanLabels();
			}
			else if (scannerEnabled == null || !scannerEnabled.Value)
			{
				visibleTimer = 0f;
				scanCooldownTimer = 0f;
				ClearScanLabels();
			}
			else
			{
				if (scanCooldownTimer > 0f)
				{
					scanCooldownTimer = Mathf.Max(0f, scanCooldownTimer - Time.deltaTime);
				}
				if ((Object)(object)InputManager.instance != (Object)null && SemiFunc.InputDown(ScanInputKey))
				{
					if (scanCooldownTimer <= 0f)
					{
						visibleTimer = GetScanHoldSeconds();
						scanCooldownTimer = ClampScanInterval((scanIntervalSeconds == null) ? 1f : ((float)scanIntervalSeconds.Value));
						LogScanDebug($"[ScanDebug] InputDown accepted. visibleTimer={visibleTimer:F2}, cooldown={scanCooldownTimer:F2}, trackedValuables={trackedValuables.Count}, trackedItems={trackedItems.Count}, trackedEnemies={trackedEnemies.Count}");
						if (alwaysTriggerShare != null && alwaysTriggerShare.Value)
						{
							sharedValuableIds.Clear();
							sharedCustomDiscoverIds.Clear();
						}
						RefreshLabels();
					}
					else
					{
						LogScanDebug($"[ScanDebug] InputDown ignored by cooldown. remaining={scanCooldownTimer:F2}");
					}
				}
				if (visibleTimer > 0f)
				{
					visibleTimer = Mathf.Max(0f, visibleTimer - Time.deltaTime);
				}
				if (visibleTimer <= 0f)
				{
					ClearScanLabels();
				}
			}
			UpdateEnemyOverlayState();
		}
		catch (Exception arg)
		{
			((BaseUnityPlugin)this).Logger.LogError((object)$"[ScanDebug] Exception in Update: {arg}");
		}
	}

	private void RefreshLabels()
	{
		//IL_089b: Unknown result type (might be due to invalid IL or missing references)
		//IL_08a0: Unknown result type (might be due to invalid IL or missing references)
		//IL_08ac: Unknown result type (might be due to invalid IL or missing references)
		//IL_08b1: Unknown result type (might be due to invalid IL or missing references)
		//IL_08b3: Unknown result type (might be due to invalid IL or missing references)
		//IL_08b5: Unknown result type (might be due to invalid IL or missing references)
		//IL_08b7: Unknown result type (might be due to invalid IL or missing references)
		//IL_08bc: Unknown result type (might be due to invalid IL or missing references)
		//IL_0956: Unknown result type (might be due to invalid IL or missing references)
		//IL_0958: Unknown result type (might be due to invalid IL or missing references)
		//IL_095f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0961: Unknown result type (might be due to invalid IL or missing references)
		//IL_0129: Unknown result type (might be due to invalid IL or missing references)
		//IL_012e: Unknown result type (might be due to invalid IL or missing references)
		//IL_013b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0140: Unknown result type (might be due to invalid IL or missing references)
		//IL_0142: Unknown result type (might be due to invalid IL or missing references)
		//IL_0144: Unknown result type (might be due to invalid IL or missing references)
		//IL_0146: Unknown result type (might be due to invalid IL or missing references)
		//IL_014b: Unknown result type (might be due to invalid IL or missing references)
		//IL_01cc: Unknown result type (might be due to invalid IL or missing references)
		//IL_01ce: Unknown result type (might be due to invalid IL or missing references)
		//IL_01d5: Unknown result type (might be due to invalid IL or missing references)
		//IL_01d7: Unknown result type (might be due to invalid IL or missing references)
		//IL_0a78: Unknown result type (might be due to invalid IL or missing references)
		//IL_0a7d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0a81: Unknown result type (might be due to invalid IL or missing references)
		//IL_0a85: Unknown result type (might be due to invalid IL or missing references)
		//IL_0a8a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0a8c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0a8e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0a90: Unknown result type (might be due to invalid IL or missing references)
		//IL_0a95: Unknown result type (might be due to invalid IL or missing references)
		//IL_0656: Unknown result type (might be due to invalid IL or missing references)
		//IL_065b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0668: Unknown result type (might be due to invalid IL or missing references)
		//IL_066d: Unknown result type (might be due to invalid IL or missing references)
		//IL_066f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0671: Unknown result type (might be due to invalid IL or missing references)
		//IL_0673: Unknown result type (might be due to invalid IL or missing references)
		//IL_0678: Unknown result type (might be due to invalid IL or missing references)
		//IL_0b25: Unknown result type (might be due to invalid IL or missing references)
		//IL_0b27: Unknown result type (might be due to invalid IL or missing references)
		//IL_0b2e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0b30: Unknown result type (might be due to invalid IL or missing references)
		//IL_0720: Unknown result type (might be due to invalid IL or missing references)
		//IL_0722: Unknown result type (might be due to invalid IL or missing references)
		//IL_0729: Unknown result type (might be due to invalid IL or missing references)
		//IL_072b: Unknown result type (might be due to invalid IL or missing references)
		//IL_042d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0432: Unknown result type (might be due to invalid IL or missing references)
		//IL_043f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0444: Unknown result type (might be due to invalid IL or missing references)
		//IL_0446: Unknown result type (might be due to invalid IL or missing references)
		//IL_0448: Unknown result type (might be due to invalid IL or missing references)
		//IL_044a: Unknown result type (might be due to invalid IL or missing references)
		//IL_044f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0520: Unknown result type (might be due to invalid IL or missing references)
		//IL_0522: Unknown result type (might be due to invalid IL or missing references)
		//IL_0529: Unknown result type (might be due to invalid IL or missing references)
		//IL_052b: Unknown result type (might be due to invalid IL or missing references)
		try
		{
			ClearScanLabels();
			seenObjects.Clear();
			int num = 0;
			int num2 = 0;
			int num3 = 0;
			int num4 = 0;
			int num5 = 0;
			int num6 = 0;
			if (!TryGetScanOriginPosition(out var position))
			{
				LogScanDebug("[ScanDebug] RefreshLabels aborted: no local scan origin.");
				return;
			}
			float scanDistanceSquared = GetScanDistanceSquared();
			bool showDistance = ShouldShowDistanceMeters();
			bool showName = ShouldShowValuableNames();
			bool showPrice = ShouldShowValuablePrices();
			ForceRefreshContainmentSets();
			Vector3 val;
			if (showValuables == null || showValuables.Value)
			{
				PruneTrackedCollection<ValuableObject>(trackedValuables, trackedValuableSet);
				foreach (ValuableObject trackedValuable in trackedValuables)
				{
					num++;
					if ((Object)(object)trackedValuable == (Object)null || IsVehicleCached((Component)(object)trackedValuable) || !IsObjectUsable(((Component)trackedValuable).gameObject))
					{
						continue;
					}
					PhysGrabObject physGrabObjectCached = GetPhysGrabObjectCached((Component)(object)trackedValuable, ValuablePhysGrabObjectField);
					if (IsPhysGrabObjectHiddenOrDead(physGrabObjectCached) || IsHeldByLocalPlayer(physGrabObjectCached) || IsObjectInCart((Component)(object)trackedValuable, physGrabObjectCached) || IsObjectInHaul((Component)(object)trackedValuable, physGrabObjectCached))
					{
						continue;
					}
					Renderer[] usableRenderersCached = GetUsableRenderersCached((Component)(object)trackedValuable);
					Vector3 objectAnchorPosition = GetObjectAnchorPosition(((Component)trackedValuable).transform, physGrabObjectCached);
					Vector3 objectCenter = GetObjectCenter(((Component)trackedValuable).transform, physGrabObjectCached, usableRenderersCached);
					val = objectCenter - position;
					float sqrMagnitude = ((Vector3)(ref val)).sqrMagnitude;
					if (!(sqrMagnitude > scanDistanceSquared))
					{
						int instanceID = ((Object)trackedValuable).GetInstanceID();
						seenObjects.Add(instanceID);
						int distanceMeters = Mathf.RoundToInt(Mathf.Sqrt(sqrMagnitude));
						string valuableDisplayNameCached = GetValuableDisplayNameCached(trackedValuable);
						ScanLabel scanLabel = RentScanLabel();
						scanLabel.Target = (Component)(object)trackedValuable;
						scanLabel.PhysGrabObject = physGrabObjectCached;
						scanLabel.IsValuable = true;
						scanLabel.ShareMode = TeamShareMode.Valuable;
						scanLabel.DisplayName = valuableDisplayNameCached;
						scanLabel.Renderers = usableRenderersCached;
						scanLabel.Position = objectCenter;
						scanLabel.LastAnchorPosition = objectAnchorPosition;
						scanLabel.HasAnchorPosition = true;
						scanLabel.DistanceSquared = sqrMagnitude;
						scanLabel.DistanceMeters = distanceMeters;
						if (!RefreshValuableLabelText(scanLabel, trackedValuable, distanceMeters, sqrMagnitude, showDistance, showName, showPrice))
						{
							ReturnScanLabel(scanLabel);
							continue;
						}
						labels.Add(scanLabel);
						num2++;
					}
				}
			}
			bool flag = showLotteryCoinBoxes != null && showLotteryCoinBoxes.Value;
			bool flag2 = showCarts == null || showCarts.Value;
			bool flag3 = flag2 && ((showBigCarts != null && showBigCarts.Value) || (showSmallCarts != null && showSmallCarts.Value));
			if ((showItems != null && showItems.Value) || flag3)
			{
				PruneTrackedCollection<ItemAttributes>(trackedItems, trackedItemSet);
				foreach (ItemAttributes trackedItem in trackedItems)
				{
					num3++;
					if ((Object)(object)trackedItem == (Object)null || IsVehicleCached((Component)(object)trackedItem) || !IsObjectUsable(((Component)trackedItem).gameObject) || HasValuableObjectCached(trackedItem))
					{
						continue;
					}
					PhysGrabObject physGrabObjectCached2 = GetPhysGrabObjectCached((Component)(object)trackedItem, ItemPhysGrabObjectField);
					if (IsPhysGrabObjectHiddenOrDead(physGrabObjectCached2) || IsHeldByLocalPlayer(physGrabObjectCached2) || IsObjectInCart((Component)(object)trackedItem, physGrabObjectCached2) || IsObjectInHaul((Component)(object)trackedItem, physGrabObjectCached2) || IsShopItemCached(trackedItem))
					{
						continue;
					}
					CartScanInfo cartScanInfoCached = GetCartScanInfoCached((Component)(object)trackedItem, physGrabObjectCached2);
					bool isCart = cartScanInfoCached.IsCart;
					bool isSmallCart = cartScanInfoCached.IsSmallCart;
					if ((isCart && !flag2) || (isCart && !isSmallCart && (showBigCarts == null || !showBigCarts.Value)) || (isCart && isSmallCart && (showSmallCarts == null || !showSmallCarts.Value)) || (!isCart && !ShouldScanItemCached(trackedItem)) || (!isCart && (showItems == null || !showItems.Value)))
					{
						continue;
					}
					Renderer[] usableRenderersCached2 = GetUsableRenderersCached((Component)(object)trackedItem);
					Vector3 objectAnchorPosition2 = GetObjectAnchorPosition(((Component)trackedItem).transform, physGrabObjectCached2);
					Vector3 objectCenter2 = GetObjectCenter(((Component)trackedItem).transform, physGrabObjectCached2, usableRenderersCached2);
					val = objectCenter2 - position;
					float sqrMagnitude2 = ((Vector3)(ref val)).sqrMagnitude;
					if (sqrMagnitude2 > scanDistanceSquared)
					{
						continue;
					}
					string text;
					string colorHex;
					if (isCart)
					{
						text = ((InstanceLanguage != DisplayLanguage.English) ? (isSmallCart ? "小推车" : "推车") : (isSmallCart ? "Small Cart" : "Cart"));
						colorHex = "#ffd84d";
					}
					else
					{
						text = GetItemDisplayNameCached(trackedItem);
						colorHex = "#62d8ff";
					}
					if (!string.IsNullOrWhiteSpace(text))
					{
						int distanceMeters2 = Mathf.RoundToInt(Mathf.Sqrt(sqrMagnitude2));
						ScanLabel scanLabel2 = RentScanLabel();
						scanLabel2.Target = (Component)(object)trackedItem;
						scanLabel2.PhysGrabObject = physGrabObjectCached2;
						scanLabel2.IsItem = true;
						scanLabel2.IsCart = isCart;
						scanLabel2.IsSmallCart = isSmallCart;
						scanLabel2.ShareMode = TeamShareMode.None;
						scanLabel2.ColorHex = colorHex;
						scanLabel2.DisplayName = text;
						scanLabel2.Renderers = usableRenderersCached2;
						scanLabel2.Position = objectCenter2;
						scanLabel2.LastAnchorPosition = objectAnchorPosition2;
						scanLabel2.HasAnchorPosition = true;
						scanLabel2.DistanceSquared = sqrMagnitude2;
						scanLabel2.DistanceMeters = distanceMeters2;
						if (!RefreshItemLabelText(scanLabel2, distanceMeters2, sqrMagnitude2, showDistance))
						{
							ReturnScanLabel(scanLabel2);
							continue;
						}
						labels.Add(scanLabel2);
						num4++;
					}
				}
			}
			if (flag)
			{
				PruneTrackedCollection<ValuableDiscoverCustom>(trackedDiscoverCustoms, trackedDiscoverCustomSet);
				foreach (ValuableDiscoverCustom trackedDiscoverCustom in trackedDiscoverCustoms)
				{
					num5++;
					if ((Object)(object)trackedDiscoverCustom == (Object)null || !IsObjectUsable(((Component)trackedDiscoverCustom).gameObject) || seenObjects.Contains(((Object)trackedDiscoverCustom).GetInstanceID()))
					{
						continue;
					}
					PhysGrabObject physGrabObjectCached3 = GetPhysGrabObjectCached((Component)(object)trackedDiscoverCustom, ValuableDiscoverCustomPhysGrabObjectField);
					if (IsPhysGrabObjectHiddenOrDead(physGrabObjectCached3) || IsHeldByLocalPlayer(physGrabObjectCached3) || IsObjectInCart((Component)(object)trackedDiscoverCustom, physGrabObjectCached3) || IsObjectInHaul((Component)(object)trackedDiscoverCustom, physGrabObjectCached3))
					{
						continue;
					}
					Renderer[] usableRenderersCached3 = GetUsableRenderersCached((Component)(object)trackedDiscoverCustom);
					Vector3 objectAnchorPosition3 = GetObjectAnchorPosition(((Component)trackedDiscoverCustom).transform, physGrabObjectCached3);
					Vector3 objectCenter3 = GetObjectCenter(((Component)trackedDiscoverCustom).transform, physGrabObjectCached3, usableRenderersCached3);
					val = objectCenter3 - position;
					float sqrMagnitude3 = ((Vector3)(ref val)).sqrMagnitude;
					if (!(sqrMagnitude3 > scanDistanceSquared))
					{
						int instanceID2 = ((Object)trackedDiscoverCustom).GetInstanceID();
						seenObjects.Add(instanceID2);
						int distanceMeters3 = Mathf.RoundToInt(Mathf.Sqrt(sqrMagnitude3));
						string customDiscoverColorHexCached = GetCustomDiscoverColorHexCached(trackedDiscoverCustom);
						string displayName = ((InstanceLanguage == DisplayLanguage.English) ? "Decor Box" : "装饰箱");
						ScanLabel scanLabel3 = RentScanLabel();
						scanLabel3.Target = (Component)(object)trackedDiscoverCustom;
						scanLabel3.PhysGrabObject = physGrabObjectCached3;
						scanLabel3.IsItem = true;
						scanLabel3.IsLotteryCoinBox = true;
						scanLabel3.ShareMode = TeamShareMode.LotteryCoinBox;
						scanLabel3.ColorHex = customDiscoverColorHexCached;
						scanLabel3.DisplayName = displayName;
						scanLabel3.Renderers = usableRenderersCached3;
						scanLabel3.Position = objectCenter3;
						scanLabel3.LastAnchorPosition = objectAnchorPosition3;
						scanLabel3.HasAnchorPosition = true;
						scanLabel3.DistanceSquared = sqrMagnitude3;
						scanLabel3.DistanceMeters = distanceMeters3;
						if (!RefreshItemLabelText(scanLabel3, distanceMeters3, sqrMagnitude3, showDistance))
						{
							ReturnScanLabel(scanLabel3);
							continue;
						}
						labels.Add(scanLabel3);
						num6++;
					}
				}
			}
			bool num7 = showVehicles == null || showVehicles.Value;
			bool flag4 = showCargoVehicles != null && showCargoVehicles.Value;
			bool flag5 = showRacingVehicles != null && showRacingVehicles.Value;
			if (num7 && (flag4 || flag5))
			{
				PruneTrackedCollection<ItemVehicle>(trackedVehicles, trackedVehicleSet);
				foreach (ItemVehicle trackedVehicle in trackedVehicles)
				{
					if ((Object)(object)trackedVehicle == (Object)null || !IsObjectUsable(((Component)trackedVehicle).gameObject))
					{
						continue;
					}
					bool flag6 = false;
					if (ItemVehicleIsRacingField != null)
					{
						try
						{
							flag6 = (bool)ItemVehicleIsRacingField.GetValue(trackedVehicle);
						}
						catch (Exception ex)
						{
							((BaseUnityPlugin)this).Logger.LogWarning((object)("Failed to read isRacingVehicle: " + ex.Message));
						}
					}
					if ((flag6 && !flag5) || (!flag6 && !flag4))
					{
						continue;
					}
					Renderer[] usableRenderersCached4 = GetUsableRenderersCached((Component)(object)trackedVehicle);
					Vector3 position2 = ((Component)trackedVehicle).transform.position;
					Vector3 objectCenter4 = GetObjectCenter(((Component)trackedVehicle).transform, null, usableRenderersCached4);
					val = objectCenter4 - position;
					float sqrMagnitude4 = ((Vector3)(ref val)).sqrMagnitude;
					if (sqrMagnitude4 > scanDistanceSquared)
					{
						continue;
					}
					int distanceMeters4 = Mathf.RoundToInt(Mathf.Sqrt(sqrMagnitude4));
					string vehicleDisplayName = ItemNameLocalizer.GetVehicleDisplayName(flag6, InstanceLanguage);
					if (!string.IsNullOrWhiteSpace(vehicleDisplayName))
					{
						string colorHex2 = "#ffd84d";
						ScanLabel scanLabel4 = RentScanLabel();
						scanLabel4.Target = (Component)(object)trackedVehicle;
						scanLabel4.PhysGrabObject = null;
						scanLabel4.IsItem = false;
						scanLabel4.IsVehicle = true;
						scanLabel4.IsRacingVehicle = flag6;
						scanLabel4.ShareMode = TeamShareMode.None;
						scanLabel4.ColorHex = colorHex2;
						scanLabel4.DisplayName = vehicleDisplayName;
						scanLabel4.Renderers = usableRenderersCached4;
						scanLabel4.Position = objectCenter4;
						scanLabel4.LastAnchorPosition = position2;
						scanLabel4.HasAnchorPosition = true;
						scanLabel4.DistanceSquared = sqrMagnitude4;
						scanLabel4.DistanceMeters = distanceMeters4;
						if (!RefreshItemLabelText(scanLabel4, distanceMeters4, sqrMagnitude4, showDistance))
						{
							ReturnScanLabel(scanLabel4);
						}
						else
						{
							labels.Add(scanLabel4);
						}
					}
				}
			}
			bool num8 = showTeammates == null || showTeammates.Value;
			bool flag7 = showAliveTeammates != null && showAliveTeammates.Value;
			bool flag8 = showDeadTeammates == null || showDeadTeammates.Value;
			if (num8 && (flag7 || flag8))
			{
				foreach (PlayerAvatar allPlayer in GetAllPlayers())
				{
					if ((Object)(object)allPlayer == (Object)null || !IsPlayerAvatarUsable(allPlayer) || IsPlayerAvatarLocal(allPlayer))
					{
						continue;
					}
					bool flag9 = IsPlayerDead(allPlayer);
					if (flag9)
					{
						if (!flag8)
						{
							continue;
						}
					}
					else if (!flag7)
					{
						continue;
					}
					Vector3 playerReferencePosition = GetPlayerReferencePosition(allPlayer, flag9);
					Vector3 playerLabelPosition = GetPlayerLabelPosition(allPlayer, playerReferencePosition, flag9);
					val = playerLabelPosition - position;
					float sqrMagnitude5 = ((Vector3)(ref val)).sqrMagnitude;
					if (sqrMagnitude5 > scanDistanceSquared)
					{
						continue;
					}
					int distanceMeters5 = Mathf.RoundToInt(Mathf.Sqrt(sqrMagnitude5));
					string playerName = GetPlayerName(allPlayer);
					if (!string.IsNullOrWhiteSpace(playerName))
					{
						ScanLabel scanLabel5 = RentScanLabel();
						scanLabel5.Target = (Component)(object)allPlayer;
						scanLabel5.PhysGrabObject = null;
						scanLabel5.IsTeammate = true;
						scanLabel5.IsDeadTeammate = flag9;
						scanLabel5.ShareMode = TeamShareMode.None;
						scanLabel5.ColorHex = "#FFFFFF";
						scanLabel5.DisplayName = playerName;
						scanLabel5.Renderers = GetUsableRenderersCached((Component)(object)allPlayer);
						scanLabel5.Position = playerLabelPosition;
						scanLabel5.LastAnchorPosition = playerReferencePosition;
						scanLabel5.HasAnchorPosition = true;
						scanLabel5.DistanceSquared = sqrMagnitude5;
						scanLabel5.DistanceMeters = distanceMeters5;
						if (!RefreshTeammateLabelText(scanLabel5, distanceMeters5, sqrMagnitude5, showDistance))
						{
							ReturnScanLabel(scanLabel5);
						}
						else
						{
							labels.Add(scanLabel5);
						}
					}
				}
			}
			labels.Sort(CompareScanLabels);
			LogScanDebug($"[ScanDebug] RefreshLabels done. valuableCandidates={num}, valuableAdded={num2}, itemCandidates={num3}, itemAdded={num4}, customCandidates={num5}, customAdded={num6}, totalLabels={labels.Count}, visibleTimer={visibleTimer:F2}");
		}
		catch (Exception arg)
		{
			((BaseUnityPlugin)this).Logger.LogError((object)$"[ScanDebug] Exception in RefreshLabels: {arg}");
		}
	}

	private static int CompareScanLabels(ScanLabel a, ScanLabel b)
	{
		int num = a.DistanceSquared.CompareTo(b.DistanceSquared);
		if (num != 0)
		{
			return num;
		}
		return GetLabelSortPriority(a).CompareTo(GetLabelSortPriority(b));
	}

	private ScanLabel RentScanLabel()
	{
		if (scanLabelPool.Count > 0)
		{
			return scanLabelPool.Pop();
		}
		return new ScanLabel();
	}

	private void ReturnScanLabel(ScanLabel label)
	{
		//IL_0073: Unknown result type (might be due to invalid IL or missing references)
		//IL_0078: Unknown result type (might be due to invalid IL or missing references)
		//IL_007e: 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_010e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0113: Unknown result type (might be due to invalid IL or missing references)
		if (label != null)
		{
			label.Target = null;
			label.PhysGrabObject = null;
			label.Renderers = Array.Empty<Renderer>();
			label.DisplayName = string.Empty;
			label.IsValuable = false;
			label.IsItem = false;
			label.IsCart = false;
			label.IsLotteryCoinBox = false;
			label.IsSmallCart = false;
			label.IsVehicle = false;
			label.IsRacingVehicle = false;
			label.IsTeammate = false;
			label.IsDeadTeammate = false;
			label.ColorHex = "#62d8ff";
			label.Position = Vector3.zero;
			label.LastAnchorPosition = Vector3.zero;
			label.HasAnchorPosition = false;
			label.PlainText = string.Empty;
			label.RichText = string.Empty;
			label.DistanceSquared = 0f;
			label.DistanceMeters = 0;
			label.CachedTextDistanceMeters = int.MinValue;
			label.CachedTextValue = int.MinValue;
			label.CachedShowDistanceMeters = false;
			label.CachedShowValuableNames = false;
			label.CachedShowValuablePrices = false;
			label.CachedIsMasked = false;
			label.ShareMode = TeamShareMode.None;
			label.SharedWithTeam = false;
			label.NextRuntimeRefreshTime = 0f;
			label.CachedLayoutFontSize = int.MinValue;
			label.CachedLayoutSize = Vector2.zero;
			scanLabelPool.Push(label);
		}
	}

	private void ClearScanLabels()
	{
		if (labels.Count != 0)
		{
			for (int i = 0; i < labels.Count; i++)
			{
				ReturnScanLabel(labels[i]);
			}
			labels.Clear();
		}
	}

	private static int GetLabelSortPriority(ScanLabel label)
	{
		if (label.IsTeammate)
		{
			return -1;
		}
		if (label.IsValuable)
		{
			return 0;
		}
		if (label.IsVehicle)
		{
			return 5;
		}
		if (label.IsCart && !label.IsSmallCart)
		{
			return 3;
		}
		if (label.IsCart && label.IsSmallCart)
		{
			return 4;
		}
		if (label.IsLotteryCoinBox)
		{
			return 2;
		}
		return 1;
	}

	private bool RevealValuableToTeam(ValuableObject valuable)
	{
		if ((Object)(object)valuable == (Object)null)
		{
			return false;
		}
		int instanceID = ((Object)valuable).GetInstanceID();
		if (sharedValuableIds.Contains(instanceID))
		{
			return true;
		}
		try
		{
			if (alwaysTriggerShare != null && alwaysTriggerShare.Value)
			{
				if (ValuableObjectDiscoveredField != null && (bool)ValuableObjectDiscoveredField.GetValue(valuable))
				{
					PhysGrabObject physGrabObjectCached = GetPhysGrabObjectCached((Component)(object)valuable, ValuablePhysGrabObjectField);
					if ((Object)(object)ValuableDiscover.instance != (Object)null && (Object)(object)physGrabObjectCached != (Object)null)
					{
						ValuableDiscover.instance.New(physGrabObjectCached, (State)0, (ValuableDiscoverCustom)null);
					}
				}
				else
				{
					valuable.Discover((State)0);
				}
			}
			else
			{
				valuable.Discover((State)0);
			}
			sharedValuableIds.Add(instanceID);
			return true;
		}
		catch (Exception ex)
		{
			((BaseUnityPlugin)this).Logger.LogWarning((object)("Native valuable reveal failed: " + ex.GetType().Name + ": " + ex.Message));
			return false;
		}
	}

	private bool RevealCustomDiscoverToTeam(ValuableDiscoverCustom custom)
	{
		if ((Object)(object)custom == (Object)null)
		{
			return false;
		}
		int instanceID = ((Object)custom).GetInstanceID();
		if (sharedCustomDiscoverIds.Contains(instanceID))
		{
			return true;
		}
		try
		{
			if (alwaysTriggerShare != null && alwaysTriggerShare.Value)
			{
				if (ValuableDiscoverCustomDiscoveredField != null && (bool)ValuableDiscoverCustomDiscoveredField.GetValue(custom))
				{
					PhysGrabObject physGrabObjectCached = GetPhysGrabObjectCached((Component)(object)custom, ValuableDiscoverCustomPhysGrabObjectField);
					if ((Object)(object)ValuableDiscover.instance != (Object)null && (Object)(object)physGrabObjectCached != (Object)null)
					{
						ValuableDiscover.instance.New(physGrabObjectCached, (State)3, custom);
					}
				}
				else
				{
					custom.Discover();
				}
			}
			else
			{
				custom.Discover();
			}
			sharedCustomDiscoverIds.Add(instanceID);
			return true;
		}
		catch (Exception ex)
		{
			((BaseUnityPlugin)this).Logger.LogWarning((object)("Native custom discover reveal failed: " + ex.GetType().Name + ": " + ex.Message));
			return false;
		}
	}

	private void UpdateEnemyOverlayState()
	{
		//IL_0076: Unknown result type (might be due to invalid IL or missing references)
		if (!CanUseLocalScan())
		{
			ClearEnemyLabels();
			ClearEnemyProximityTracking();
			enemyVisibleTimer = 0f;
			enemyProximityVisibleTimer = 0f;
			return;
		}
		if (enemyOverlayEnabled == null || !enemyOverlayEnabled.Value)
		{
			ClearEnemyLabels();
			ClearEnemyProximityTracking();
			enemyVisibleTimer = 0f;
			enemyProximityVisibleTimer = 0f;
			return;
		}
		SyncTrackedEnemiesFromDirector();
		if ((Object)(object)InputManager.instance != (Object)null && SemiFunc.InputHold(ScanInputKey))
		{
			enemyVisibleTimer = GetScanHoldSeconds();
		}
		if (enemyVisibleTimer > 0f)
		{
			enemyVisibleTimer -= Time.deltaTime;
		}
		bool flag = UpdateEnemyProximityAutoShowState();
		UpdateEnemyProximityPopTimers();
		if (!(enemyVisibleTimer > 0f || flag))
		{
			ClearEnemyLabels();
			nextEnemyLabelRefreshTime = 0f;
		}
		else if (enemyLabels.Count == 0 || Time.unscaledTime >= nextEnemyLabelRefreshTime)
		{
			RefreshEnemyLabels();
			nextEnemyLabelRefreshTime = Time.unscaledTime + 0.12f;
		}
	}

	private bool UpdateEnemyProximityAutoShowState()
	{
		if (enemyProximityAutoShowEnabled == null || !enemyProximityAutoShowEnabled.Value)
		{
			enemyProximityVisibleTimer = 0f;
			ClearEnemyProximityTracking();
			return false;
		}
		if (Time.unscaledTime >= nextEnemyProximityRefreshTime)
		{
			UpdateEnemiesWithinProximityDistance(enemyProximityAutoShowDistance.Value);
			nextEnemyProximityRefreshTime = Time.unscaledTime + 0.12f;
		}
		UpdateEnemyProximityLingerTimers();
		bool flag = enemyProximityLingerTimers.Count > 0;
		enemyProximityVisibleTimer = (flag ? 5f : 0f);
		return flag;
	}

	private bool UpdateEnemiesWithinProximityDistance(float distance)
	{
		//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_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)
		enemiesInsideProximityRange.Clear();
		if (!TryGetScanOriginPosition(out var position))
		{
			return false;
		}
		float num = distance * distance;
		CleanupTrackedEnemiesThrottled();
		foreach (Enemy trackedEnemy in trackedEnemies)
		{
			if (!TryGetEnemyFrameState(trackedEnemy, out var state))
			{
				continue;
			}
			Vector3 val = state.ReferencePosition - position;
			if (((Vector3)(ref val)).sqrMagnitude <= num)
			{
				int enemyKey = GetEnemyKey(trackedEnemy);
				enemiesInsideProximityRange.Add(enemyKey);
				if (!enemyProximityLingerTimers.ContainsKey(enemyKey) && !enemyProximityPopTimers.ContainsKey(enemyKey))
				{
					enemyProximityPopTimers[enemyKey] = 1.2f;
				}
				enemyProximityLingerTimers[enemyKey] = 5f;
			}
		}
		return enemiesInsideProximityRange.Count > 0;
	}

	private void UpdateEnemyProximityLingerTimers()
	{
		if (enemyProximityLingerTimers.Count == 0)
		{
			return;
		}
		enemyProximityTimerKeys.Clear();
		expiredEnemyProximityKeys.Clear();
		foreach (KeyValuePair<int, float> enemyProximityLingerTimer in enemyProximityLingerTimers)
		{
			enemyProximityTimerKeys.Add(enemyProximityLingerTimer.Key);
		}
		for (int i = 0; i < enemyProximityTimerKeys.Count; i++)
		{
			int num = enemyProximityTimerKeys[i];
			if (!enemiesInsideProximityRange.Contains(num) && enemyProximityLingerTimers.TryGetValue(num, out var value))
			{
				float num2 = value - Time.deltaTime;
				if (num2 <= 0f)
				{
					expiredEnemyProximityKeys.Add(num);
				}
				else
				{
					enemyProximityLingerTimers[num] = num2;
				}
			}
		}
		for (int j = 0; j < expiredEnemyProximityKeys.Count; j++)
		{
			enemyProximityLingerTimers.Remove(expiredEnemyProximityKeys[j]);
		}
	}

	private void UpdateEnemyProximityPopTimers()
	{
		if (enemyProximityPopTimers.Count == 0)
		{
			return;
		}
		enemyProximityTimerKeys.Clear();
		expiredEnemyProximityKeys.Clear();
		foreach (KeyValuePair<int, float> enemyProximityPopTimer in enemyProximityPopTimers)
		{
			enemyProximityTimerKeys.Add(enemyProximityPopTimer.Key);
		}
		for (int i = 0; i < enemyProximityTimerKeys.Count; i++)
		{
			int num = enemyProximityTimerKeys[i];
			if (enemyProximityPopTimers.TryGetValue(num, out var value))
			{
				float num2 = value - Time.deltaTime;
				if (num2 <= 0f)
				{
					expiredEnemyProximityKeys.Add(num);
				}
				else
				{
					enemyProximityPopTimers[num] = num2;
				}
			}
		}
		for (int j = 0; j < expiredEnemyProximityKeys.Count; j++)
		{
			enemyProximityPopTimers.Remove(expiredEnemyProximityKeys[j]);
		}
	}

	private void ClearEnemyProximityTracking()
	{
		enemiesInsideProximityRange.Clear();
		enemyProximityLingerTimers.Clear();
		enemyProximityPopTimers.Clear();
		enemyProximityTimerKeys.Clear();
		expiredEnemyProximityKeys.Clear();
		nextEnemyProximityRefreshTime = 0f;
	}

	private void RefreshEnemyLabels()
	{
		//IL_0061: Unknown result type (might be due to invalid IL or missing references)
		//IL_0066: Unknown result type (might be due to invalid IL or missing references)
		//IL_0067: 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)
		ClearEnemyLabels();
		if (!TryGetScanOriginPosition(out var position))
		{
			return;
		}
		CleanupTrackedEnemiesThrottled();
		float activeEnemyLabelDistanceSquared = GetActiveEnemyLabelDistanceSquared();
		foreach (Enemy trackedEnemy in trackedEnemies)
		{
			if (TryGetEnemyFrameState(trackedEnemy, out var state) && state.IsUsable)
			{
				string enemyDisplayNameCached = GetEnemyDisplayNameCached(trackedEnemy);
				Transform referenceTransform = state.ReferenceTransform;
				Vector3 val = state.ReferencePosition - position;
				float sqrMagnitude = ((Vector3)(ref val)).sqrMagnitude;
				if (!(sqrMagnitude > activeEnemyLabelDistanceSquared))
				{
					float enemyLabelYOffsetCached = GetEnemyLabelYOffsetCached(trackedEnemy, referenceTransform);
					EnemyLabelInfo enemyLabelInfo = RentEnemyLabel();
					enemyLabelInfo.Enemy = trackedEnemy;
					enemyLabelInfo.Name = enemyDisplayNameCached;
					enemyLabelInfo.ReferenceTransform = referenceTransform;
					enemyLabelInfo.LabelYOffset = enemyLabelYOffsetCached;
					enemyLabelInfo.DistanceSquared = sqrMagnitude;
					enemyLabels.Add(enemyLabelInfo);
				}
			}
		}
		enemyLabels.Sort(CompareEnemyLabelsByDistance);
	}

	private static int CompareEnemyLabelsByDistance(EnemyLabelInfo a, EnemyLabelInfo b)
	{
		return a.DistanceSquared.CompareTo(b.DistanceSquared);
	}

	private EnemyLabelInfo RentEnemyLabel()
	{
		if (enemyLabelPool.Count > 0)
		{
			return enemyLabelPool.Pop();
		}
		return new EnemyLabelInfo();
	}

	private void ClearEnemyLabels()
	{
		//IL_0099: Unknown result type (might be due to invalid IL or missing references)
		//IL_009e: Unknown result type (might be due to invalid IL or missing references)
		if (enemyLabels.Count == 0)
		{
			return;
		}
		for (int i = 0; i < enemyLabels.Count; i++)
		{
			EnemyLabelInfo enemyLabelInfo = enemyLabels[i];
			if (enemyLabelInfo != null)
			{
				enemyLabelInfo.Enemy = null;
				enemyLabelInfo.Name = string.Empty;
				enemyLabelInfo.ReferenceTransform = null;
				enemyLabelInfo.LabelYOffset = 0f;
				enemyLabelInfo.DistanceSquared = 0f;
				enemyLabelInfo.CachedDistanceMeters = -1;
				enemyLabelInfo.CachedShowDistance = false;
				enemyLabelInfo.CachedIsMasked = false;
				enemyLabelInfo.PlainText = string.Empty;
				enemyLabelInfo.RichText = string.Empty;
				enemyLabelInfo.NextRuntimeRefreshTime = 0f;
				enemyLabelInfo.CachedLayoutFontSize = int.MinValue;
				enemyLabelInfo.CachedLayoutSize = Vector2.zero;
				enemyLabelPool.Push(enemyLabelInfo);
			}
		}
		enemyLabels.Clear();
	}

	private string GetEnemyDisplayNameCached(Enemy enemy)
	{
		DisplayLanguage instanceLanguage = InstanceLanguage;
		if ((Object)(object)enemy == (Object)null)
		{
			if (instanceLanguage != DisplayLanguage.English)
			{
				return "未知怪物";
			}
			return "Unknown Enemy";
		}
		bool flag = instanceLanguage == DisplayLanguage.中文 && enemyNicknameEnabled != null && enemyNicknameEnabled.Value;
		if (enemyDisplayNameCacheLanguage != instanceLanguage || enemyDisplayNameCacheNicknames != flag)
		{
			enemyDisplayNameCache.Clear();
			enemyDisplayNameCacheLanguage = instanceLanguage;
			enemyDisplayNameCacheNicknames = flag;
		}
		int enemyKey = GetEnemyKey(enemy);
		if (!enemyDisplayNameCache.TryGetValue(enemyKey, out var value) || string.IsNullOrWhiteSpace(value))
		{
			value = GetEnemyDisplayName(enemy, instanceLanguage, flag);
			enemyDisplayNameCache[enemyKey] = value;
		}
		return value;
	}

	private Transform GetEnemyCenterTransformCached(Enemy enemy)
	{
		if ((Object)(object)enemy == (Object)null)
		{
			return null;
		}
		int enemyKey = GetEnemyKey(enemy);
		if (enemyCenterTransformCache.TryGetValue(enemyKey, out var value) && (Object)(object)value != (Object)null)
		{
			return value;
		}
		object? obj = EnemyCenterTransformField?.GetValue(enemy);
		Transform val = (Transform)((obj is Transform) ? obj : null);
		if ((Object)(object)val != (Object)null)
		{
			enemyCenterTransformCache[enemyKey] = val;
		}
		return val;
	}

	private void CleanupTrackedEnemiesThrottled()
	{
		if (!(Time.unscaledTime < nextEnemyListCleanupTime))
		{
			PruneTrackedCollection<Enemy>(trackedEnemies, trackedEnemySet);
			nextEnemyListCleanupTime = Time.unscaledTime + 1f;
		}
	}

	private float GetEnemyLabelYOffsetCached(Enemy enemy, Transform centerTransform)
	{
		if ((Object)(object)enemy == (Object)null)
		{
			return 1.1f;
		}
		int enemyKey = GetEnemyKey(enemy);
		if (!enemyLabelYOffsetCache.TryGetValue(enemyKey, out var value) || value <= 0.01f)
		{
			value = GetEnemyLabelYOffset(enemy, centerTransform);
			enemyLabelYOffsetCache[enemyKey] = value;
		}
		return value;
	}

	private float GetEnemyLabelYOffset(Enemy enemy, Transform centerTransform)
	{
		//IL_0053: Unknown result type (might be due to invalid IL or missing references)
		//IL_0058: Unknown result type (might be due to invalid IL or missing references)
		//IL_005c: 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_00e5: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f2: Unknown result type (might be due to invalid IL or missing references)
		//IL_00fa: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a9: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ae: 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)
		float result = 1.1f;
		Transform transform = ((Component)enemy).transform;
		if ((Object)(object)transform == (Object)null)
		{
			return result;
		}
		Renderer[] enemyRenderersCached = GetEnemyRenderersCached(enemy);
		Collider[] enemyCollidersCached = GetEnemyCollidersCached(enemy);
		float num = float.MinValue;
		bool flag = false;
		Renderer[] array = enemyRenderersCached;
		foreach (Renderer val in array)
		{
			if (!((Object)(object)val == (Object)null) && val.enabled)
			{
				Bounds bounds = val.bounds;
				float y = ((Bounds)(ref bounds)).max.y;
				if (y > num)
				{
					num = y;
				}
				flag = true;
			}
		}
		if (!flag)
		{
			Collider[] array2 = enemyCollidersCached;
			foreach (Collider val2 in array2)
			{
				if (!((Object)(object)val2 == (Object)null) && val2.enabled)
				{
					Bounds bounds2 = val2.bounds;
					float y2 = ((Bounds)(ref bounds2)).max.y;
					if (y2 > num)
					{
						num = y2;
					}
					flag = true;
				}
			}
		}
		if (flag)
		{
			Vector3 val3 = (((Object)(object)centerTransform != (Object)null) ? centerTransform.position : transform.position);
			result = Mathf.Max(0.5f, num - val3.y + 0.3f);
		}
		return result;
	}

	private Renderer[] GetEnemyRenderersCached(Enemy enemy)
	{
		if ((Object)(object)enemy == (Object)null)
		{
			return Array.Empty<Renderer>();
		}
		int enemyKey = GetEnemyKey(enemy);
		if (!enemyRendererCache.TryGetValue(enemyKey, out var value) || value == null)
		{
			value = ((Component)enemy).GetComponentsInChildren<Renderer>(false) ?? Array.Empty<Renderer>();
			enemyRendererCache[enemyKey] = value;
		}
		return value;
	}

	private Collider[] GetEnemyCollidersCached(Enemy enemy)
	{
		if ((Object)(object)enemy == (Object)null)
		{
			return Array.Empty<Collider>();
		}
		int enemyKey = GetEnemyKey(enemy);
		if (!enemyColliderCache.TryGetValue(enemyKey, out var value) || value == null)
		{
			value = ((Component)enemy).GetComponentsInChildren<Collider>(false) ?? Array.Empty<Collider>();
			enemyColliderCache[enemyKey] = value;
		}
		return value;
	}

	private void ClearEnemyRuntimeCaches()
	{
		ClearEnemyLabels();
		ClearEnemyProximityTracking();
		enemyLabelStyleCache.Clear();
		enemyRendererCache.Clear();
		enemyColliderCache.Clear();
		enemyDisplayNameCache.Clear();
		enemyLabelYOffsetCache.Clear();
		enemyCenterTransformCache.Clear();
		enemyFrameStateCache.Clear();
		cachedEnemyStateFrame = -1;
		nextEnemyLabelRefreshTime = 0f;
		nextEnemyListCleanupTime = 0f;
	}

	private static int GetEnemyKey(Enemy enemy)
	{
		return ((Object)enemy).GetInstanceID();
	}

	private static bool IsEnemyDrawableFast(Enemy enemy)
	{
		if ((Object)(object)enemy != (Object)null && (Object)(object)((Component)enemy).gameObject != (Object)null)
		{
			return ((Component)enemy).gameObject.activeInHierarchy;
		}
		return false;
	}

	private bool ShouldLimitEnemyLabelsToProximity()
	{
		if (enemyProximityAutoShowEnabled != null && enemyProximityAutoShowEnabled.Value && enemyVisibleTimer <= 0f)
		{
			return enemyProximityLingerTimers.Count > 0;
		}
		return false;
	}

	private int GetActiveEnemyLabelDistanceMeters()
	{
		int num = GetScanDistanceMeters();
		if (enemyProximityLingerTimers.Count > 0)
		{
			int num2 = Mathf.Clamp((enemyProximityAutoShowDistance == null) ? 30 : enemyProximityAutoShowDistance.Value, 1, 100);
			return Mathf.Max(num, num2);
		}
		return num;
	}

	private float GetActiveEnemyLabelDistanceSquared()
	{
		int activeEnemyLabelDistanceMeters = GetActiveEnemyLabelDistanceMeters();
		return activeEnemyLabelDistanceMeters * activeEnemyLabelDistanceMeters;
	}

	private string GetEnemyDisplayName(Enemy enemy)
	{
		DisplayLanguage instanceLanguage = InstanceLanguage;
		bool useNicknames = instanceLanguage == DisplayLanguage.中文 && enemyNicknameEnabled != null && enemyNicknameEnabled.Value;
		return GetEnemyDisplayName(enemy, instanceLanguage, useNicknames);
	}

	private string GetEnemyDisplayName(Enemy enemy, DisplayLanguage language, bool useNicknames)
	{
		if ((Object)(object)enemy == (Object)null)
		{
			if (language != DisplayLanguage.English)
			{
				return "未知怪物";
			}
			return "Unknown Enemy";
		}
		object enemyParent = EnemyParentField?.GetValue(enemy);
		if (TryGetEnemyParentDisplayName(enemyParent, out var name))
		{
			return EnemyNameLocalizer.Translate(name, language, useNicknames);
		}
		object obj = EnemyTypeField?.GetValue(enemy);
		if (obj != null)
		{
			string text = obj.ToString();
			if (!string.IsNullOrWhiteSpace(text))
			{
				return EnemyNameLocalizer.Translate(text, language, useNicknames);
			}
		}
		string text2 = CleanName(((Object)(object)((Component)enemy).gameObject == (Object)null) ? string.Empty : ((Object)((Component)enemy).gameObject).name);
		if (!string.IsNullOrWhiteSpace(text2))
		{
			return EnemyNameLocalizer.Translate(text2, language, useNicknames);
		}
		if (language != DisplayLanguage.English)
		{
			return "未知怪物";
		}
		return "Unknown Enemy";
	}

	private bool TryGetEnemyParentDisplayName(object enemyParent, out string name)
	{
		name = string.Empty;
		if (enemyParent == null)
		{
			return false;
		}
		string text = EnemyParentNameField?.GetValue(enemyParent) as string;
		if (!IsInternalEnemyName(text))
		{
			name = text.Trim();
			return true;
		}
		object obj = EnemyParentLocalizedNameField?.GetValue(enemyParent);
		if (obj != null)
		{
			try
			{
				string text2 = LocalizedAssetGetStringMethod?.Invoke(obj, null) as string;
				if (!IsInternalEnemyName(text2))
				{
					name = text2.Trim();
					return true;
				}
			}
			catch
			{
			}
		}
		return false;
	}

	private static bool IsInternalEnemyName(string name)
	{
		if (string.IsNullOrWhiteSpace(name))
		{
			return true;
		}
		string a = name.Trim();
		if (!string.Equals(a, "ENM", StringComparison.OrdinalIgnoreCase))
		{
			return string.Equals(a, "Enemy", StringComparison.OrdinalIgnoreCase);
		}
		return true;
	}

	private bool TryGetEnemyFrameState(Enemy enemy, out EnemyFrameState state)
	{
		state = default(EnemyFrameState);
		if ((Object)(object)enemy == (Object)null)
		{
			return false;
		}
		if (cachedEnemyStateFrame != Time.frameCount)
		{
			cachedEnemyStateFrame = Time.frameCount;
			enemyFrameStateCache.Clear();
		}
		int enemyKey = GetEnemyKey(enemy);
		if (!enemyFrameStateCache.TryGetValue(enemyKey, out state))
		{
			state = BuildEnemyFrameState(enemy);
			enemyFrameStateCache[enemyKey] = state;
		}
		if (state.IsUsable)
		{
			return state.IsAliveAndSpawned;
		}
		return false;
	}

	private EnemyFrameState BuildEnemyFrameState(Enemy enemy)
	{
		//IL_0036: 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)
		//IL_0086: 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_008b: Unknown result type (might be due to invalid IL or missing references)
		EnemyFrameState result = default(EnemyFrameState);
		if ((Object)(object)enemy == (Object)null || (Object)(object)((Component)enemy).gameObject == (Object)null)
		{
			return result;
		}
		int isUsable;
		if (((Component)enemy).gameObject.activeInHierarchy)
		{
			Scene scene = ((Component)enemy).gameObject.scene;
			isUsable = (((Scene)(ref scene)).IsValid() ? 1 : 0);
		}
		else
		{
			isUsable = 0;
		}
		result.IsUsable = (byte)isUsable != 0;
		if (!result.IsUsable)
		{
			return result;
		}
		result.ReferenceTransform = GetEnemyCenterTransformCached(enemy);
		result.ReferencePosition = (((Object)(object)result.ReferenceTransform != (Object)null) ? result.ReferenceTransform.position : ((Component)enemy).transform.position);
		object obj = EnemyHealthField?.GetValue(enemy);
		if (obj != null)
		{
			object obj2 = EnemyHealthDeadField?.GetValue(obj);
			bool flag = default(bool);
			int num;
			if (obj2 is bool)
			{
				flag = (bool)obj2;
				num = 1;
			}
			else
			{
				num = 0;
			}
			if (((uint)num & (flag ? 1u : 0u)) != 0)
			{
				return result;
			}
		}
		object obj3 = EnemyParentField?.GetValue(enemy);
		if (obj3 != null)
		{
			object obj4 = EnemyParentSpawnedField?.GetValue(obj3);
			if (obj4 is bool && !(bool)obj4)
			{
				return result;
			}
		}
		result.IsAliveAndSpawned = true;
		return result;
	}

	private void OnGUI()
	{
		//IL_000a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0010: Invalid comparison between Unknown and I4
		//IL_012b: Unknown result type (might be due to invalid IL or missing references)
		//IL_00e0: Unknown result type (might be due to invalid IL or missing references)
		try
		{
			Event current = Event.current;
			if ((current != null && (int)current.type != 7) || !CanUseLocalScan())
			{
				return;
			}
			bool flag = visibleTimer > 0f && labels.Count > 0;
			bool flag2 = enemyLabels.Count > 0;
			if (!flag && !flag2)
			{
				return;
			}
			Camera worldCameraCached = GetWorldCameraCached();
			if ((Object)(object)worldCameraCached == (Object)null || !TryGetScanOriginPosition(out var position))
			{
				return;
			}
			int maxDistance = GetScanDistanceMeters();
			if (flag)
			{
				float scanDistanceSquared = GetScanDistanceSquared();
				int configuredFontSize = GetConfiguredFontSize();
				bool showDistance = ShouldShowDistanceMeters();
				bool showValuableName = ShouldShowValuableNames();
				bool showValuablePrice = ShouldShowValuablePrices();
				RefreshContainmentSetsForFrame();
				for (int num = labels.Count - 1; num >= 0; num--)
				{
					ScanLabel label = labels[num];
					if (!TryRefreshLabel(label, position, scanDistanceSquared, showDistance, showValuableName, showValuablePrice))
					{
						ReturnScanLabel(label);
						labels.RemoveAt(num);
					}
					else
					{
						int shrinkPercent = 30;
						DrawLabel(worldCameraCached, label, maxDistance, configuredFontSize, shrinkPercent);
					}
				}
			}
			if (flag2)
			{
				DrawEnemyWorldLabels(worldCameraCached, position, GetActiveEnemyLabelDistanceMeters());
			}
		}
		catch (Exception arg)
		{
			((BaseUnityPlugin)this).Logger.LogError((object)$"[ScanDebug] Exception in OnGUI: {arg}");
		}
	}

	private void DrawEnemyWorldLabels(Camera camera, Vector3 localPosition, int enemyMaxDistance)
	{
		//IL_00b7: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a9: Unknown result type (might be due to invalid IL or missing references)
		//IL_00bc: Unknown result type (might be due to invalid IL or missing references)
		//IL_00be: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c0: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c1: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c6: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f7: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f9: Unknown result type (might be due to invalid IL or missing references)
		//IL_0100: Unknown result type (might be due to invalid IL or missing references)
		//IL_0105: Unknown result type (might be due to invalid IL or missing references)
		//IL_010a: 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)
		//IL_024f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0254: Unknown result type (might be due to invalid IL or missing references)
		//IL_0256: Unknown result type (might be due to invalid IL or missing references)
		//IL_025d: Unknown result type (might be due to invalid IL or missing references)
		//IL_026b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0272: Unknown result type (might be due to invalid IL or missing references)
		//IL_0280: Unknown result type (might be due to invalid IL or missing references)
		//IL_028d: Unknown result type (might be due to invalid IL or missing references)
		//IL_029a: Unknown result type (might be due to invalid IL or missing references)
		if (enemyLabels.Count == 0 || (Object)(object)camera == (Object)null)
		{
			return;
		}
		bool flag = ShouldLimitEnemyLabelsToProximity();
		float num = Mathf.Max(1f, (float)enemyMaxDistance);
		num *= num;
		int configuredFontSize = GetConfiguredFontSize();
		bool flag2 = ShouldShowDistanceMeters();
		for (int num2 = enemyLabels.Count - 1; num2 >= 0; num2--)
		{
			EnemyLabelInfo enemyLabelInfo = enemyLabels[num2];
			Enemy enemy = enemyLabelInfo.Enemy;
			if (IsEnemyDrawableFast(enemy))
			{
				int enemyKey = GetEnemyKey(enemy);
				if (!flag || enemyProximityLingerTimers.ContainsKey(enemyKey))
				{
					Vector3 val = (((Object)(object)enemyLabelInfo.ReferenceTransform != (Object)null) ? enemyLabelInfo.ReferenceTransform.position : ((Component)enemy).transform.position);
					Vector3 val2 = val - localPosition;
					float sqrMagnitude = ((Vector3)(ref val2)).sqrMagnitude;
					if (!(sqrMagnitude > num))
					{
						float num3 = ((enemyLabelInfo.LabelYOffset > 0.01f) ? enemyLabelInfo.LabelYOffset : 1.1f);
						Vector3 worldPosition = val + Vector3.up * num3;
						if (TryWorldToGuiPoint(camera, worldPosition, out var guiPosition, out var cameraDepth))
						{
							int num4 = Mathf.RoundToInt(Mathf.Sqrt(sqrMagnitude));
							bool flag3 = !IsScanTargetUnlockedByProximity((Component)(object)enemy, sqrMagnitude);
							bool flag4 = flag2 && !flag3;
							bool num5 = Time.unscaledTime >= enemyLabelInfo.NextRuntimeRefreshTime || enemyLabelInfo.CachedDistanceMeters != num4 || enemyLabelInfo.CachedShowDistance != flag4 || enemyLabelInfo.CachedIsMasked != flag3 || string.IsNullOrWhiteSpace(enemyLabelInfo.PlainText);
							int distanceScaledFontSize = GetDistanceScaledFontSize(configuredFontSize, 30, cameraDepth, enemyMaxDistance, 48);
							if (num5)
							{
								string text = (flag3 ? BuildMaskedLabelText() : (string.IsNullOrWhiteSpace(enemyLabelInfo.Name) ? GetEnemyDisplayName(enemy) : enemyLabelInfo.Name));
								enemyLabelInfo.CachedDistanceMeters = num4;
								enemyLabelInfo.CachedShowDistance = flag4;
								enemyLabelInfo.CachedIsMasked = flag3;
								enemyLabelInfo.PlainText = (flag4 ? $"{text} {num4}m" : text);
								enemyLabelInfo.RichText = "<color=#ff3333>" + enemyLabelInfo.PlainText + "</color>";
								enemyLabelInfo.NextRuntimeRefreshTime = Time.unscaledTime + 0.08f;
								enemyLabelInfo.CachedLayoutFontSize = int.MinValue;
							}
							GUIStyle centeredLabelStyle = GetCenteredLabelStyle(distanceScaledFontSize, shadow: false);
							Vector2 enemyLabelSizeCached = GetEnemyLabelSizeCached(enemyLabelInfo, centeredLabelStyle);
							GUI.Label(new Rect(guiPosition.x - enemyLabelSizeCached.x / 2f, guiPosition.y - enemyLabelSizeCached.y / 2f, enemyLabelSizeCached.x + 14f, enemyLabelSizeCached.y + 4f), enemyLabelInfo.RichText, centeredLabelStyle);
						}
					}
				}
			}
		}
	}

	private GUIStyle GetCenteredLabelStyle(int fontSize, bool shadow)
	{
		//IL_0025: Unknown result type (might be due to invalid IL or missing references)
		//IL_002b: Expected O, but got Unknown
		//IL_0050: 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)
		int key = (shadow ? (-fontSize) : fontSize);
		if (enemyLabelStyleCache.TryGetValue(key, out var value))
		{
			return value;
		}
		GUIStyle val = new GUIStyle(GUI.skin.label);
		val.fontSize = fontSize;
		val.fontStyle = (FontStyle)1;
		val.alignment = (TextAnchor)4;
		val.normal.textColor = (shadow ? Color.black : Color.white);
		enemyLabelStyleCache[key] = val;
		return val;
	}

	private void DrawLabel(Camera camera, ScanLabel label, int maxDistance, int baseFontSize, int shrinkPercent)
	{
		//IL_0007: 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_0038: Unknown result type (might be due to invalid IL or missing references)
		//IL_0062: Unknown result type (might be due to invalid IL or missing references)
		//IL_0071: Unknown result type (might be due to invalid IL or missing references)
		//IL_0084: Unknown result type (might be due to invalid IL or missing references)
		if (label != null && TryWorldToGuiPoint(camera, label.Position, out var guiPosition, out var cameraDepth))
		{
			int distanceScaledFontSize = GetDistanceScaledFontSize(baseFontSize, shrinkPercent, cameraDepth, maxDistance, 48);
			GUIStyle centeredStyle = GetCenteredStyle(distanceScaledFontSize, shadow: false);
			Vector2 scanLabelSizeCached = GetScanLabelSizeCached(label, centeredStyle);
			float num = Mathf.Clamp(scanLabelSizeCached.x + 18f, 80f, 420f);
			float num2 = scanLabelSizeCached.y + 6f;
			GUI.Label(new Rect(guiPosition.x - num / 2f, guiPosition.y - num2 / 2f, num, num2), label.RichText, centeredStyle);
		}
	}

	private bool TryRefreshLabel(ScanLabel label, Vector3 localPosition, float maxDistanceSquared, bool showDistance, bool showValuableName, bool showValuablePrice)
	{
		//IL_009f: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a4: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a8: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ac: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b1: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b3: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b5: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b6: 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_00dc: Unknown result type (might be due to invalid IL or missing references)
		//IL_00de: Unknown result type (might be due to invalid IL or missing references)
		//IL_00e4: Unknown result type (might be due to invalid IL or missing references)
		//IL_00e6: Unknown result type (might be due to invalid IL or missing references)
		//IL_028d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0292: Unknown result type (might be due to invalid IL or missing references)
		//IL_0294: Unknown result type (might be due to invalid IL or missing references)
		//IL_0299: Unknown result type (might be due