Decompiled source of ValuablesScanner v1.2.2

Zichen-ValuablesScanner-1.2.2.dll

Decompiled 2 weeks 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.Configuration;
using HarmonyLib;
using Microsoft.CodeAnalysis;
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-ValuablesScanner-1.2.2")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0+97ae45c624f8b7fff2d14028e0383f3703f6fcff")]
[assembly: AssemblyProduct("Zichen-ValuablesScanner-1.2.2")]
[assembly: AssemblyTitle("Zichen-ValuablesScanner-1.2.2")]
[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.valuablesscanner", "A.Valuables Scanner", "1.2.2")]
public class ZichenValuablesScannerPlugin : 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 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;
	}

	[CompilerGenerated]
	private sealed class <GetComponentTypeNames>d__392 : 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__392(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__392 <GetComponentTypeNames>d__;
			if (<>1__state == -2 && <>l__initialThreadId == Environment.CurrentManagedThreadId)
			{
				<>1__state = 0;
				<GetComponentTypeNames>d__ = this;
			}
			else
			{
				<GetComponentTypeNames>d__ = new <GetComponentTypeNames>d__392(0);
			}
			<GetComponentTypeNames>d__.gameObject = <>3__gameObject;
			return <GetComponentTypeNames>d__;
		}

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

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

		private object <>2__current;

		public ZichenValuablesScannerPlugin <>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__384(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;
			ZichenValuablesScannerPlugin zichenValuablesScannerPlugin = <>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)zichenValuablesScannerPlugin).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;
			}
			zichenValuablesScannerPlugin.DumpItemResources();
			zichenValuablesScannerPlugin.DumpValuableResources();
			((BaseUnityPlugin)zichenValuablesScannerPlugin).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.valuablesscanner";

	public const string PluginVersion = "1.2.2";

	public const string PluginName = "A.Valuables Scanner";

	private static ZichenValuablesScannerPlugin Instance;

	private const string InfoSection = "模组信息";

	private const string GlobalSection = "A.全局设置";

	private const string ScannerSection = "B.扫描设置";

	private const string ValuablesSubSection = "B1.贵重品扫描";

	private const string ItemsSubSection = "B2.装备武器扫描";

	private const string LotterySubSection = "B3.装饰箱扫描";

	private const string CartSubSection = "B4.购物车扫描";

	private const string EnemyScannerSection = "B5.怪物扫描";

	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 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 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 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> showValuables;

	private ConfigEntry<bool> showValuableNames;

	private ConfigEntry<bool> showValuablePrices;

	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<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<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;

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

	private void Awake()
	{
		//IL_0058: Unknown result type (might be due to invalid IL or missing references)
		//IL_0062: Expected O, but got Unknown
		DetachFromManager();
		Instance = this;
		ResetConfigIfVersionChanged();
		BindConfig();
		scanKey.SettingChanged += delegate
		{
			RebindScanKey();
		};
		((BaseUnityPlugin)this).Logger.LogInfo((object)"zichen-valuables-scanner loaded.");
		harmony = new Harmony("zichen.valuablesscanner");
		ApplyHarmonyPatches();
		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()
	{
		ZichenValuablesScannerPlugin 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()
	{
		//IL_0067: Unknown result type (might be due to invalid IL or missing references)
		//IL_0071: Expected O, but got Unknown
		//IL_00ed: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f7: Expected O, but got Unknown
		moduleNameInfo = ((BaseUnityPlugin)this).Config.Bind<string>("模组信息", "模组名称", "价值扫描器", new ConfigDescription("当前模组的中文名称。此处只是提示,不影响功能。", (AcceptableValueBase)null, new object[1]
		{
			new ConfigurationManagerAttributes
			{
				Order = 1000,
				CustomDrawer = DrawInfo,
				ReadOnly = true
			}
		}));
		moduleNameInfo.Value = "价值扫描器";
		moduleVersionInfo = ((BaseUnityPlugin)this).Config.Bind<string>("模组信息", "模组版本号", "1.2.2", new ConfigDescription("当前模组版本号。此处只是提示,不影响功能。", (AcceptableValueBase)null, new object[1]
		{
			new ConfigurationManagerAttributes
			{
				Order = 990,
				CustomDrawer = DrawInfo,
				ReadOnly = true
			}
		}));
		moduleVersionInfo.Value = "1.2.2";
		modEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("A.全局设置", "模组启用", true, ConfigDescriptionWithOrder("关闭后整个模组所有扫描和显示功能都不生效。默认开启。", 1005));
		displayLanguage = ((BaseUnityPlugin)this).Config.Bind<DisplayLanguage>("A.全局设置", "语言/Language", DisplayLanguage.中文, ConfigDescriptionWithOrder("选择扫描标签显示语言。默认中文,English 会显示原始英文名称。", 1000));
		enemyNicknameEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("A.全局设置", "敌人名字优化", true, ConfigDescriptionWithOrder("开启后怪物显示社区昵称(如 大眼哥 等)。关闭后显示标准中文名。默认开启。", 995));
		scannerEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("B.扫描设置", "启用", true, ConfigDescriptionWithOrder("关闭后整个扫描显示都不生效。", 900));
		shareScansWithTeam = ((BaseUnityPlugin)this).Config.Bind<bool>("B.扫描设置", "信息共享队友", true, ConfigDescriptionWithOrder("开启后,只有你主动按扫描键时,且目标距离自己不超过 15 米的贵重品和装饰箱,才会走游戏原生发现同步,队友不装这个模组也能收到发现效果。默认开启;若扫描探索模式开启,则会等目标解除 ? 后才触发一次同步。默认解锁距离为:贵重品 4 米、其他扫描目标 6 米、怪物 20 米。", 895));
		scanExploreMode = ((BaseUnityPlugin)this).Config.Bind<bool>("B.扫描设置", "扫描探索模式", false, ConfigDescriptionWithOrder("开启后扫描标签会先显示 ?,只有目标第一次进入解锁距离后才会显示正常名称、价格和米数。默认解锁距离为:贵重品 4 米、其他扫描目标 6 米、怪物 20 米;贵重品与装饰箱的信息共享也会等到解除 ? 后才触发一次。默认关闭。", 890));
		showValuables = ((BaseUnityPlugin)this).Config.Bind<bool>("B1.贵重品扫描", "启用", true, ConfigDescriptionWithOrder("显示可回收贵重品。", 890));
		showValuableNames = ((BaseUnityPlugin)this).Config.Bind<bool>("B1.贵重品扫描", "显示名称", true, ConfigDescriptionWithOrder("开启后贵重品扫描标签显示物品名称。默认开启。", 889));
		showValuablePrices = ((BaseUnityPlugin)this).Config.Bind<bool>("B1.贵重品扫描", "显示价格", false, ConfigDescriptionWithOrder("开启后贵重品扫描标签显示当前价格。默认关闭。", 888));
		showItems = ((BaseUnityPlugin)this).Config.Bind<bool>("B2.装备武器扫描", "启用", true, ConfigDescriptionWithOrder("显示枪、近战、血包、手雷等装备/武器。", 880));
		showItemNames = ((BaseUnityPlugin)this).Config.Bind<bool>("B2.装备武器扫描", "显示名称", true, ConfigDescriptionWithOrder("开启后装备武器标签显示名称。默认开启。", 879));
		showLotteryCoinBoxes = ((BaseUnityPlugin)this).Config.Bind<bool>("B3.装饰箱扫描", "启用", true, ConfigDescriptionWithOrder("显示关卡中的投币机、硬币宝箱、代币箱和装饰箱。不同类型用不同颜色区分。默认开启。", 870));
		showCarts = ((BaseUnityPlugin)this).Config.Bind<bool>("B4.购物车扫描", "启用", false, ConfigDescriptionWithOrder("购物车扫描总开关。关闭后大购物车和小购物车都不会显示。默认关闭。", 865));
		showBigCarts = ((BaseUnityPlugin)this).Config.Bind<bool>("B4.购物车扫描", "显示大购物车", true, ConfigDescriptionWithOrder("开启后扫描时显示大购物车。默认开启。", 860));
		showSmallCarts = ((BaseUnityPlugin)this).Config.Bind<bool>("B4.购物车扫描", "显示小购物车", true, ConfigDescriptionWithOrder("开启后扫描时显示小购物车。默认开启。", 859));
		showDistanceMeters = ((BaseUnityPlugin)this).Config.Bind<bool>("B.扫描设置", "显示米数", false, ConfigDescriptionWithOrder("开启后扫描标签显示距离米数;关闭后物品、贵重品、装饰箱、购物车和怪物都不显示米数。默认关闭。", 875));
		fontSize = ((BaseUnityPlugin)this).Config.Bind<int>("B.扫描设置", "字体大小", 26, ConfigDescriptionWithOrder("局内物品和怪物扫描标签的字体大小。", (AcceptableValueBase)(object)new AcceptableValueRange<int>(8, 48), 874));
		scanKey = ((BaseUnityPlugin)this).Config.Bind<string>("B.扫描设置", "扫描按键", "F", ConfigDescriptionWithOrder("按下这个按键后显示附近贵重品、装备、购物车、装饰箱和怪物,固定显示5秒。", (AcceptableValueBase)(object)new AcceptableValueList<string>(AvailableKeybinds), 870));
		scanIntervalSeconds = ((BaseUnityPlugin)this).Config.Bind<int>("B.扫描设置", "扫描冷却/秒", 1, ConfigDescriptionWithOrder("按下扫描按键后,多少秒内再次按下不会重新显示。范围1-5秒,每次调整1秒。", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 5), 860));
		scanDistanceMeters = ((BaseUnityPlugin)this).Config.Bind<int>("B.扫描设置", "扫描距离/米", 15, ConfigDescriptionWithOrder("按下扫描按键时,只扫描并显示距离自己多少米以内的物品和怪物。范围1-100米,每次调整1米。默认15米。", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 100), 850));
		enemyOverlayEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("B5.怪物扫描", "启用", true, ConfigDescriptionWithOrder("关闭后不再显示怪物局内标签;显示按键、扫描距离、字体大小和米数显示同步使用 B.扫描设置 的设置。默认开启。", 800));
		enemyProximityAutoShowEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("B5.怪物扫描", "启用靠近自动显示", true, ConfigDescriptionWithOrder("怪物进入靠近自动显示距离时,会临时显示怪物标签;怪物离开范围后5秒恢复。靠近自动显示距离可独立大于 B.扫描设置 的扫描距离。", 790));
		enemyProximityAutoShowDistance = ((BaseUnityPlugin)this).Config.Bind<int>("B5.怪物扫描", "靠近自动显示距离/米", 30, ConfigDescriptionWithOrder("怪物距离你多少米以内时自动临时显示。这个距离可以独立大于 B.扫描设置 的扫描距离。默认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.2"))
			{
				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;
		}
		Match match = Regex.Match(File.ReadAllText(configPath), "(?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 ConfigDescription ConfigDescriptionWithOrder(string description, int order)
	{
		//IL_001c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0022: Expected O, but got Unknown
		return new ConfigDescription(description, (AcceptableValueBase)null, new object[1]
		{
			new ConfigurationManagerAttributes
			{
				Order = order
			}
		});
	}

	private static ConfigDescription ConfigDescriptionWithOrder(string description, AcceptableValueBase acceptableValues, int order)
	{
		//IL_001c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0022: Expected O, but got Unknown
		return new ConfigDescription(description, acceptableValues, new object[1]
		{
			new ConfigurationManagerAttributes
			{
				Order = order
			}
		});
	}

	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_0104: Unknown result type (might be due to invalid IL or missing references)
		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}");
					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();
	}

	private void RefreshLabels()
	{
		//IL_0118: Unknown result type (might be due to invalid IL or missing references)
		//IL_011d: Unknown result type (might be due to invalid IL or missing references)
		//IL_012a: Unknown result type (might be due to invalid IL or missing references)
		//IL_012f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0131: Unknown result type (might be due to invalid IL or missing references)
		//IL_0133: Unknown result type (might be due to invalid IL or missing references)
		//IL_0135: Unknown result type (might be due to invalid IL or missing references)
		//IL_013a: Unknown result type (might be due to invalid IL or missing references)
		//IL_01bb: Unknown result type (might be due to invalid IL or missing references)
		//IL_01bd: Unknown result type (might be due to invalid IL or missing references)
		//IL_01c4: Unknown result type (might be due to invalid IL or missing references)
		//IL_01c6: Unknown result type (might be due to invalid IL or missing references)
		//IL_0638: Unknown result type (might be due to invalid IL or missing references)
		//IL_063d: Unknown result type (might be due to invalid IL or missing references)
		//IL_064a: Unknown result type (might be due to invalid IL or missing references)
		//IL_064f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0651: Unknown result type (might be due to invalid IL or missing references)
		//IL_0653: Unknown result type (might be due to invalid IL or missing references)
		//IL_0655: Unknown result type (might be due to invalid IL or missing references)
		//IL_065a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0702: Unknown result type (might be due to invalid IL or missing references)
		//IL_0704: Unknown result type (might be due to invalid IL or missing references)
		//IL_070b: Unknown result type (might be due to invalid IL or missing references)
		//IL_070d: Unknown result type (might be due to invalid IL or missing references)
		//IL_040f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0414: Unknown result type (might be due to invalid IL or missing references)
		//IL_0421: Unknown result type (might be due to invalid IL or missing references)
		//IL_0426: Unknown result type (might be due to invalid IL or missing references)
		//IL_0428: Unknown result type (might be due to invalid IL or missing references)
		//IL_042a: Unknown result type (might be due to invalid IL or missing references)
		//IL_042c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0431: Unknown result type (might be due to invalid IL or missing references)
		//IL_0502: Unknown result type (might be due to invalid IL or missing references)
		//IL_0504: Unknown result type (might be due to invalid IL or missing references)
		//IL_050b: Unknown result type (might be due to invalid IL or missing references)
		//IL_050d: Unknown result type (might be due to invalid IL or missing references)
		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 (!IsObjectUsable(((Object)(object)trackedValuable == (Object)null) ? null : ((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 (!IsObjectUsable(((Object)(object)trackedItem == (Object)null) ? null : ((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 = "#62d8ff";
				}
				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++;
				}
			}
		}
		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}");
	}

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

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

	private void ReturnScanLabel(ScanLabel label)
	{
		//IL_0057: 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_0062: 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_00f2: 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)
		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.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.IsValuable)
		{
			return 0;
		}
		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
		{
			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
		{
			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)
	{
		if ((Object)(object)enemy == (Object)null)
		{
			return "未知怪物";
		}
		DisplayLanguage instanceLanguage = InstanceLanguage;
		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)
		{
			return "未知怪物";
		}
		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);
		}
		return "未知怪物";
	}

	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_0117: Unknown result type (might be due to invalid IL or missing references)
		//IL_00cc: Unknown result type (might be due to invalid IL or missing references)
		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());
		}
	}

	private void DrawEnemyWorldLabels(Camera camera, Vector3 localPosition, int enemyMaxDistance)
	{
		//IL_00ab: Unknown result type (might be due to invalid IL or missing references)
		//IL_009d: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b0: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b2: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b4: 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_00ba: Unknown result type (might be due to invalid IL or missing references)
		//IL_00eb: 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_00f4: 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_00fe: Unknown result type (might be due to invalid IL or missing references)
		//IL_0102: Unknown result type (might be due to invalid IL or missing references)
		//IL_0243: Unknown result type (might be due to invalid IL or missing references)
		//IL_0248: Unknown result type (might be due to invalid IL or missing references)
		//IL_024a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0251: Unknown result type (might be due to invalid IL or missing references)
		//IL_025f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0266: Unknown result type (might be due to invalid IL or missing references)
		//IL_0274: Unknown result type (might be due to invalid IL or missing references)
		//IL_0281: Unknown result type (might be due to invalid IL or missing references)
		//IL_028e: 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 i = 0; i < enemyLabels.Count; i++)
		{
			EnemyLabelInfo enemyLabelInfo = enemyLabels[i];
			Enemy enemy = enemyLabelInfo.Enemy;
			if (!IsEnemyDrawableFast(enemy))
			{
				continue;
			}
			int enemyKey = GetEnemyKey(enemy);
			if (flag && !enemyProximityLingerTimers.ContainsKey(enemyKey))
			{
				continue;
			}
			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)
			{
				continue;
			}
			float num2 = ((enemyLabelInfo.LabelYOffset > 0.01f) ? enemyLabelInfo.LabelYOffset : 1.1f);
			Vector3 worldPosition = val + Vector3.up * num2;
			if (TryWorldToGuiPoint(camera, worldPosition, out var guiPosition, out var cameraDepth))
			{
				int num3 = Mathf.RoundToInt(Mathf.Sqrt(sqrMagnitude));
				bool flag3 = !IsScanTargetUnlockedByProximity((Component)(object)enemy, sqrMagnitude);
				bool flag4 = flag2 && !flag3;
				bool num4 = Time.unscaledTime >= enemyLabelInfo.NextRuntimeRefreshTime || enemyLabelInfo.CachedDistanceMeters != num3 || enemyLabelInfo.CachedShowDistance != flag4 || enemyLabelInfo.CachedIsMasked != flag3 || string.IsNullOrWhiteSpace(enemyLabelInfo.PlainText);
				int distanceScaledFontSize = GetDistanceScaledFontSize(configuredFontSize, 30, cameraDepth, enemyMaxDistance, 48);
				if (num4)
				{
					string text = (flag3 ? BuildMaskedLabelText() : (string.IsNullOrWhiteSpace(enemyLabelInfo.Name) ? GetEnemyDisplayName(enemy) : enemyLabelInfo.Name));
					enemyLabelInfo.CachedDistanceMeters = num3;
					enemyLabelInfo.CachedShowDistance = flag4;
					enemyLabelInfo.CachedIsMasked = flag3;
					enemyLabelInfo.PlainText = (flag4 ? $"{text} {num3}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_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_0147: Unknown result type (might be due to invalid IL or missing references)
		//IL_0174: Unknown result type (might be due to invalid IL or missing references)
		//IL_0179: Unknown result type (might be due to invalid IL or missing references)
		//IL_017b: Unknown result type (might be due to invalid IL or missing references)
		//IL_017c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0150: Unknown result type (might be due to invalid IL or missing references)
		//IL_0152: Unknown result type (might be due to invalid IL or missing references)
		//IL_0157: Unknown result type (might be due to invalid IL or missing references)
		//IL_015c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0188: Unknown result type (might be due to invalid IL or missing references)
		//IL_0189: Unknown result type (might be due to invalid IL or missing references)
		//IL_018a: Unknown result type (might be due to invalid IL or missing references)
		//IL_018f: Unknown result type (might be due to invalid IL or missing references)
		//IL_01f9: Unknown result type (might be due to invalid IL or missing references)
		//IL_01fa: Unknown result type (might be due to invalid IL or missing references)
		if (label == null || (Object)(object)label.Target == (Object)null || !IsObjectUsable(label.Target.gameObject))
		{
			return false;
		}
		if (!(Time.unscaledTime >= label.NextRuntimeRefreshTime) && label.CachedShowDistanceMeters == showDistance && (!label.IsValuable || (label.CachedShowValuableNames == showValuableName && label.CachedShowValuablePrices == showValuablePrice)))
		{
			return true;
		}
		PhysGrabObject physGrabObject = label.PhysGrabObject;
		if (IsPhysGrabObjectHiddenOrDead(physGrabObject) || IsHeldByLocalPlayer(physGrabObject) || IsObjectInCart(label.Target, physGrabObject) || IsObjectInHaul(label.Target, physGrabObject))
		{
			return false;
		}
		if (label.IsCart && showCarts != null && !showCarts.Value)
		{
			return false;
		}
		if (label.IsCart && !label.IsSmallCart && (showBigCarts == null || !showBigCarts.Value))
		{
			return false;
		}
		if (label.IsCart && label.IsSmallCart && (showSmallCarts == null || !showSmallCarts.Value))
		{
			return false;
		}
		if (label.IsLotteryCoinBox && (showLotteryCoinBoxes == null || !showLotteryCoinBoxes.Value))
		{
			return false;
		}
		Transform transform = label.Target.transform;
		Vector3 objectAnchorPosition = GetObjectAnchorPosition(transform, physGrabObject);
		Vector3 val = label.Position;
		Vector3 val2;
		if (label.HasAnchorPosition)
		{
			val2 = objectAnchorPosition - label.LastAnchorPosition;
			if (!(((Vector3)(ref val2)).sqrMagnitude > 0.0001f))
			{
				goto IL_0188;
			}
		}
		val = GetObjectCenter(transform, physGrabObject, label.Renderers);
		label.LastAnchorPosition = objectAnchorPosition;
		label.HasAnchorPosition = true;
		goto IL_0188;
		IL_0188:
		val2 = val - localPosition;
		float sqrMagnitude = ((Vector3)(ref val2)).sqrMagnitude;
		if (sqrMagnitude > maxDistanceSquared)
		{
			return false;
		}
		int distanceMeters = Mathf.RoundToInt(Mathf.Sqrt(sqrMagnitude));
		if (label.IsValuable)
		{
			Component target = label.Target;
			ValuableObject val3 = (ValuableObject)(object)((target is ValuableObject) ? target : null);
			if (val3 != null)
			{
				if (!RefreshValuableLabelText(label, val3, distanceMeters, sqrMagnitude, showDistance, showValuableName, showValuablePrice))
				{
					return false;
				}
				goto IL_01f8;
			}
		}
		if (label.IsItem && !RefreshItemLabelText(label, distanceMeters, sqrMagnitude, showDistance))
		{
			return false;
		}
		goto IL_01f8;
		IL_01f8:
		label.Position = val;
		label.DistanceSquared = sqrMagnitude;
		label.DistanceMeters = distanceMeters;
		label.NextRuntimeRefreshTime = Time.unscaledTime + 0.08f;
		TryShareLabelWithTeamIfNeeded(label);
		return true;
	}

	private void TryShareLabelWithTeamIfNeeded(ScanLabel label)
	{
		if (label == null || label.SharedWithTeam || label.ShareMode == TeamShareMode.None || shareScansWithTeam == null || !shareScansWithTeam.Value || !IsScanTargetUnlockedByProximity(label.Target, label.DistanceSquared) || label.DistanceMeters > 15)
		{
			return;
		}
		if (label.ShareMode == TeamShareMode.Valuable)
		{
			Component target = label.Target;
			ValuableObject val = (ValuableObject)(object)((target is ValuableObject) ? target : null);
			if (val != null)
			{
				label.SharedWithTeam = RevealValuableToTeam(val);
				return;
			}
		}
		if (label.ShareMode == TeamShareMode.LotteryCoinBox)
		{
			Component target2 = label.Target;
			ValuableDiscoverCustom val2 = (ValuableDiscoverCustom)(object)((target2 is ValuableDiscoverCustom) ? target2 : null);
			if (val2 != null)
			{
				label.SharedWithTeam = RevealCustomDiscoverToTeam(val2);
			}
		}
	}

	private GUIStyle GetCenteredStyle(int size, bool shadow)
	{
		//IL_001e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0023: Unknown result type (might be due to invalid IL or missing references)
		//IL_002a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0031: Unknown result type (might be due to invalid IL or missing references)
		//IL_0038: Unknown result type (might be due to invalid IL or missing references)
		//IL_003f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0046: Unknown result type (might be due to invalid IL or missing references)
		//IL_004e: Expected O, but got Unknown
		//IL_0072: Unknown result type (might be due to invalid IL or missing references)
		//IL_0057: Unknown result type (might be due to invalid IL or missing references)
		Dictionary<int, GUIStyle> dictionary = labelStyleCache;
		if (dictionary.TryGetValue(size, out var value))
		{
			return value;
		}
		GUIStyle val = new GUIStyle(GUI.skin.label)
		{
			alignment = (TextAnchor)4,
			richText = true,
			fontSize = size,
			fontStyle = (FontStyle)1,
			wordWrap = false,
			clipping = (TextClipping)0
		};
		val.normal.textColor = (Color)(shadow ? new Color(0f, 0f, 0f, 0.88f) : Color.white);
		dictionary[size] = val;
		return val;
	}

	private static int GetDistanceScaledFontSize(int baseSize, int shrinkPercent, float distance, float maxDistance, int maxSize)
	{
		baseSize = Mathf.Clamp(baseSize, 8, maxSize);
		shrinkPercent = Mathf.Clamp(shrinkPercent, 0, 75);
		if (maxDistance <= 0.1f || shrinkPercent <= 0)
		{
			return baseSize;
		}
		float num = Mathf.Max(1f, Mathf.Min(maxDistance, 30f));
		float num2 = Mathf.Clamp01(distance / num);
		float num3 = 1f + (float)shrinkPercent / 100f;
		float num4 = 1f - (float)shrinkPercent / 100f;
		float num5 = Mathf.Lerp(num3, num4, num2);
		return Mathf.Clamp(Mathf.RoundToInt((float)baseSize * num5), 8, maxSize);
	}

	private static bool IsObjectUsable(GameObject gameObject)
	{
		//IL_0012: Unknown result type (might be due to invalid IL or missing references)
		//IL_0017: Unknown result type (might be due to invalid IL or missing references)
		if ((Object)(object)gameObject != (Object)null && gameObject.activeInHierarchy)
		{
			Scene scene = gameObject.scene;
			return ((Scene)(ref scene)).IsValid();
		}
		return false;
	}

	private bool IsPhysGrabObjectHiddenOrDead(PhysGrabObject physGrabObject)
	{
		if ((Object)(object)physGrabObject == (Object)null)
		{
			return false;
		}
		if (cachedPhysGrabStateFrame != Time.frameCount)
		{
			cachedPhysGrabStateFrame = Time.frameCount;
			physGrabHiddenOrDeadFrameCache.Clear();
		}
		int instanceID = ((Object)physGrabObject).GetInstanceID();
		if (physGrabHiddenOrDeadFrameCache.TryGetValue(instanceID, out var value))
		{
			return value;
		}
		bool flag = false;
		object obj = PhysGrabObjectDeadField?.GetValue(physGrabObject);
		bool flag2 = default(bool);
		int num;
		if (obj is bool)
		{
			flag2 = (bool)obj;
			num = 1;
		}
		else
		{
			num = 0;
		}
		if (((uint)num & (flag2 ? 1u : 0u)) != 0)
		{
			flag = true;
		}
		else
		{
			obj = PhysGrabObjectIsHiddenField?.GetValue(physGrabObject);
			bool flag3 = default(bool);
			int num2;
			if (obj is bool)
			{
				flag3 = (bool)obj;
				num2 = 1;
			}
			else
			{
				num2 = 0;
			}
			if (((uint)num2 & (flag3 ? 1u : 0u)) != 0)
			{
				flag = true;
			}
		}
		physGrabHiddenOrDeadFrameCache[instanceID] = flag;
		return flag;
	}

	private bool IsObjectInCart(Component component, PhysGrabObject physGrabObject)
	{
		if (!IsObjectInReferenceSet(component, physGrabObject, cartObjectSet))
		{
			return IsPhysGrabObjectMarkedInCart(physGrabObject);
		}
		return true;
	}

	private bool IsObjectInHaul(Component component, PhysGrabObject physGrabObject)
	{
		return IsObjectInReferenceSet(component, physGrabObject, haulObjectSet);
	}

	private static void ClearTrackedCollection<T>(List<T> list, HashSet<T> set) where T : Object
	{
		list.Clear();
		set.Clear();
	}

	private static void PruneTrackedCollection<T>(List<T> list, HashSet<T> set) where T : Object
	{
		bool flag = false;
		for (int num = list.Count - 1; num >= 0; num--)
		{
			if (!((Object)(object)list[num] != (Object)null))
			{
				list.RemoveAt(num);
				flag = true;
			}
		}
		if (!flag)
		{
			return;
		}
		set.Clear();
		for (int i = 0; i < list.Count; i++)
		{
			T val = list[i];
			if ((Object)(object)val != (Object)null)
			{
				set.Add(val);
			}
		}
	}

	private static bool IsObjectInReferenceSet(Component component, PhysGrabObject physGrabObject, HashSet<object> set)
	{
		if (set == null || set.Count == 0)
		{
			return false;
		}
		GameObject val = (((Object)(object)component == (Object)null) ? null : component.gameObject);
		GameObject val2 = (((Object)(object)physGrabObject == (Object)null) ? null : ((Component)physGrabObject).gameObject);
		if (((Object)(object)component != (Object)null && set.Contains(component)) || ((Object)(object)val != (Object)null && set.Contains(val)) || ((Object)(object)physGrabObject != (Object)null && set.Contains(physGrabObject)) || ((Object)(object)val2 != (Object)null && set.Contains(val2)))
		{
			return true;
		}
		return false;
	}

	private static bool IsPhysGrabObjectMarkedInCart(PhysGrabObject physGrabObject)
	{
		if ((Object)(object)physGrabObject == (Object)null)
		{
			return false;
		}
		object obj = PhysGrabObjectImpactDetectorField?.GetValue(physGrabObject);
		bool flag = default(bool);
		int num;
		if (obj != null)
		{
			object obj2 = PhysGrabObjectImpactDetectorInCartField?.GetValue(obj);
			if (obj2 is bool)
			{
				flag = (bool)obj2;
				num = 1;
			}
			else
			{
				num = 0;
			}
		}
		else
		{
			num = 0;
		}
		return (byte)((uint)num & (flag ? 1u : 0u)) != 0;
	}

	private static bool IsCartObject(Component component, PhysGrabObject physGrabObject)
	{
		if ((Object)(object)component != (Object)null && ((Object)(object)component.GetComponent<PhysGrabCart>() != (Object)null || (Object)(object)component.GetComponentInParent<PhysGrabCart>() != (Object)null || (Object)(object)component.GetComponentInChildren<PhysGrabCart>(false) != (Object)null))
		{
			return true;
		}
		if ((Object)(object)physGrabObject != (Object)null)
		{
			if (!((Object)(object)((Component)physGrabObject).GetComponent<PhysGrabCart>() != (Object)null) && !((Object)(object)((Component)physGrabObject).GetComponentInParent<PhysGrabCart>() != (Object)null))
			{
				return (Object)(object)((Component)physGrabObject).GetComponentInChildren<PhysGrabCart>(false) != (Object)null;
			}
			return true;
		}
		return false;
	}

	private static bool ShouldScanItem(ItemAttributes item)
	{
		if ((Object)(object)item == (Object)null)
		{
			return false;
		}
		if (ItemEquippableField?.GetValue(item) != null)
		{
			return true;
		}
		object obj = ItemTypeField?.GetValue(item);
		if (obj != null && !string.IsNullOrWhiteSpace(obj.ToString()))
		{
			return true;
		}
		if (!string.IsNullOrWhiteSpace(ReadTrimmedString(ItemNameField?.GetValue(item))) || !string.IsNullOrWhiteSpace(ReadTrimmedString(ItemPromptNameField?.GetValue(item))) || !string.IsNullOrWhiteSpace(ReadTrimmedString(ItemAssetNameField?.GetValue(item))) || !string.IsNullOrWhiteSpace(ReadTrimmedString(ItemInstanceNameField?.GetValue(item))) || !string.IsNullOrWhiteSpace(ReadTrimmedString(ItemTagField?.GetValue(item))))
		{
			return true;
		}
		string text = (((Object)(object)((Component)item).gameObject == (Object)null) ? string.Empty : ((Object)((Component)item).gameObject).name.ToLowerInvariant());
		for (int i = 0; i < ItemKeywords.Length; i++)
		{
			if (text.Contains(ItemKeywords[i]))
			{
				return true;
			}
		}
		return false;
	}

	private bool ShouldScanItemCached(ItemAttributes item)
	{
		if ((Object)(object)item == (Object)null)
		{
			return false;
		}
		int instanceID = ((Object)item).GetInstanceID();
		if (!itemShouldScanCache.TryGetValue(instanceID, out var value))
		{
			value = ShouldScanItem(item);
			itemShouldScanCache[instanceID] = value;
		}
		return value;
	}

	private void PrimeTrackedItemCaches(ItemAttributes item)
	{
		if (!((Object)(object)item == (Object)null))
		{
			HasValuableObjectCached(item);
			IsShopItemCached(item);
			PhysGrabObject physGrabObjectCached = GetPhysGrabObjectCached((Component)(object)item, ItemPhysGrabObjectField);
			GetCartScanInfoCached((Component)(object)item, physGrabObjectCached);
			ShouldScanItemCached(item);
		}
	}

	private PhysGrabObject GetPhysGrabObjectCached(Component component, FieldInfo field)
	{
		if ((Object)(object)component == (Object)null || field == null)
		{
			return null;
		}
		int instanceID = ((Object)component).GetInstanceID();
		if (!objectPhysGrabCache.TryGetValue(instanceID, out var value))
		{
			object? value2 = field.GetValue(component);
			value = (PhysGrabObject)((value2 is PhysGrabObject) ? value2 : null);
			objectPhysGrabCache[instanceID] = value;
		}
		return value;
	}

	private bool HasValuableObjectCached(ItemAttributes item)
	{
		if ((Object)(object)item == (Object)null)
		{
			return false;
		}
		int instanceID = ((Object)item).GetInstanceID();
		if (!itemHasValuableCache.TryGetValue(instanceID, out var value))
		{
			value = (Object)(object)((Component)item).GetComponent<ValuableObject>() != (Object)null;
			itemHasValuableCache[instanceID] = value;
		}
		return value;
	}

	private bool IsShopItemCached(ItemAttributes item)
	{
		if ((Object)(object)item == (Object)null)
		{
			return false;
		}
		int instanceID = ((Object)item).GetInstanceID();
		if (!itemShopItemCache.TryGetValue(instanceID, out var value))
		{
			object obj = ItemShopItemField?.GetValue(item);
			bool flag = default(bool);
			int num;
			if (obj is bool)
			{
				flag = (bool)obj;
				num = 1;
			}
			else
			{
				num = 0;
			}
			value = (byte)((uint)num & (flag ? 1u : 0u)) != 0;
			itemShopItemCache[instanceID] = value;
		}
		return value;
	}

	private string GetCustomDiscoverColorHexCached(ValuableDiscoverCustom custom)
	{
		//IL_004a: Unknown result type (might be due to invalid IL or missing references)
		//IL_004f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0050: Unknown result type (might be due to invalid IL or missing references)
		//IL_0056: Unknown result type (might be due to invalid IL or missing references)
		//IL_005d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0072: Unknown result type (might be due to invalid IL or missing references)
		if ((Object)(object)custom == (Object)null)
		{
			return "FFFFFF";
		}
		int instanceID = ((Object)custom).GetInstanceID();
		if (!customDiscoverColorCache.TryGetValue(instanceID, out var value) || string.IsNullOrWhiteSpace(value))
		{
			value = ((ValuableDiscoverCustomColorCornerField?.GetValue(custom) is Color val && val.r + val.g + val.b > 0.05f) ? ColorUtility.ToHtmlStringRGB(val) : "FFFFFF");
			customDiscoverColorCache[instanceID] = value;
		}
		return value;
	}

	private CartScanInfo GetCartScanInfoCached(Component component, PhysGrabObject physGrabObject)
	{
		if ((Object)(object)component == (Object)null)
		{
			return default(CartScanInfo);
		}
		int instanceID = ((Object)component).GetInstanceID();
		if (itemCartInfoCache.TryGetValue(instanceID, out var value))
		{
			return value;
		}
		value.IsCart = IsCartObject(component, physGrabObject);
		if (value.IsCart && (Object)(object)physGrabObject != (Object)null)
		{
			PhysGrabCart val = ((Component)physGrabObject).GetComponent<PhysGrabCart>() ?? ((Component)physGrabObject).GetComponentInParent<PhysGrabCart>() ?? ((Component)physGrabObject).GetComponentInChildren<PhysGrabCart>();
			bool flag = default(bool);
			int num;
			if ((Object)(object)val != (Object)null)
			{
				object obj = PhysGrabCartIsSmallField?.GetValue(val);
				if (obj is bool)
				{
					flag = (bool)obj;
					num = 1;
				}
				else
				{
					num = 0;
				}
			}
			else
			{
				num = 0;
			}
			value.IsSmallCart = (byte)((uint)num & (flag ? 1u : 0u)) != 0;
		}
		itemCartInfoCache[instanceID] = value;
		return value;
	}

	private static Renderer[] GetUsableRenderers(Component root)
	{
		if (!((Object)(object)root == (Object)null))
		{
			return root.GetComponentsInChildren<Renderer>(false);
		}
		return Array.Empty<Renderer>();
	}

	private Renderer[] GetUsableRenderersCached(Component root)
	{
		if ((Object)(object)root == (Object)null)
		{
			return Array.Empty<Renderer>();
		}
		int instanceID = ((Object)root).GetInstanceID();
		if (!objectRendererCache.