Decompiled source of PingItems v1.6.2

PingItems.dll

Decompiled a month ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Reflection.Emit;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using System.Text;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using Photon.Pun;
using PingItems.Adapters.Animals;
using PingItems.Adapters.Celestial;
using PingItems.Adapters.Items;
using PingItems.Adapters.SpecialObjects;
using PingItems.Common;
using PingItems.Common.Interfaces;
using PingItems.Configuration;
using PingItems.Core;
using PingItems.Core.Highlighting;
using PingItems.Core.Management;
using PingItems.Factories;
using PingItems.Pooling;
using PingItems.Services;
using PingItems.Spatial;
using TMPro;
using UnityEngine;
using UnityEngine.SceneManagement;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("PingItems")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.6.2.0")]
[assembly: AssemblyInformationalVersion("1.6.2")]
[assembly: AssemblyProduct("Ping Items")]
[assembly: AssemblyTitle("PingItems")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.6.2.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace PingItems
{
	[BepInPlugin("com.memiczny.peak.pingitems", "Ping Items", "1.6.2")]
	[BepInProcess("PEAK.exe")]
	public class Plugin : BaseUnityPlugin
	{
		public static class PluginInfo
		{
			public const string PLUGIN_GUID = "com.memiczny.peak.pingitems";

			public const string PLUGIN_NAME = "Ping Items";

			public const string PLUGIN_VERSION = "1.6.2";
		}

		public static ManualLogSource Logger { get; private set; }

		public static Plugin Instance { get; private set; }

		private void Awake()
		{
			Instance = this;
			Logger = ((BaseUnityPlugin)this).Logger;
			try
			{
				PingItemsConfig.Initialize(((BaseUnityPlugin)this).Config);
				Logger.LogInfo((object)"⚙\ufe0f Configuration initialized");
				ApplyHarmonyPatches();
				InitializeUISystem();
				PingService.Initialize();
				Logger.LogInfo((object)"\ud83d\udce1 Ping service initialized");
				SmartObjectManager.Initialize();
				Logger.LogInfo((object)"\ud83c\udfaf Smart object manager initialized");
				OptimizedPingableFactory.Initialize();
				Logger.LogInfo((object)"⚡ Performance optimizations initialized");
				InitializeCustomLocalization();
				InitializePoolingSystems();
				Logger.LogInfo((object)"\ud83d\ude80 Ping Items v1.6.2 loaded successfully!");
			}
			catch (Exception arg)
			{
				Logger.LogError((object)$"❌ Failed to initialize plugin: {arg}");
			}
		}

		private static void ApplyHarmonyPatches()
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				new Harmony("com.memiczny.peak.pingitems").PatchAll();
				Logger.LogInfo((object)"\ud83d\udd27 Harmony patches applied successfully");
			}
			catch (Exception arg)
			{
				Logger.LogError((object)$"❌ Failed to apply Harmony patches: {arg}");
				throw;
			}
		}

		private static void InitializePoolingSystems()
		{
			ObjectPool.Initialize();
			Logger.LogInfo((object)"\ud83c\udfca Pooling systems initialized (will populate when prefab available)");
		}

		private static void InitializeCustomLocalization()
		{
			try
			{
				CustomLocalization.IntegrateWithGameLocalization();
				Logger.LogInfo((object)"\ud83c\udf0d Custom localization system integrated");
			}
			catch (Exception ex)
			{
				Logger.LogWarning((object)("⚠\ufe0f Failed to initialize custom localization: " + ex.Message));
			}
		}

		public static void PopulateAllPools()
		{
			try
			{
				UIManager instance = UIManager.Instance;
				if ((Object)(object)instance != (Object)null)
				{
					instance.PopulatePools();
				}
				else
				{
					Logger.LogWarning((object)"⚠\ufe0f UIManager not available for pool population");
				}
			}
			catch (Exception ex)
			{
				Logger.LogWarning((object)("⚠\ufe0f Failed to populate pools: " + ex.Message));
			}
		}

		private static void WriteLocalizedTextToFile()
		{
			try
			{
				string text = Path.Combine(Paths.ConfigPath, "LocalizedText.txt");
				File.WriteAllLines(text, LocalizedText.mainTable.Select((KeyValuePair<string, List<string>> entry) => entry.Key + "=" + entry.Value.Aggregate((string a, string b) => a + "," + b)));
				Logger.LogInfo((object)("\ud83d\udcdd Localized text written to " + text));
			}
			catch (Exception arg)
			{
				Logger.LogError((object)$"❌ Failed to write localized text to file: {arg}");
			}
		}

		private static void InitializeUISystem()
		{
			//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)
			//IL_0023: Expected O, but got Unknown
			try
			{
				if ((Object)(object)UIManager.Instance == (Object)null)
				{
					GameObject val = new GameObject("PingItems_UIManager");
					val.AddComponent<UIManager>();
					Object.DontDestroyOnLoad((Object)val);
				}
				Logger.LogInfo((object)"\ud83c\udfa8 UI system initialized");
			}
			catch (Exception arg)
			{
				Logger.LogError((object)$"❌ Failed to initialize UI system: {arg}");
				throw;
			}
		}

		private void OnDestroy()
		{
			try
			{
				ObjectPool.Cleanup();
				Logger.LogInfo((object)"\ud83e\uddf9 Plugin cleanup completed");
			}
			catch (Exception ex)
			{
				Logger.LogWarning((object)("⚠\ufe0f Error during plugin cleanup: " + ex.Message));
			}
		}
	}
}
namespace PingItems.Spatial
{
	public class SpatialGrid
	{
		private readonly float _cellSize;

		private readonly Dictionary<Vector2Int, List<IPingable>> _grid;

		public SpatialGrid(float cellSize = 50f)
		{
			_cellSize = cellSize;
			_grid = new Dictionary<Vector2Int, List<IPingable>>();
		}

		private Vector2Int GetCellCoords(Vector3 worldPos)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			return new Vector2Int(Mathf.FloorToInt(worldPos.x / _cellSize), Mathf.FloorToInt(worldPos.z / _cellSize));
		}

		public void AddObject(IPingable pingable)
		{
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				if (!((Object)(object)pingable?.GetGameObject() == (Object)null))
				{
					Vector3 center = pingable.GetCenter();
					Vector2Int cellCoords = GetCellCoords(center);
					if (!_grid.ContainsKey(cellCoords))
					{
						_grid[cellCoords] = new List<IPingable>();
					}
					_grid[cellCoords].Add(pingable);
				}
			}
			catch (Exception ex)
			{
				if (PingItemsConfig.EnableDebugLogging.Value)
				{
					Plugin.Logger.LogDebug((object)("Failed to add object to spatial grid: " + ex.Message));
				}
			}
		}

		public List<IPingable> FindNearbyObjects(Vector3 position, float radius)
		{
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_0053: Unknown result type (might be due to invalid IL or missing references)
			//IL_008a: Unknown result type (might be due to invalid IL or missing references)
			//IL_008f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0090: Unknown result type (might be due to invalid IL or missing references)
			//IL_0095: Unknown result type (might be due to invalid IL or missing references)
			List<IPingable> list = new List<IPingable>();
			float num = radius * radius;
			Vector2Int cellCoords = GetCellCoords(position);
			int num2 = Mathf.CeilToInt(radius / _cellSize);
			Vector2Int key = default(Vector2Int);
			for (int i = -num2; i <= num2; i++)
			{
				for (int j = -num2; j <= num2; j++)
				{
					((Vector2Int)(ref key))..ctor(((Vector2Int)(ref cellCoords)).x + i, ((Vector2Int)(ref cellCoords)).y + j);
					if (!_grid.TryGetValue(key, out var value))
					{
						continue;
					}
					foreach (IPingable item in value)
					{
						if (!((Object)(object)item?.GetGameObject() == (Object)null))
						{
							Vector3 val = item.GetCenter() - position;
							if (((Vector3)(ref val)).sqrMagnitude <= num)
							{
								list.Add(item);
							}
						}
					}
				}
			}
			return list;
		}

		public void Clear()
		{
			_grid.Clear();
		}

		public (int totalCells, int totalObjects, float avgObjectsPerCell) GetStats()
		{
			int num = 0;
			foreach (List<IPingable> value in _grid.Values)
			{
				num += value.Count;
			}
			float item = ((_grid.Count > 0) ? ((float)num / (float)_grid.Count) : 0f);
			return (_grid.Count, num, item);
		}
	}
}
namespace PingItems.Services
{
	public static class PingService
	{
		private static readonly List<PingHighlighter> _activeHighlights = new List<PingHighlighter>();

		private static readonly Dictionary<GameObject, PingHighlighter> _itemToGroupMapping = new Dictionary<GameObject, PingHighlighter>();

		private static float _lastPingTime = 0f;

		public static void Initialize()
		{
			_activeHighlights.Clear();
			Application.quitting += Cleanup;
		}

		public static void Cleanup()
		{
			foreach (PingHighlighter item in from h in _activeHighlights.AsEnumerable()
				where (Object)(object)h != (Object)null
				select h)
			{
				item.Cleanup();
			}
			_activeHighlights.Clear();
			_itemToGroupMapping.Clear();
			Application.quitting -= Cleanup;
		}

		public static void ProcessPing(Vector3 pingPosition, Color playerColor, string playerName, Character pingingCharacter = null)
		{
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			//IL_007d: 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_00bb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00af: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b0: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				if (!ShouldProcessPing())
				{
					return;
				}
				if (PingItemsConfig.EnableDebugLogging.Value)
				{
					Plugin.Logger.LogDebug((object)$"Processing ping at position: {pingPosition}, player: {playerName}");
				}
				List<IPingable> list = OptimizedPingableFactory.FindPingablesForPing(pingPosition, pingingCharacter, PingItemsConfig.DetectionRadius.Value, PingItemsConfig.LuggageDetectionRadius.Value);
				if (list.Count == 0)
				{
					if (PingItemsConfig.EnableDebugLogging.Value)
					{
						Plugin.Logger.LogDebug((object)"No pingables found near ping position");
					}
					return;
				}
				EnforcePingLimit();
				if (TryRefreshExistingHighlights(list, pingPosition))
				{
					if (PingItemsConfig.EnableDebugLogging.Value)
					{
						Plugin.Logger.LogDebug((object)"Refreshed existing highlights");
					}
					return;
				}
				if (PingItemsConfig.EnableItemGrouping.Value)
				{
					CreateGroupedHighlights(list, pingPosition, playerColor, playerName);
				}
				else
				{
					CreateIndividualHighlights(list, pingPosition, playerColor, playerName);
				}
				if (PingItemsConfig.EnableDebugLogging.Value)
				{
					Plugin.Logger.LogDebug((object)$"Created {list.Count} new ping highlights");
				}
				_lastPingTime = Time.time;
			}
			catch (Exception ex)
			{
				Plugin.Logger.LogError((object)("Error processing ping: " + ex.Message));
			}
		}

		public static void ProcessCelestialPing(Vector3 pingPosition, Color playerColor, string playerName, Character pingingCharacter, List<IPingable> celestialBodies)
		{
			//IL_0080: Unknown result type (might be due to invalid IL or missing references)
			//IL_0081: Unknown result type (might be due to invalid IL or missing references)
			//IL_0075: Unknown result type (might be due to invalid IL or missing references)
			//IL_0076: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				if (celestialBodies == null || celestialBodies.Count == 0)
				{
					DebugLogger.Log("No celestial bodies provided for celestial ping");
					return;
				}
				DebugLogger.Log($"Processing celestial ping for {celestialBodies.Count} celestial bodies");
				foreach (IPingable celestialBody in celestialBodies)
				{
					try
					{
						string displayName = celestialBody.GetDisplayName();
						PingHighlighter pingHighlighter = FindExistingCelestialHighlight(displayName);
						if ((Object)(object)pingHighlighter != (Object)null)
						{
							DebugLogger.Log("Refreshing existing celestial highlight for " + displayName);
							RefreshCelestialHighlight(pingHighlighter, celestialBody, pingPosition, playerColor, playerName);
							continue;
						}
						PingHighlighter pingHighlighter2 = CreateCelestialHighlight(celestialBody, pingPosition, playerColor, playerName);
						if ((Object)(object)pingHighlighter2 != (Object)null)
						{
							_activeHighlights.Add(pingHighlighter2);
							DebugLogger.Log("Created new celestial ping highlight for " + displayName);
						}
					}
					catch (Exception ex)
					{
						Plugin.Logger.LogWarning((object)("Failed to process celestial body " + celestialBody.GetDisplayName() + ": " + ex.Message));
					}
				}
				_lastPingTime = Time.time;
				DebugLogger.Log("Celestial ping processing completed");
			}
			catch (Exception ex2)
			{
				Plugin.Logger.LogError((object)("Error processing celestial ping: " + ex2.Message));
			}
		}

		private static bool ShouldProcessPing()
		{
			if (PingItemsConfig.DetectionRadius.Value <= 0.01f && PingItemsConfig.LuggageDetectionRadius.Value <= 0.01f)
			{
				return false;
			}
			float num = Time.time - _lastPingTime;
			if (num < PingItemsConfig.PingCooldownDelay.Value)
			{
				if (PingItemsConfig.EnableDebugLogging.Value)
				{
					Plugin.Logger.LogDebug((object)$"Ping cooldown active: {num:F2}s < {PingItemsConfig.PingCooldownDelay.Value:F2}s");
				}
				return false;
			}
			return true;
		}

		private static void EnforcePingLimit()
		{
			int value = PingItemsConfig.MaxActivePings.Value;
			if (value <= 0)
			{
				return;
			}
			while (_activeHighlights.Count >= value)
			{
				PingHighlighter pingHighlighter = _activeHighlights.FirstOrDefault();
				if ((Object)(object)pingHighlighter != (Object)null)
				{
					if (PingItemsConfig.EnableDebugLogging.Value)
					{
						Plugin.Logger.LogDebug((object)$"Removing oldest ping to enforce limit of {value}");
					}
					RemoveHighlight(pingHighlighter);
					continue;
				}
				break;
			}
		}

		public static void RemoveHighlight(PingHighlighter highlighter)
		{
			if ((Object)(object)highlighter == (Object)null)
			{
				return;
			}
			try
			{
				if (_activeHighlights.Remove(highlighter))
				{
					CleanupGroupMapping(highlighter);
					UIManager instance = UIManager.Instance;
					if ((Object)(object)instance != (Object)null)
					{
						highlighter.Cleanup();
						instance.ReleaseHighlighter(highlighter);
					}
					else
					{
						highlighter.Cleanup();
						ObjectPool.ReturnObject(((Component)highlighter).gameObject, ObjectPool.ObjectType.Highlighter);
					}
				}
			}
			catch (Exception ex)
			{
				Plugin.Logger.LogWarning((object)("Failed to remove highlighter: " + ex.Message));
			}
		}

		private static PingHighlighter FindExistingCelestialHighlight(string celestialBodyName)
		{
			foreach (PingHighlighter activeHighlight in _activeHighlights)
			{
				if ((Object)(object)activeHighlight == (Object)null)
				{
					continue;
				}
				try
				{
					FieldInfo field = typeof(PingHighlighter).GetField("_targetPingable", BindingFlags.Instance | BindingFlags.NonPublic);
					if (field != null && field.GetValue(activeHighlight) as IPingable is CelestialBodyPingableAdapter celestialBodyPingableAdapter && celestialBodyPingableAdapter.GetDisplayName().Equals(celestialBodyName, StringComparison.OrdinalIgnoreCase))
					{
						return activeHighlight;
					}
				}
				catch (Exception ex)
				{
					Plugin.Logger.LogWarning((object)("Error checking celestial highlight: " + ex.Message));
				}
			}
			return null;
		}

		private static void RefreshCelestialHighlight(PingHighlighter existingHighlight, IPingable celestialBody, Vector3 pingPosition, Color playerColor, string playerName)
		{
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				string displayName = celestialBody.GetDisplayName();
				DebugLogger.Log("Refreshing celestial highlight for " + displayName + " - removing old and creating new");
				RemoveHighlight(existingHighlight);
				PingHighlighter pingHighlighter = CreateCelestialHighlight(celestialBody, pingPosition, playerColor, playerName);
				if ((Object)(object)pingHighlighter != (Object)null)
				{
					_activeHighlights.Add(pingHighlighter);
					DebugLogger.Log("Successfully refreshed celestial highlight for " + displayName);
				}
			}
			catch (Exception ex)
			{
				Plugin.Logger.LogWarning((object)("Failed to refresh celestial highlight: " + ex.Message));
			}
		}

		private static bool TryRefreshExistingHighlights(List<IPingable> pingables, Vector3 pingPosition)
		{
			//IL_0086: Unknown result type (might be due to invalid IL or missing references)
			//IL_007b: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c5: Unknown result type (might be due to invalid IL or missing references)
			bool result = false;
			HashSet<PingHighlighter> hashSet = new HashSet<PingHighlighter>();
			foreach (IPingable pingable in pingables)
			{
				GameObject gameObject = pingable.GetGameObject();
				if ((Object)(object)gameObject == (Object)null)
				{
					continue;
				}
				PingHighlighter pingHighlighter = _activeHighlights.FirstOrDefault((PingHighlighter h) => (Object)(object)h?.TargetGameObject == (Object)(object)gameObject);
				PingHighlighter value;
				if ((Object)(object)pingHighlighter != (Object)null && !hashSet.Contains(pingHighlighter))
				{
					if (pingHighlighter.IsGroupedPing)
					{
						RefreshGroupHighlight(pingHighlighter, pingables, pingPosition);
					}
					else
					{
						pingHighlighter.Init(pingable, pingPosition);
					}
					hashSet.Add(pingHighlighter);
					result = true;
				}
				else if (_itemToGroupMapping.TryGetValue(gameObject, out value) && (Object)(object)value != (Object)null && !hashSet.Contains(value))
				{
					RefreshGroupHighlight(value, pingables, pingPosition);
					hashSet.Add(value);
					result = true;
				}
			}
			return result;
		}

		private static void CreateIndividualHighlights(List<IPingable> pingables, Vector3 pingPosition, Color playerColor, string playerName)
		{
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			foreach (IPingable pingable in pingables)
			{
				CreateIndividualHighlight(pingable, pingPosition, playerColor, playerName);
			}
		}

		private static void CreateGroupedHighlights(List<IPingable> pingables, Vector3 pingPosition, Color playerColor, string playerName)
		{
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			foreach (List<IPingable> item in GroupPingablesByType(ExpandItemClusters(pingables)))
			{
				CreateGroupHighlight(item, pingPosition, playerColor, playerName);
			}
		}

		private static void CreateIndividualHighlight(IPingable pingable, Vector3 pingPosition, Color playerColor, string playerName)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				PingHighlighter pingHighlighter = CreateNewHighlight(pingable, pingPosition, playerColor, playerName);
				if ((Object)(object)pingHighlighter != (Object)null)
				{
					_activeHighlights.Add(pingHighlighter);
				}
			}
			catch (Exception ex)
			{
				Plugin.Logger.LogWarning((object)("Failed to create individual highlight for " + pingable?.GetDisplayName() + ": " + ex.Message));
			}
		}

		private static void CreateGroupHighlight(List<IPingable> group, Vector3 pingPosition, Color playerColor, string playerName)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				PingHighlighter pingHighlighter = CreateNewGroupedHighlight(group, pingPosition, playerColor, playerName);
				if ((Object)(object)pingHighlighter != (Object)null)
				{
					_activeHighlights.Add(pingHighlighter);
					UpdateGroupMapping(pingHighlighter, group);
				}
			}
			catch (Exception ex)
			{
				Plugin.Logger.LogWarning((object)("Failed to create group highlight: " + ex.Message));
			}
		}

		private static void RefreshGroupHighlight(PingHighlighter groupHighlight, List<IPingable> newPingables, Vector3 pingPosition)
		{
			//IL_00c1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00aa: Unknown result type (might be due to invalid IL or missing references)
			if (groupHighlight == null || !groupHighlight.IsGroupedPing)
			{
				return;
			}
			try
			{
				List<IPingable> currentGroupItems = GetGroupItems(groupHighlight);
				if (PingItemsConfig.EnableItemGrouping.Value)
				{
					List<IPingable> source = ExpandItemClusters(newPingables);
					string groupItemType = currentGroupItems.FirstOrDefault()?.GetDisplayName();
					if (!string.IsNullOrEmpty(groupItemType))
					{
						List<IPingable> source2 = source.Where((IPingable item) => item.GetDisplayName() == groupItemType).ToList();
						List<IPingable> list = currentGroupItems.Concat(source2.Where((IPingable newItem) => !ContainsItem(currentGroupItems, newItem))).ToList();
						groupHighlight.Init(list, pingPosition);
						UpdateGroupMapping(groupHighlight, list);
					}
				}
				else
				{
					groupHighlight.Init(currentGroupItems, pingPosition);
				}
			}
			catch (Exception ex)
			{
				Plugin.Logger.LogWarning((object)("Failed to refresh group highlight: " + ex.Message));
			}
		}

		private static List<IPingable> ExpandItemClusters(List<IPingable> initialItems)
		{
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			if (initialItems.Count == 0)
			{
				return initialItems;
			}
			try
			{
				List<IPingable> allItems = PingableFactory.FindPingablesNearPosition(Vector3.zero, float.MaxValue, float.MaxValue);
				List<IPingable> list = new List<IPingable>();
				HashSet<string> hashSet = new HashSet<string>();
				foreach (IPingable initialItem in initialItems)
				{
					string displayName = initialItem.GetDisplayName();
					if (hashSet.Add(displayName))
					{
						List<IPingable> collection = FindCompleteClusterForType(initialItem, allItems);
						list.AddRange(collection);
					}
				}
				return (from item in list
					group item by item.GetGameObject() into @group
					select @group.First()).ToList();
			}
			catch (Exception ex)
			{
				Plugin.Logger.LogWarning((object)("Cluster expansion failed, using original items: " + ex.Message));
				return initialItems;
			}
		}

		private static List<IPingable> FindCompleteClusterForType(IPingable seedItem, List<IPingable> allItems)
		{
			HashSet<IPingable> processed = new HashSet<IPingable>();
			return BuildItemCluster(seedItem, allItems, processed);
		}

		private static List<IPingable> GetGroupItems(PingHighlighter groupHighlight)
		{
			List<IPingable> list = new List<IPingable>();
			foreach (KeyValuePair<GameObject, PingHighlighter> item in _itemToGroupMapping)
			{
				if ((Object)(object)item.Value == (Object)(object)groupHighlight)
				{
					IPingable pingable = CreatePingableFromGameObject(item.Key);
					if (pingable != null)
					{
						list.Add(pingable);
					}
				}
			}
			return list;
		}

		private static void UpdateGroupMapping(PingHighlighter groupHighlight, List<IPingable> items)
		{
			foreach (KeyValuePair<GameObject, PingHighlighter> item in _itemToGroupMapping.Where((KeyValuePair<GameObject, PingHighlighter> kvp) => (Object)(object)kvp.Value == (Object)(object)groupHighlight).ToList())
			{
				_itemToGroupMapping.Remove(item.Key);
			}
			foreach (IPingable item2 in items)
			{
				GameObject gameObject = item2.GetGameObject();
				if ((Object)(object)gameObject != (Object)null)
				{
					_itemToGroupMapping[gameObject] = groupHighlight;
				}
			}
		}

		private static IPingable CreatePingableFromGameObject(GameObject gameObject)
		{
			if ((Object)(object)gameObject == (Object)null)
			{
				return null;
			}
			Item component = gameObject.GetComponent<Item>();
			if ((Object)(object)component != (Object)null)
			{
				return new ItemPingableAdapter(component);
			}
			Luggage component2 = gameObject.GetComponent<Luggage>();
			if ((Object)(object)component2 != (Object)null)
			{
				return new LuggagePingableAdapter(component2);
			}
			MirageLuggage component3 = gameObject.GetComponent<MirageLuggage>();
			if ((Object)(object)component3 != (Object)null)
			{
				return new MirageLuggagePingableAdapter(component3);
			}
			return null;
		}

		private static bool ContainsItem(List<IPingable> items, IPingable targetItem)
		{
			GameObject targetGameObject = targetItem?.GetGameObject();
			if ((Object)(object)targetGameObject == (Object)null)
			{
				return false;
			}
			return items.Any((IPingable item) => (Object)(object)item?.GetGameObject() == (Object)(object)targetGameObject);
		}

		private static void CleanupGroupMapping(PingHighlighter highlighter)
		{
			foreach (KeyValuePair<GameObject, PingHighlighter> item in _itemToGroupMapping.Where((KeyValuePair<GameObject, PingHighlighter> kvp) => (Object)(object)kvp.Value == (Object)(object)highlighter).ToList())
			{
				_itemToGroupMapping.Remove(item.Key);
			}
		}

		private static PingHighlighter CreateNewHighlight(IPingable pingable, Vector3 pingPoint, Color playerColor, string playerName)
		{
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_0037: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				UIManager instance = UIManager.Instance;
				if ((Object)(object)instance == (Object)null)
				{
					return null;
				}
				PingHighlighter pingHighlighter = instance.RentHighlighter();
				if ((Object)(object)pingHighlighter == (Object)null)
				{
					return null;
				}
				pingHighlighter.PlayerColor = playerColor;
				pingHighlighter.PlayerName = playerName;
				pingHighlighter.Init(pingable, pingPoint);
				return pingHighlighter;
			}
			catch (Exception ex)
			{
				Plugin.Logger.LogWarning((object)("Failed to create highlight: " + ex.Message));
				return null;
			}
		}

		private static PingHighlighter CreateCelestialHighlight(IPingable pingable, Vector3 pingPoint, Color playerColor, string playerName)
		{
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_003a: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				UIManager instance = UIManager.Instance;
				if ((Object)(object)instance == (Object)null)
				{
					return null;
				}
				PingHighlighter pingHighlighter = instance.RentHighlighter();
				if ((Object)(object)pingHighlighter == (Object)null)
				{
					return null;
				}
				pingHighlighter.PlayerColor = playerColor;
				pingHighlighter.PlayerName = playerName;
				pingHighlighter.Init(pingable, pingPoint);
				FieldInfo field = typeof(PingHighlighter).GetField("_distanceFadeProvider", BindingFlags.Instance | BindingFlags.NonPublic);
				if (field != null)
				{
					field.SetValue(pingHighlighter, new CelestialDistanceFadeProvider());
					DebugLogger.Log("Applied celestial distance fade provider for infinite visibility");
				}
				return pingHighlighter;
			}
			catch (Exception ex)
			{
				Plugin.Logger.LogWarning((object)("Failed to create celestial highlight: " + ex.Message));
				return null;
			}
		}

		private static List<List<IPingable>> GroupPingablesByType(List<IPingable> pingables)
		{
			List<List<IPingable>> list = new List<List<IPingable>>();
			HashSet<IPingable> hashSet = new HashSet<IPingable>();
			foreach (IPingable pingable in pingables)
			{
				if (!hashSet.Contains(pingable))
				{
					List<IPingable> list2 = BuildItemCluster(pingable, pingables, hashSet);
					if (list2.Count > 0)
					{
						list.Add(list2);
					}
				}
			}
			return list;
		}

		private static List<IPingable> BuildItemCluster(IPingable startItem, List<IPingable> allItems, HashSet<IPingable> processed)
		{
			List<IPingable> list = new List<IPingable>();
			Queue<IPingable> queue = new Queue<IPingable>();
			string displayName = startItem.GetDisplayName();
			float value = PingItemsConfig.GroupingRadius.Value;
			int value2 = PingItemsConfig.MaxGroupSize.Value;
			queue.Enqueue(startItem);
			while (queue.Count > 0 && list.Count < value2)
			{
				IPingable pingable = queue.Dequeue();
				if (processed.Contains(pingable))
				{
					continue;
				}
				if (list.Count >= value2)
				{
					if (PingItemsConfig.EnableDebugLogging.Value)
					{
						Plugin.Logger.LogDebug((object)$"Stopping cluster expansion: reached max group size of {value2}");
					}
					break;
				}
				processed.Add(pingable);
				list.Add(pingable);
				foreach (IPingable item in from n in FindItemNeighbors(pingable, allItems, displayName, value, processed)
					where !processed.Contains(n)
					select n)
				{
					if (list.Count + queue.Count < value2)
					{
						queue.Enqueue(item);
					}
				}
			}
			if (PingItemsConfig.EnableDebugLogging.Value && list.Count > 1)
			{
				Plugin.Logger.LogDebug((object)$"Built cluster of {list.Count} {displayName} items (max: {value2})");
			}
			return list;
		}

		private static List<IPingable> FindItemNeighbors(IPingable centerItem, List<IPingable> allItems, string itemType, float radius, HashSet<IPingable> processed)
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_003a: Unknown result type (might be due to invalid IL or missing references)
			//IL_003c: Unknown result type (might be due to invalid IL or missing references)
			List<IPingable> list = new List<IPingable>();
			Vector3 center = centerItem.GetCenter();
			foreach (IPingable allItem in allItems)
			{
				if (!processed.Contains(allItem) && allItem != centerItem && !(allItem.GetDisplayName() != itemType) && Vector3.Distance(center, allItem.GetCenter()) <= radius)
				{
					list.Add(allItem);
				}
			}
			return list;
		}

		private static PingHighlighter CreateNewGroupedHighlight(List<IPingable> group, Vector3 pingPoint, Color playerColor, string playerName)
		{
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_0037: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				UIManager instance = UIManager.Instance;
				if ((Object)(object)instance == (Object)null)
				{
					return null;
				}
				PingHighlighter pingHighlighter = instance.RentHighlighter();
				if ((Object)(object)pingHighlighter == (Object)null)
				{
					return null;
				}
				pingHighlighter.PlayerColor = playerColor;
				pingHighlighter.PlayerName = playerName;
				pingHighlighter.Init(group, pingPoint);
				return pingHighlighter;
			}
			catch (Exception ex)
			{
				Plugin.Logger.LogWarning((object)("Failed to create grouped highlight: " + ex.Message));
				return null;
			}
		}
	}
}
namespace PingItems.Pooling
{
	public static class ObjectPool
	{
		public enum ObjectType
		{
			Generic,
			Reticle,
			Highlighter,
			Label,
			EdgeText
		}

		private static readonly Dictionary<ObjectType, Queue<GameObject>> _availableObjects = new Dictionary<ObjectType, Queue<GameObject>>();

		private static readonly Dictionary<ObjectType, HashSet<GameObject>> _activeObjects = new Dictionary<ObjectType, HashSet<GameObject>>();

		private const int MAX_POOL_SIZE_PER_TYPE = 30;

		private const int INITIAL_POOL_SIZE_PER_TYPE = 5;

		private static bool _initialized = false;

		public static void Initialize()
		{
			if (_initialized)
			{
				return;
			}
			foreach (ObjectType value in Enum.GetValues(typeof(ObjectType)))
			{
				_availableObjects[value] = new Queue<GameObject>();
				_activeObjects[value] = new HashSet<GameObject>();
				for (int i = 0; i < 5; i++)
				{
					GameObject val = CreatePooledObject(value);
					val.SetActive(false);
					_availableObjects[value].Enqueue(val);
				}
			}
			_initialized = true;
			Plugin.Logger.LogInfo((object)$"ObjectPool initialized with {5} objects per type");
		}

		public static GameObject GetObject(ObjectType objectType = ObjectType.Generic)
		{
			EnsureInitialized();
			GameObject val;
			if (_availableObjects[objectType].Count > 0)
			{
				val = _availableObjects[objectType].Dequeue();
				ResetObjectState(val, objectType);
			}
			else
			{
				val = CreatePooledObject(objectType);
			}
			if ((Object)(object)val != (Object)null)
			{
				_activeObjects[objectType].Add(val);
				val.SetActive(true);
			}
			return val;
		}

		public static void ReturnObject(GameObject obj, ObjectType objectType = ObjectType.Generic)
		{
			if (!((Object)(object)obj == (Object)null))
			{
				EnsureInitialized();
				_activeObjects[objectType].Remove(obj);
				obj.SetActive(false);
				if (_availableObjects[objectType].Count < 30)
				{
					_availableObjects[objectType].Enqueue(obj);
				}
				else
				{
					Object.Destroy((Object)(object)obj);
				}
			}
		}

		public static void Cleanup()
		{
			foreach (ObjectType item in _availableObjects.Keys.ToList())
			{
				while (_availableObjects[item].Count > 0)
				{
					GameObject val = _availableObjects[item].Dequeue();
					if ((Object)(object)val != (Object)null)
					{
						Object.Destroy((Object)(object)val);
					}
				}
				_activeObjects[item].Where((GameObject obj) => (Object)(object)obj != (Object)null).ToList().ForEach((Action<GameObject>)Object.Destroy);
				_activeObjects[item].Clear();
			}
			_availableObjects.Clear();
			_activeObjects.Clear();
			_initialized = false;
			Plugin.Logger.LogInfo((object)"ObjectPool cleaned up");
		}

		public static string GetPoolStats()
		{
			StringBuilder stringBuilder = new StringBuilder();
			foreach (ObjectType key in _availableObjects.Keys)
			{
				int count = _availableObjects[key].Count;
				int count2 = _activeObjects[key].Count;
				stringBuilder.AppendLine($"{key}: Available={count}, Active={count2}");
			}
			return stringBuilder.ToString();
		}

		private static void EnsureInitialized()
		{
			if (!_initialized)
			{
				Initialize();
			}
		}

		private static GameObject CreatePooledObject(ObjectType objectType)
		{
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: Expected O, but got Unknown
			//IL_003a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0040: Expected O, but got Unknown
			//IL_004e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0054: Expected O, but got Unknown
			//IL_0062: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: Expected O, but got Unknown
			//IL_0076: Unknown result type (might be due to invalid IL or missing references)
			//IL_007c: Expected O, but got Unknown
			GameObject val;
			switch (objectType)
			{
			case ObjectType.Reticle:
				val = new GameObject("PooledReticle");
				val.AddComponent<RectTransform>();
				val.AddComponent<Image>();
				break;
			case ObjectType.Highlighter:
				val = new GameObject("PooledHighlighter");
				val.AddComponent<PingHighlighter>();
				break;
			case ObjectType.Label:
				val = new GameObject("PooledLabel");
				val.AddComponent<TextMeshProUGUI>();
				break;
			case ObjectType.EdgeText:
				val = new GameObject("PooledEdgeText");
				val.AddComponent<EdgeDistanceText>();
				break;
			default:
				val = new GameObject("PooledObject");
				val.AddComponent<RectTransform>();
				break;
			}
			Object.DontDestroyOnLoad((Object)(object)val);
			return val;
		}

		private static void ResetObjectState(GameObject obj, ObjectType objectType)
		{
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: 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_0056: Unknown result type (might be due to invalid IL or missing references)
			//IL_0061: Unknown result type (might be due to invalid IL or missing references)
			//IL_006c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0092: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c0: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)obj == (Object)null)
			{
				return;
			}
			obj.transform.localScale = Vector3.one;
			obj.transform.localPosition = Vector3.zero;
			obj.transform.localRotation = Quaternion.identity;
			RectTransform component = obj.GetComponent<RectTransform>();
			if ((Object)(object)component != (Object)null)
			{
				component.anchoredPosition = Vector2.zero;
				component.sizeDelta = Vector2.zero;
				component.offsetMin = Vector2.zero;
				component.offsetMax = Vector2.zero;
			}
			switch (objectType)
			{
			case ObjectType.Reticle:
			{
				Image component3 = obj.GetComponent<Image>();
				if ((Object)(object)component3 != (Object)null)
				{
					((Graphic)component3).color = Color.white;
					component3.sprite = null;
				}
				break;
			}
			case ObjectType.Label:
			case ObjectType.EdgeText:
			{
				TextMeshProUGUI component2 = obj.GetComponent<TextMeshProUGUI>();
				if ((Object)(object)component2 != (Object)null)
				{
					((TMP_Text)component2).text = "";
					((Graphic)component2).color = Color.white;
					((TMP_Text)component2).fontSize = 12f;
				}
				break;
			}
			}
		}
	}
}
namespace PingItems.Patches
{
	[HarmonyPatch(typeof(GUIManager), "InitReticleList")]
	public static class GUIManagerPatch
	{
		private static readonly ReticleResolver _reticleResolver = new ReticleResolver();

		[HarmonyPostfix]
		public static void Postfix(GUIManager __instance)
		{
			try
			{
				CaptureReticle(__instance);
				CaptureFont(__instance);
				ConfigureCanvasFromHUD();
			}
			catch (Exception ex)
			{
				Plugin.Logger.LogError((object)("❌ GUIManager patch failed: " + ex.Message));
			}
		}

		private static void CaptureReticle(GUIManager guiManager)
		{
			try
			{
				GameObject configuredReticle = _reticleResolver.GetConfiguredReticle(guiManager);
				if ((Object)(object)configuredReticle != (Object)null)
				{
					Plugin.Logger.LogInfo((object)$"\ud83c\udfaf Captured reticle: {((Object)configuredReticle).name} ({PingItemsConfig.ReticleType.Value})");
					UIManager.Instance?.SetReticlePrefab(configuredReticle);
					Plugin.PopulateAllPools();
				}
				else
				{
					Plugin.Logger.LogWarning((object)"⚠\ufe0f No reticle captured from GUIManager");
				}
			}
			catch (Exception ex)
			{
				Plugin.Logger.LogWarning((object)("⚠\ufe0f Failed to capture reticle: " + ex.Message));
			}
		}

		private static void CaptureFont(GUIManager guiManager)
		{
			try
			{
				TMP_FontAsset val = (from textComponent in ((Component)guiManager).GetComponentsInChildren<TMP_Text>(true)
					select textComponent.font).FirstOrDefault((Func<TMP_FontAsset, bool>)((TMP_FontAsset f) => (Object)(object)f != (Object)null));
				if ((Object)(object)val != (Object)null)
				{
					Plugin.Logger.LogInfo((object)("\ud83d\udd24 Captured font: " + ((Object)val).name));
					UIManager.Instance?.SetGameFont(val);
				}
			}
			catch (Exception ex)
			{
				Plugin.Logger.LogError((object)("❌ Failed to capture font: " + ex.Message));
			}
		}

		private static void ConfigureCanvasFromHUD()
		{
			try
			{
				UIManager instance = UIManager.Instance;
				if ((Object)(object)instance == (Object)null)
				{
					Plugin.Logger.LogWarning((object)"⚠\ufe0f UIManager not available for Canvas_HUD configuration");
					return;
				}
				Canvas val = FindCanvasHUD();
				if ((Object)(object)val != (Object)null)
				{
					instance.ConfigureCanvasFromHUD(val);
				}
				else
				{
					Plugin.Logger.LogInfo((object)"ℹ\ufe0f Canvas_HUD not found - using fallback configuration");
				}
			}
			catch (Exception ex)
			{
				Plugin.Logger.LogError((object)("❌ Failed to configure canvas from Canvas_HUD: " + ex.Message));
			}
		}

		private static Canvas FindCanvasHUD()
		{
			GameObject val = GameObject.Find("Canvas_HUD");
			if ((Object)(object)val != (Object)null)
			{
				Canvas component = val.GetComponent<Canvas>();
				if ((Object)(object)component != (Object)null)
				{
					Plugin.Logger.LogInfo((object)$"\ud83c\udfaf Found Canvas_HUD: {((Object)val).name} (sorting: {component.sortingOrder})");
					return component;
				}
			}
			return null;
		}
	}
	[HarmonyPatch(typeof(PointPinger))]
	public static class PointPingerPatch
	{
		[HarmonyPatch("Update")]
		[HarmonyPrefix]
		private static bool Prefix_Update(PointPinger __instance)
		{
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: Expected O, but got Unknown
			//IL_00cd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00dd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e6: Unknown result type (might be due to invalid IL or missing references)
			//IL_0110: Unknown result type (might be due to invalid IL or missing references)
			//IL_0111: Unknown result type (might be due to invalid IL or missing references)
			//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_0122: Unknown result type (might be due to invalid IL or missing references)
			//IL_0124: Unknown result type (might be due to invalid IL or missing references)
			//IL_0126: Unknown result type (might be due to invalid IL or missing references)
			//IL_012b: Unknown result type (might be due to invalid IL or missing references)
			//IL_013c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0146: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				PhotonView val = (PhotonView)typeof(PointPinger).GetField("photonView", BindingFlags.Instance | BindingFlags.NonPublic).GetValue(__instance);
				if (!val.IsMine)
				{
					return true;
				}
				if (!PingItemsConfig.EnableEnhancedPingSystem.Value)
				{
					return true;
				}
				FieldInfo field = typeof(PointPinger).GetField("coolDownLeft", BindingFlags.Instance | BindingFlags.NonPublic);
				float num = (float)field.GetValue(__instance);
				num -= Time.deltaTime;
				field.SetValue(__instance, num);
				if (num > 0f)
				{
					return false;
				}
				if (!__instance.character.input.pingWasPressed)
				{
					return false;
				}
				if (__instance.character.data.dead)
				{
					return false;
				}
				Vector3 position = ((Component)Camera.main).transform.position;
				Vector3 forward = ((Component)Camera.main).transform.forward;
				if (CelestialBodyDetectionService.DetectCelestialBodies(forward, position).Count > 0)
				{
					DebugLogger.Log("Detected celestial body ping - handling without raycast");
					field.SetValue(__instance, __instance.coolDown);
					Vector3 val2 = position + forward * 1000f;
					Vector3 val3 = -forward;
					val.RPC("ReceivePoint_Rpc", (RpcTarget)0, new object[2] { val2, val3 });
					return false;
				}
				return true;
			}
			catch (Exception arg)
			{
				Plugin.Logger.LogError((object)$"Error in PointPinger Update prefix: {arg}");
				return true;
			}
		}

		[HarmonyPatch("Update")]
		[HarmonyTranspiler]
		private static IEnumerable<CodeInstruction> UpdateTranspiler(IEnumerable<CodeInstruction> instructions)
		{
			//IL_0062: Unknown result type (might be due to invalid IL or missing references)
			//IL_006c: Expected O, but got Unknown
			List<CodeInstruction> list = new List<CodeInstruction>(instructions);
			if (!PingItemsConfig.EnableEnhancedPingSystem.Value)
			{
				Plugin.Logger.LogInfo((object)"\ud83d\udd04 Enhanced ping system disabled - skipping raycast patch");
				return list;
			}
			for (int i = 0; i < list.Count - 1; i++)
			{
				if (list[i].opcode == OpCodes.Ldc_I4_1 && IsMethodCallWithName(list[i + 1], "ToLayerMask"))
				{
					list[i] = new CodeInstruction(OpCodes.Ldc_I4, (object)5);
					Plugin.Logger.LogInfo((object)"✅ Enhanced ping system enabled - patched raycast to use AllPhysicalExceptCharacter layers");
					break;
				}
			}
			return list;
		}

		private static bool IsMethodCallWithName(CodeInstruction instruction, string methodName)
		{
			if (instruction.opcode == OpCodes.Call && instruction.operand is MethodInfo methodInfo)
			{
				return methodInfo.Name == methodName;
			}
			return false;
		}

		[HarmonyPatch("ReceivePoint_Rpc")]
		[HarmonyPostfix]
		private static void Postfix_ReceivePoint_Rpc(PointPinger __instance, Vector3 point, Vector3 hitNormal)
		{
			//IL_002a: 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_0040: Unknown result type (might be due to invalid IL or missing references)
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			//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_006b: Unknown result type (might be due to invalid IL or missing references)
			//IL_006f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0075: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c8: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				if (!PingItemsConfig.EnableEnhancedPingSystem.Value)
				{
					Plugin.Logger.LogDebug((object)"Enhanced ping system disabled - skipping item detection");
					return;
				}
				Plugin.Logger.LogDebug((object)$"ReceivePoint_Rpc postfix called with point: {point}");
				Color pingingPlayerColor = GetPingingPlayerColor(__instance);
				string pingingPlayerName = GetPingingPlayerName(__instance);
				Character val = __instance?.character;
				DebugLogger.Log("Checking for celestial body ping...");
				Vector3 val2 = point - val.Center;
				List<IPingable> list = CelestialBodyDetectionService.DetectCelestialBodies(((Vector3)(ref val2)).normalized, val.Center);
				if (list.Count > 0)
				{
					DebugLogger.Log("Celestial bodies detected: " + string.Join(", ", list.Select((IPingable cb) => cb.GetDisplayName())));
					PingService.ProcessCelestialPing(point, pingingPlayerColor, pingingPlayerName, val, list);
				}
				else
				{
					PingService.ProcessPing(point, pingingPlayerColor, pingingPlayerName, val);
				}
			}
			catch (Exception arg)
			{
				Plugin.Logger.LogError((object)$"Error in PointPinger ReceivePoint_Rpc postfix: {arg}");
			}
		}

		private static Color GetPingingPlayerColor(PointPinger pointPinger)
		{
			//IL_0063: Unknown result type (might be due to invalid IL or missing references)
			//IL_003c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			//IL_0069: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				if ((Object)(object)pointPinger?.character?.refs?.customization != (Object)null)
				{
					return pointPinger.character.refs.customization.PlayerColor;
				}
			}
			catch (Exception ex)
			{
				Plugin.Logger.LogWarning((object)("Failed to get pinging player color: " + ex.Message));
			}
			return Color.cyan;
		}

		private static string GetPingingPlayerName(PointPinger pointPinger)
		{
			try
			{
				if (pointPinger != null)
				{
					Character character = pointPinger.character;
					if (((character != null) ? character.characterName : null) != null)
					{
						return pointPinger.character.characterName;
					}
				}
			}
			catch (Exception ex)
			{
				Plugin.Logger.LogWarning((object)("Failed to get pinging player name: " + ex.Message));
			}
			return "Unknown";
		}
	}
}
namespace PingItems.Factories
{
	public static class OptimizedPingableFactory
	{
		private static SpatialGrid _spatialGrid;

		private static float _lastGridRebuildTime = 0f;

		private static readonly float GRID_REBUILD_INTERVAL = 5f;

		private static string _lastSceneName = "";

		private static int _lastGameSegment = -1;

		public static void Initialize()
		{
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			_spatialGrid = new SpatialGrid(PingItemsConfig.SpatialGridCellSize.Value);
			Scene activeScene = SceneManager.GetActiveScene();
			_lastSceneName = ((Scene)(ref activeScene)).name;
			_lastGameSegment = GetCurrentGameSegment();
			RebuildSpatialGrid();
		}

		public static List<IPingable> FindPingablesForPing(Vector3 pingPosition, Character pingingCharacter, float itemRadius, float luggageRadius)
		{
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			if (!PingItemsConfig.EnableSpatialOptimization.Value)
			{
				return PingableFactory.FindPingablesForPing(pingPosition, pingingCharacter, itemRadius, luggageRadius);
			}
			try
			{
				return FindPingablesOptimized(pingPosition, pingingCharacter, itemRadius, luggageRadius);
			}
			catch (Exception ex)
			{
				Plugin.Logger.LogWarning((object)("Spatial optimization failed, using standard method: " + ex.Message));
				return PingableFactory.FindPingablesForPing(pingPosition, pingingCharacter, itemRadius, luggageRadius);
			}
		}

		private static List<IPingable> FindPingablesOptimized(Vector3 pingPosition, Character pingingCharacter, float itemRadius, float luggageRadius)
		{
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			if (ShouldRebuildGrid())
			{
				RebuildSpatialGrid();
			}
			if (_spatialGrid == null)
			{
				DebugLogger.Log("Spatial grid is null, falling back to standard method");
				return PingableFactory.FindPingablesForPing(pingPosition, pingingCharacter, itemRadius, luggageRadius);
			}
			return ProcessCandidates(pingPosition, itemRadius, luggageRadius);
		}

		private static bool ShouldRebuildGrid()
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			Scene activeScene = SceneManager.GetActiveScene();
			string name = ((Scene)(ref activeScene)).name;
			if (name != _lastSceneName)
			{
				DebugLogger.Log("Scene changed from '" + _lastSceneName + "' to '" + name + "', forcing grid rebuild");
				_lastSceneName = name;
				return true;
			}
			int currentGameSegment = GetCurrentGameSegment();
			if (currentGameSegment != -1 && currentGameSegment != _lastGameSegment)
			{
				DebugLogger.Log($"Game segment changed from {_lastGameSegment} to {currentGameSegment}, forcing grid rebuild");
				_lastGameSegment = currentGameSegment;
				return true;
			}
			return Time.time - _lastGridRebuildTime > GRID_REBUILD_INTERVAL;
		}

		private static List<IPingable> ProcessCandidates(Vector3 pingPosition, float itemRadius, float luggageRadius)
		{
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0064: Unknown result type (might be due to invalid IL or missing references)
			//IL_0069: Unknown result type (might be due to invalid IL or missing references)
			float radius = Mathf.Max(itemRadius, luggageRadius);
			List<IPingable> list = _spatialGrid.FindNearbyObjects(pingPosition, radius);
			List<IPingable> list2 = new List<IPingable>();
			int num = 0;
			int value = PingItemsConfig.MaxDistanceChecksPerFrame.Value;
			foreach (IPingable item in list)
			{
				if (num >= value)
				{
					DebugLogger.Log($"Hit distance check limit of {value}, stopping early");
					break;
				}
				if (IsValidCandidate(item))
				{
					float num2 = Vector3.Distance(item.GetCenter(), pingPosition);
					num++;
					float applicableRadius = GetApplicableRadius(item, itemRadius, luggageRadius);
					if (num2 <= applicableRadius)
					{
						list2.Add(item);
					}
				}
			}
			LogPerformanceStats(list.Count, num, list2.Count);
			return list2;
		}

		private static bool IsValidCandidate(IPingable candidate)
		{
			try
			{
				return candidate != null && candidate.CanBePinged() && (Object)(object)candidate.GetGameObject() != (Object)null;
			}
			catch
			{
				return false;
			}
		}

		private static float GetApplicableRadius(IPingable pingable, float itemRadius, float luggageRadius)
		{
			GameObject gameObject = pingable.GetGameObject();
			if ((Object)(object)gameObject == (Object)null)
			{
				return itemRadius;
			}
			if (!((Object)(object)gameObject.GetComponent<Luggage>() != (Object)null) && !((Object)(object)gameObject.GetComponent<MirageLuggage>() != (Object)null))
			{
				return itemRadius;
			}
			return luggageRadius;
		}

		private static void RebuildSpatialGrid()
		{
			DebugLogger.Log("Rebuilding spatial grid...");
			float realtimeSinceStartup = Time.realtimeSinceStartup;
			try
			{
				_spatialGrid?.Clear();
				if (_spatialGrid == null)
				{
					_spatialGrid = new SpatialGrid(PingItemsConfig.SpatialGridCellSize.Value);
				}
				AddObjectsToGrid(SmartObjectManager.GetItems(), (Item item) => new ItemPingableAdapter(item), "items");
				AddObjectsToGrid(Luggage.ALL_LUGGAGE, (Luggage luggage) => new LuggagePingableAdapter(luggage), "luggage");
				AddObjectsToGrid(SmartObjectManager.GetMirageLuggages(), (MirageLuggage mirage) => new MirageLuggagePingableAdapter(mirage), "mirage luggage");
				AddObjectsToGrid(SmartObjectManager.GetSlipperyJellyfish(), (SlipperyJellyfish jellyfish) => new SlipperyJellyfishPingableAdapter((Component)(object)jellyfish), "jellyfish");
				AddObjectsToGrid(SmartObjectManager.GetSporeShrooms(), (GameObject shroom) => new SporeShroomPingableAdapter(shroom), "shrooms");
				AddObjectsToGrid(SmartObjectManager.GetCapybaras(), (Capybara capybara) => new CapybaraPingableAdapter(capybara), "capybaras");
				_lastGridRebuildTime = Time.time;
				float num = (Time.realtimeSinceStartup - realtimeSinceStartup) * 1000f;
				var (num2, num3, num4) = _spatialGrid.GetStats();
				DebugLogger.Log($"Spatial grid rebuilt in {num:F1}ms: {num3} objects in {num2} cells ({num4:F1} avg per cell)");
			}
			catch (Exception ex)
			{
				Plugin.Logger.LogWarning((object)("Failed to rebuild spatial grid: " + ex.Message));
				_spatialGrid = new SpatialGrid(PingItemsConfig.SpatialGridCellSize.Value);
				_lastGridRebuildTime = Time.time;
			}
		}

		private static void AddObjectsToGrid<T>(IEnumerable<T> objects, Func<T, IPingable> createPingable, string typeName) where T : class
		{
			if (objects == null)
			{
				return;
			}
			int num = 0;
			foreach (T @object in objects)
			{
				try
				{
					if (@object == null)
					{
						continue;
					}
					object obj = ((@object is GameObject) ? @object : null);
					if (obj == null)
					{
						T obj2 = ((@object is Component) ? @object : null);
						obj = ((obj2 != null) ? ((Component)obj2).gameObject : null);
					}
					if (!((Object)obj == (Object)null))
					{
						IPingable pingable = createPingable(@object);
						if (pingable != null && pingable.CanBePinged() && (Object)(object)pingable.GetGameObject() != (Object)null)
						{
							_spatialGrid.AddObject(pingable);
							num++;
						}
					}
				}
				catch (Exception ex)
				{
					DebugLogger.Log("Skipped invalid " + typeName + " during grid rebuild: " + ex.Message);
				}
			}
			DebugLogger.Log($"Added {num} {typeName} to spatial grid");
		}

		private static int GetCurrentGameSegment()
		{
			try
			{
				Type? type = Type.GetType("MapHandler");
				object obj = (type?.GetProperty("Instance", BindingFlags.Static | BindingFlags.Public))?.GetValue(null);
				object obj2 = (type?.GetMethod("GetCurrentSegment"))?.Invoke(obj, null);
				return (obj2 != null) ? ((int)obj2) : (-1);
			}
			catch (Exception ex)
			{
				DebugLogger.Log("Could not get current game segment: " + ex.Message);
				return -1;
			}
		}

		private static void LogPerformanceStats(int candidatesCount, int distanceChecks, int resultCount)
		{
			if (DebugLogger.IsDebugEnabled)
			{
				var (num, num2, num3) = _spatialGrid.GetStats();
				DebugLogger.Log($"Spatial optimization: {candidatesCount} candidates from {num} cells, {distanceChecks} distance checks, {resultCount} valid");
				DebugLogger.Log($"Grid stats: {num2} objects, {num3:F1} avg per cell");
			}
		}

		public static void ForceRebuild()
		{
			_lastGridRebuildTime = 0f;
		}

		public static (int totalCells, int totalObjects, float avgObjectsPerCell) GetPerformanceStats()
		{
			return _spatialGrid?.GetStats() ?? (0, 0, 0f);
		}
	}
	public static class PingableFactory
	{
		public static List<IPingable> FindPingablesForPing(Vector3 pingPosition, Character pingingCharacter, float itemRadius, float luggageRadius)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			return FindPingablesNearPosition(pingPosition, itemRadius, luggageRadius);
		}

		public static List<IPingable> FindPingablesNearPosition(Vector3 position, float itemRadius, float luggageRadius)
		{
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			List<IPingable> list = new List<IPingable>();
			float radiusSquared = itemRadius * itemRadius;
			float radiusSquared2 = luggageRadius * luggageRadius;
			AddPingableItems(list, position, radiusSquared);
			AddPingableLuggage(list, position, radiusSquared2);
			AddPingableMirageLuggage(list, position, radiusSquared2);
			AddPingableSlipperyJellyfish(list, position, radiusSquared);
			AddPingableSporeShrooms(list, position, radiusSquared);
			return list;
		}

		private static void AddPingableItems(List<IPingable> pingables, Vector3 position, float radiusSquared)
		{
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			List<Item> items = SmartObjectManager.GetItems();
			for (int i = 0; i < items.Count; i++)
			{
				Item val = items[i];
				if ((Object)(object)val != (Object)null && IsObjectNearPositionSquared(((Component)val).gameObject, position, radiusSquared))
				{
					ItemPingableAdapter itemPingableAdapter = new ItemPingableAdapter(val);
					if (itemPingableAdapter.CanBePinged())
					{
						pingables.Add(itemPingableAdapter);
					}
				}
			}
		}

		private static void AddPingableLuggage(List<IPingable> pingables, Vector3 position, float radiusSquared)
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			foreach (Luggage item in Luggage.ALL_LUGGAGE.Where((Luggage luggage) => (Object)(object)luggage != (Object)null && IsObjectNearPositionSquared(((Component)luggage).gameObject, position, radiusSquared)))
			{
				LuggagePingableAdapter luggagePingableAdapter = new LuggagePingableAdapter(item);
				if (luggagePingableAdapter.CanBePinged())
				{
					pingables.Add(luggagePingableAdapter);
				}
			}
		}

		private static void AddPingableMirageLuggage(List<IPingable> pingables, Vector3 position, float radiusSquared)
		{
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			List<MirageLuggage> mirageLuggages = SmartObjectManager.GetMirageLuggages();
			for (int i = 0; i < mirageLuggages.Count; i++)
			{
				MirageLuggage val = mirageLuggages[i];
				if ((Object)(object)val != (Object)null && IsObjectNearPositionSquared(((Component)val).gameObject, position, radiusSquared))
				{
					MirageLuggagePingableAdapter mirageLuggagePingableAdapter = new MirageLuggagePingableAdapter(val);
					if (mirageLuggagePingableAdapter.CanBePinged())
					{
						pingables.Add(mirageLuggagePingableAdapter);
					}
				}
			}
		}

		private static void AddPingableSlipperyJellyfish(List<IPingable> pingables, Vector3 position, float radiusSquared)
		{
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			List<SlipperyJellyfish> slipperyJellyfish = SmartObjectManager.GetSlipperyJellyfish();
			for (int i = 0; i < slipperyJellyfish.Count; i++)
			{
				SlipperyJellyfish val = slipperyJellyfish[i];
				if ((Object)(object)val != (Object)null && IsObjectNearPositionSquared(((Component)val).gameObject, position, radiusSquared))
				{
					SlipperyJellyfishPingableAdapter slipperyJellyfishPingableAdapter = new SlipperyJellyfishPingableAdapter((Component)(object)val);
					if (slipperyJellyfishPingableAdapter.CanBePinged())
					{
						pingables.Add(slipperyJellyfishPingableAdapter);
					}
				}
			}
		}

		private static void AddPingableSporeShrooms(List<IPingable> pingables, Vector3 position, float radiusSquared)
		{
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			List<GameObject> sporeShrooms = SmartObjectManager.GetSporeShrooms();
			for (int i = 0; i < sporeShrooms.Count; i++)
			{
				GameObject val = sporeShrooms[i];
				if ((Object)(object)val != (Object)null && IsObjectNearPositionSquared(val.gameObject, position, radiusSquared))
				{
					SporeShroomPingableAdapter sporeShroomPingableAdapter = new SporeShroomPingableAdapter(val);
					if (sporeShroomPingableAdapter.CanBePinged())
					{
						pingables.Add(sporeShroomPingableAdapter);
					}
				}
			}
		}

		private static bool IsObjectNearPositionSquared(GameObject gameObject, Vector3 position, float radiusSquared)
		{
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)gameObject == (Object)null || !gameObject.activeInHierarchy)
			{
				return false;
			}
			Vector3 val = gameObject.transform.position - position;
			return ((Vector3)(ref val)).sqrMagnitude <= radiusSquared;
		}
	}
	public static class SimplifiedPingableFactory
	{
		public delegate IEnumerable<object> ObjectSourceDelegate();

		private static readonly List<ObjectSourceDelegate> _objectSources = new List<ObjectSourceDelegate>();

		public static void Initialize()
		{
			PingTypeRegistry.Initialize();
			RegisterObjectSource(() => SmartObjectManager.GetItems().Cast<object>());
			RegisterObjectSource(() => Luggage.ALL_LUGGAGE.Cast<object>());
			RegisterObjectSource(() => SmartObjectManager.GetMirageLuggages().Cast<object>());
			RegisterObjectSource(() => SmartObjectManager.GetSlipperyJellyfish().Cast<object>());
			RegisterObjectSource(() => SmartObjectManager.GetSporeShrooms().Cast<object>());
			RegisterObjectSource(() => SmartObjectManager.GetCapybaras().Cast<object>());
		}

		public static void RegisterObjectSource(ObjectSourceDelegate sourceDelegate)
		{
			_objectSources.Add(sourceDelegate);
		}

		public static List<IPingable> FindPingablesForPing(Vector3 pingPosition, Character pingingCharacter, float itemRadius, float luggageRadius)
		{
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			List<IPingable> list = new List<IPingable>();
			try
			{
				foreach (ObjectSourceDelegate objectSource in _objectSources)
				{
					ProcessObjectSource(objectSource, pingPosition, itemRadius, luggageRadius, list);
				}
				DebugLogger.Log($"SimplifiedPingableFactory found {list.Count} pingable objects");
				return list;
			}
			catch (Exception ex)
			{
				Plugin.Logger.LogError((object)("Error in SimplifiedPingableFactory: " + ex.Message));
				return new List<IPingable>();
			}
		}

		private static void ProcessObjectSource(ObjectSourceDelegate sourceDelegate, Vector3 pingPosition, float itemRadius, float luggageRadius, List<IPingable> result)
		{
			//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)
			try
			{
				IEnumerable<object> enumerable = sourceDelegate();
				if (enumerable == null)
				{
					return;
				}
				foreach (object item in enumerable)
				{
					IPingable pingable = CreatePingableFromObject(item);
					if (pingable != null && pingable.CanBePinged())
					{
						float num = Vector3.Distance(pingable.GetCenter(), pingPosition);
						float applicableRadius = GetApplicableRadius(pingable, itemRadius, luggageRadius);
						if (num <= applicableRadius)
						{
							result.Add(pingable);
						}
					}
				}
			}
			catch (Exception ex)
			{
				DebugLogger.Log("Error processing object source: " + ex.Message);
			}
		}

		private static IPingable CreatePingableFromObject(object obj)
		{
			if (obj == null)
			{
				return null;
			}
			Component val = (Component)((obj is Component) ? obj : null);
			if (val != null)
			{
				IPingable pingable = PingTypeRegistry.TryCreateAdapter(val);
				if (pingable != null)
				{
					return pingable;
				}
			}
			return PingTypeRegistry.TryCreateAdapter(obj);
		}

		private static float GetApplicableRadius(IPingable pingable, float itemRadius, float luggageRadius)
		{
			GameObject gameObject = pingable.GetGameObject();
			if ((Object)(object)gameObject == (Object)null)
			{
				return itemRadius;
			}
			if (!((Object)(object)gameObject.GetComponent<Luggage>() != (Object)null) && !((Object)(object)gameObject.GetComponent<MirageLuggage>() != (Object)null))
			{
				return itemRadius;
			}
			return luggageRadius;
		}
	}
}
namespace PingItems.Core
{
	public abstract class BasePingableAdapter<T> : IPingable where T : Component
	{
		protected readonly T _component;

		protected readonly GameObject _gameObject;

		protected BasePingableAdapter(T component)
		{
			_component = component ?? throw new ArgumentNullException("component");
			_gameObject = ((Component)component).gameObject;
		}

		public virtual string GetDisplayName()
		{
			try
			{
				return CustomLocalization.GetLocalizedName(GetLocalizationKey());
			}
			catch (Exception ex)
			{
				Plugin.Logger.LogWarning((object)("Failed to get localized name for " + GetLocalizationKey() + ": " + ex.Message));
				return GetFallbackName();
			}
		}

		public GameObject GetGameObject()
		{
			return _gameObject;
		}

		public virtual Vector3 GetCenter()
		{
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			return _gameObject.transform.position;
		}

		public virtual bool CanBePinged()
		{
			return ValidationUtility.IsActiveAndValid((Component)(object)_component);
		}

		protected abstract string GetLocalizationKey();

		protected abstract string GetFallbackName();
	}
	public class EdgeDistanceText : MonoBehaviour
	{
		private TextMeshProUGUI _distanceText;

		private RectTransform _textRectTransform;

		private CanvasGroup _canvasGroup;

		private Transform _parentTransform;

		private Canvas _targetCanvas;

		private IPingDataProvider _pingDataProvider;

		private IDistanceFadeProvider _fadeFadeProvider;

		private bool _isVisible;

		private float _targetAlpha;

		private Vector2 _targetPosition = Vector2.zero;

		private float _lastDisplayedDistance = -1f;

		public void Initialize(Transform parentTransform, Canvas targetCanvas, IPingDataProvider pingDataProvider, float maxVisibilityDistance)
		{
			if ((Object)(object)parentTransform == (Object)null)
			{
				Plugin.Logger.LogError((object)"EdgeDistanceText: parentTransform is null");
				return;
			}
			if ((Object)(object)targetCanvas == (Object)null)
			{
				Plugin.Logger.LogError((object)"EdgeDistanceText: targetCanvas is null");
				return;
			}
			if (pingDataProvider == null)
			{
				Plugin.Logger.LogError((object)"EdgeDistanceText: pingDataProvider is null");
				return;
			}
			_parentTransform = parentTransform;
			_targetCanvas = targetCanvas;
			_pingDataProvider = pingDataProvider;
			_fadeFadeProvider = new DistanceFadeProvider(maxVisibilityDistance);
			try
			{
				CreateTextElements();
			}
			catch (Exception ex)
			{
				Plugin.Logger.LogError((object)("EdgeDistanceText: Failed to create text elements: " + ex.Message));
			}
		}

		public void UpdateDisplay(bool isVisible, ReticlePositionData positionData)
		{
			//IL_0040: Unknown result type (might be due to invalid IL or missing references)
			//IL_0045: Unknown result type (might be due to invalid IL or missing references)
			//IL_0047: Unknown result type (might be due to invalid IL or missing references)
			if (!PingItemsConfig.ShowEdgeDistance.Value || (Object)(object)_distanceText == (Object)null)
			{
				SetVisible(visible: false);
				return;
			}
			try
			{
				if (isVisible && positionData.IsOnEdge)
				{
					float num = CalculateDistanceBasedAlpha();
					if (num > 0f)
					{
						Vector2 targetPosition = CalculateSmartTextPosition(positionData);
						UpdateTextPosition(targetPosition);
						UpdateDistanceContent();
						UpdateTextColor();
						SetVisibleWithAlpha(visible: true, num);
					}
					else
					{
						SetVisible(visible: false);
					}
				}
				else
				{
					SetVisible(visible: false);
				}
			}
			catch (Exception ex)
			{
				Plugin.Logger.LogError((object)("EdgeDistanceText: UpdateDisplay failed: " + ex.Message));
				SetVisible(visible: false);
			}
		}

		public void DestroyText()
		{
			if ((Object)(object)_distanceText != (Object)null && (Object)(object)((Component)_distanceText).gameObject != (Object)null)
			{
				ValidationUtility.SafeDestroy((Object)(object)((Component)_distanceText).gameObject);
			}
			_distanceText = null;
			_textRectTransform = null;
			_canvasGroup = null;
		}

		public void Cleanup()
		{
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			_isVisible = false;
			_targetAlpha = 0f;
			_targetPosition = Vector2.zero;
			_lastDisplayedDistance = -1f;
			if ((Object)(object)_canvasGroup != (Object)null)
			{
				_canvasGroup.alpha = 0f;
			}
			if ((Object)(object)_distanceText != (Object)null)
			{
				((TMP_Text)_distanceText).text = string.Empty;
			}
			_parentTransform = null;
			_targetCanvas = null;
			_pingDataProvider = null;
			_fadeFadeProvider = null;
		}

		private void CreateTextElements()
		{
			//IL_0091: Unknown result type (might be due to invalid IL or missing references)
			//IL_0097: Expected O, but got Unknown
			if ((Object)(object)_targetCanvas == (Object)null || (Object)(object)_parentTransform == (Object)null)
			{
				return;
			}
			if ((Object)(object)_distanceText != (Object)null && (Object)(object)((Component)_distanceText).gameObject != (Object)null)
			{
				((Component)_distanceText).gameObject.transform.SetParent(_parentTransform, false);
				ConfigureTextAppearance();
				ConfigureRectTransform();
				if ((Object)(object)_canvasGroup != (Object)null)
				{
					_canvasGroup.alpha = 0f;
				}
				_isVisible = false;
			}
			else
			{
				GameObject val = new GameObject("EdgeDistanceText");
				val.transform.SetParent(_parentTransform, false);
				_distanceText = val.AddComponent<TextMeshProUGUI>();
				_textRectTransform = val.GetComponent<RectTransform>();
				_canvasGroup = val.AddComponent<CanvasGroup>();
				ConfigureTextAppearance();
				ConfigureRectTransform();
				_canvasGroup.alpha = 0f;
				_isVisible = false;
			}
		}

		private void ConfigureTextAppearance()
		{
			//IL_003b: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)_distanceText == (Object)null)
			{
				return;
			}
			try
			{
				((TMP_Text)_distanceText).text = "";
				((TMP_Text)_distanceText).fontSize = PingItemsConfig.EdgeDistanceFontSize.Value;
				((Graphic)_distanceText).color = Color.white;
				((TMP_Text)_distanceText).alignment = (TextAlignmentOptions)514;
				((TMP_Text)_distanceText).fontStyle = (FontStyles)0;
				TrySetGameFont();
				if (TextOutlineUtility.ShouldApplyOutline())
				{
					TextOutlineUtility.ApplyTextOutline(_distanceText);
				}
				((TMP_Text)_distanceText).enableAutoSizing = true;
				((TMP_Text)_distanceText).fontSizeMin = 10f;
				((TMP_Text)_distanceText).fontSizeMax = PingItemsConfig.EdgeDistanceFontSize.Value;
			}
			catch (Exception ex)
			{
				Plugin.Logger.LogError((object)("EdgeDistanceText: Failed to configure text appearance: " + ex.Message));
			}
		}

		private void TrySetGameFont()
		{
			try
			{
				UIManager instance = UIManager.Instance;
				if ((Object)(object)instance != (Object)null)
				{
					TextMeshProUGUI val = instance.RentLabel();
					if ((Object)(object)val != (Object)null && (Object)(object)((TMP_Text)val).font != (Object)null)
					{
						((TMP_Text)_distanceText).font = ((TMP_Text)val).font;
						instance.ReleaseLabel(val);
					}
				}
			}
			catch (Exception ex)
			{
				Plugin.Logger.LogWarning((object)("EdgeDistanceText: Could not set game font, using default: " + ex.Message));
			}
		}

		private void ConfigureRectTransform()
		{
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			//IL_0049: Unknown result type (might be due to invalid IL or missing references)
			//IL_0053: Unknown result type (might be due to invalid IL or missing references)
			//IL_006d: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)_textRectTransform == (Object)null))
			{
				_textRectTransform.anchorMin = Vector2.one * 0.5f;
				_textRectTransform.anchorMax = Vector2.one * 0.5f;
				_textRectTransform.pivot = Vector2.one * 0.5f;
				_textRectTransform.sizeDelta = new Vector2(100f, 30f);
			}
		}

		private Vector2 CalculateSmartTextPosition(ReticlePositionData positionData)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0049: Unknown result type (might be due to invalid IL or missing references)
			//IL_004f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0055: Unknown result type (might be due to invalid IL or missing references)
			//IL_0061: 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_006d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0073: Unknown result type (might be due to invalid IL or missing references)
			//IL_007f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0085: 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)
			//IL_0097: 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_00a9: 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_00bb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f7: Unknown result type (might be due to invalid IL or missing references)
			//IL_0103: Unknown result type (might be due to invalid IL or missing references)
			//IL_010f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0115: Unknown result type (might be due to invalid IL or missing references)
			//IL_0121: Unknown result type (might be due to invalid IL or missing references)
			//IL_0127: Unknown result type (might be due to invalid IL or missing references)
			Vector2 screenPosition = positionData.ScreenPosition;
			return (Vector2)(positionData.EdgeLocation switch
			{
				EdgeLocation.Left => new Vector2(screenPosition.x + 35f, screenPosition.y), 
				EdgeLocation.Right => new Vector2(screenPosition.x - 35f, screenPosition.y), 
				EdgeLocation.Top => new Vector2(screenPosition.x, screenPosition.y - 35f), 
				EdgeLocation.Bottom => new Vector2(screenPosition.x, screenPosition.y + 35f), 
				EdgeLocation.TopLeft => new Vector2(screenPosition.x + 25f, screenPosition.y - 25f), 
				EdgeLocation.TopRight => new Vector2(screenPosition.x - 25f, screenPosition.y - 25f), 
				EdgeLocation.BottomLeft => new Vector2(screenPosition.x + 25f, screenPosition.y + 25f), 
				EdgeLocation.BottomRight => new Vector2(screenPosition.x - 25f, screenPosition.y + 25f), 
				_ => new Vector2(screenPosition.x + 35f, screenPosition.y), 
			});
		}

		private void UpdateTextPosition(Vector2 targetPosition)
		{
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)_textRectTransform == (Object)null))
			{
				_targetPosition = targetPosition;
				_textRectTransform.anchoredPosition = _targetPosition;
			}
		}

		private void UpdateDistanceContent()
		{
			if (!((Object)(object)_distanceText == (Object)null) && _pingDataProvider != null)
			{
				float distance = _pingDataProvider.GetDistance();
				float value = PingItemsConfig.DistanceUpdateThreshold.Value;
				if (Mathf.Abs(distance - _lastDisplayedDistance) > value)
				{
					_lastDisplayedDistance = distance;
					string text = FormatDistanceText(distance);
					((TMP_Text)_distanceText).text = text;
				}
			}
		}

		private void UpdateTextColor()
		{
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)_distanceText == (Object)null) && _pingDataProvider != null)
			{
				Color playerColor = _pingDataProvider.GetPlayerColor();
				((Graphic)_distanceText).color = playerColor;
			}
		}

		private static string FormatDistanceText(float distance)
		{
			if (distance < 1000f)
			{
				return $"{distance:F0}m";
			}
			return $"{distance / 1000f:F1}km";
		}

		private float CalculateDistanceBasedAlpha()
		{
			if (_pingDataProvider == null || _fadeFadeProvider == null)
			{
				return 1f;
			}
			try
			{
				float distance = _pingDataProvider.GetDistance();
				return _fadeFadeProvider.CalculateDistanceAlpha(distance);
			}
			catch (Exception ex)
			{
				Plugin.Logger.LogError((object)("EdgeDistanceText: Failed to calculate distance alpha: " + ex.Message));
				return 1f;
			}
		}

		private void SetVisible(bool visible)
		{
			_isVisible = visible;
			_targetAlpha = (visible ? 1f : 0f);
		}

		private void SetVisibleWithAlpha(bool visible, float alpha)
		{
			_isVisible = visible;
			_targetAlpha = (visible ? Mathf.Clamp01(alpha) : 0f);
		}

		private void Update()
		{
			if (!((Object)(object)_canvasGroup == (Object)null) && !((Object)(object)_textRectTransform == (Object)null) && Mathf.Abs(_canvasGroup.alpha - _targetAlpha) > 0.01f)
			{
				_canvasGroup.alpha = Mathf.Lerp(_canvasGroup.alpha, _targetAlpha, Time.deltaTime / 0.3f);
			}
		}
	}
	public enum EdgeLocation
	{
		None,
		Left,
		Right,
		Top,
		Bottom,
		TopLeft,
		TopRight,
		BottomLeft,
		BottomRight
	}
	public struct ReticlePositionData
	{
		public Vector2 ScreenPosition { get; set; }

		public float TargetScale { get; set; }

		public bool IsOnEdge { get; set; }

		public bool IsVisible { get; set; }

		public EdgeLocation EdgeLocation { get; set; }

		public Vector2 CanvasSize { get; set; }
	}
	public class EdgeTracker
	{
		private readonly Camera _camera;

		private readonly RectTransform _canvasRect;

		public EdgeTracker(Camera camera, RectTransform canvasRect)
		{
			_camera = camera ?? throw new ArgumentNullException("camera");
			_canvasRect = canvasRect ?? throw new ArgumentNullException("canvasRect");
		}

		public ReticlePositionData CalculateReticlePosition(Vector3 worldPosition, float baseScale)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0060: Unknown result type (might be due to invalid IL or missing references)
			//IL_0065: Unknown result type (might be due to invalid IL or missing references)
			//IL_0066: Unknown result type (might be due to invalid IL or missing references)
			//IL_0074: Unknown result type (might be due to invalid IL or missing references)
			//IL_0075: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_0050: Unknown result type (might be due to invalid IL or missing references)
			//IL_0103: Unknown result type (might be due to invalid IL or missing references)
			//IL_0104: Unknown result type (might be due to invalid IL or missing references)
			//IL_0109: 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_0098: Unknown result type (might be due to invalid IL or missing references)
			//IL_009a: Unknown result type (might be due to invalid IL or missing references)
			//IL_009f: Unknown result type (might be due to invalid IL or missing references)
			//IL_008c: Unknown result type (might be due to invalid IL or missing references)
			//IL_008e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0093: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ab: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bf: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ef: Unknown result type (might be due to invalid IL or missing references)
			Vector2 sizeDelta = _canvasRect.sizeDelta;
			ReticlePositionData result;
			if ((Object)(object)_camera == (Object)null)
			{
				result = default(ReticlePositionData);
				result.ScreenPosition = Vector2.zero;
				result.TargetScale = baseScale;
				result.IsOnEdge = false;
				result.IsVisible = false;
				result.EdgeLocation = EdgeLocation.None;
				result.CanvasSize = sizeDelta;
				return result;
			}
			Vector3 val = _camera.WorldToViewportPoint(worldPosition);
			bool flag = val.z < 0f;
			bool flag2 = !IsWithinScreenBounds(Vector2.op_Implicit(val));
			if (flag || flag2)
			{
				Vector2 val2 = ((!flag) ? CalculateSmoothEdgeIntersection(val, isBehindCamera: false) : CalculateSmoothEdgeIntersection(val, isBehindCamera: true));
				float targetScale = CalculateAngularBasedScale(worldPosition, baseScale);
				EdgeLocation edgeLocation = DetermineEdgeLocation(val2);
				result = default(ReticlePositionData);
				result.ScreenPosition = ViewportToCanvasPosition(val2);
				result.TargetScale = targetScale;
				result.IsOnEdge = true;
				result.IsVisible = true;
				result.EdgeLocation = edgeLocation;
				result.CanvasSize = sizeDelta;
				return result;
			}
			result = default(ReticlePositionData);
			result.ScreenPosition = ViewportToCanvasPosition(Vector2.op_Implicit(val));
			result.TargetScale = baseScale;
			result.IsOnEdge = false;
			result.IsVisible = true;
			result.EdgeLocation = EdgeLocation.None;
			result.CanvasSize = sizeDelta;
			return result;
		}

		private static EdgeLocation DetermineEdgeLocation(Vector2 viewportPosition)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: 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)
			bool flag = viewportPosition.x <= 0.15f;
			bool flag2 = viewportPosition.x >= 0.85f;
			bool flag3 = viewportPosition.y >= 0.85f;
			bool flag4 = viewportPosition.y <= 0.15f;
			if (flag && flag3)
			{
				return EdgeLocation.TopLeft;
			}
			if (flag2 && flag3)
			{
				return EdgeLocation.TopRight;
			}
			if (flag && flag4)
			{
				return EdgeLocation.BottomLeft;
			}
			if (flag2 && flag4)
			{
				return EdgeLocation.BottomRight;
			}
			if (flag)
			{
				return EdgeLocation.Left;
			}
			if (flag2)
			{
				return EdgeLocation.Right;
			}
			if (flag3)
			{
				return EdgeLocation.Top;
			}
			if (flag4)
			{
				return EdgeLocation.Bottom;
			}
			return EdgeLocation.None;
		}

		private static bool IsWithinScreenBounds(Vector2 viewportPos)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			if (viewportPos.x >= 0f && viewportPos.x <= 1f && viewportPos.y >= 0f)
			{
				return viewportPos.y <= 1f;
			}
			return false;
		}

		private Vector2 CalculateSmoothEdgeIntersection(Vector3 viewportPos, bool isBehindCamera)
		{
			//IL_0032: 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_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_004d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0052: Unknown result type (might be due to invalid IL or missing references)
			//IL_0057: Unknown result type (might be due to invalid IL or missing references)
			//IL_005a: Unknown result type (might be due to invalid IL or missing references)
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0003: Unknown result type (might be due to invalid IL or missing references)
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0072: Unknown result type (might be due to invalid IL or missing references)
			//IL_0073: Unknown result type (might be due to invalid IL or missing references)
			//IL_0074: Unknown result type (might be due to invalid IL or missing references)
			Vector2 val;
			Vector2 normalized;
			Vector2 origin = default(Vector2);
			if (isBehindCamera)
			{
				val = new Vector2(0f - viewportPos.x, 0f - viewportPos.y);
				normalized = ((Vector2)(ref val)).normalized;
				((Vector2)(ref origin))..ctor(0.5f, 0.5f);
			}
			else
			{
				val = new Vector2(viewportPos.x, viewportPos.y) - new Vector2(0.5f, 0.5f);
				normalized = ((Vector2)(ref val)).normalized;
				((Vector2)(ref origin))..ctor(0.5f, 0.5f);
			}
			return CalculateRayEdgeIntersection(origin, normalized);
		}

		private Vector2 CalculateRayEdgeIntersection(Vector2 origin, Vector2 direction)
		{
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0058: Unknown result type (might be due to invalid IL or missing references)
			//IL_0059: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: Unknown result type (might be due to invalid IL or missing references)
			//IL_0069: Unknown result type (might be due to invalid IL or missing references)
			//IL_0078: 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_0088: Unknown result type (might be due to invalid IL or missing references)
			//IL_0089: 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_00b5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fc: 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)
			float num = 50f / Mathf.Min(_canvasRect.sizeDelta.x, _canvasRect.sizeDelta.y);
			float edgeValue = num;
			float edgeValue2 = 1f - num;
			float edgeValue3 = num;
			float edgeValue4 = 1f - num;
			Vector2? val = null;
			float num2 = float.MaxValue;
			Vector2?[] array = new Vector2?[4]
			{
				CalculateEdgeIntersection(origin, direction, edgeValue, isVertical: true),
				CalculateEdgeIntersection(origin, direction, edgeValue2, isVertical: true),
				CalculateEdgeIntersection(origin, direction, edgeValue3, isVertical: false),
				CalculateEdgeIntersection(origin, direction, edgeValue4, isVertical: false)
			};
			for (int i = 0; i < array.Length; i++)
			{
				Vector2? val2 = array[i];
				if (val2.HasValue)
				{
					float num3 = Vector2.Distance(origin, val2.Value);
					if (num3 < num2)
					{
						num2 = num3;
						val = val2;
					}
				}
			}
			return (Vector2)(((??)val) ?? new Vector2(0.5f, 0.5f));
		}

		private static Vector2? CalculateEdgeIntersection(Vector2 origin, Vector2 direction, float edgeValue, bool isVertical)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0094: Unknown result type (might be due to invalid IL or missing references)
			//IL_009b: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ac: 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_0041: Unknown result type (might be due to invalid IL or missing references)
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			//IL_0053: Unknown result type (might be due to invalid IL or missing references)
			//IL_005a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0067: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c7: Unknown result type (might be due to invalid IL or missing references)
			//IL_0074: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e6: Unknown result type (might be due to invalid IL or missing references)
			if (Mathf.Approximately(direction.x, 0f) && isVertical)
			{
				return null;
			}
			if (Mathf.Approximately(direction.y, 0f) && !isVertical)
			{
				return null;
			}
			Vector2 val = default(Vector2);
			if (isVertical)
			{
				float num = (edgeValue - origin.x) / direction.x;
				((Vector2)(ref val))..ctor(edgeValue, origin.y + num * direction.y);
				if (val.y < 0f || val.y > 1f || num < 0f)
				{
					return null;
				}
			}
			else
			{
				float num2 = (edgeValue - origin.y) / direction.y;
				((Vector2)(ref val))..ctor(origin.x + num2 * direction.x, edgeValue);
				if (val.x < 0f || val.x > 1f || num2 < 0f)
				{
					return null;
				}
			}
			return val;
		}

		private float CalculateAngularBasedScale(Vector3 worldPosition, float baseScale)
		{
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)_camera == (Object)null)
			{
				return baseScale;
			}
			baseScale = Mathf.Clamp(baseScale, 0.1f, 5f);
			float num = Mathf.Clamp01(CalculateViewingAngleInWorldSpace(worldPosition) / 90f);
			float num2 = Mathf.Lerp(1f, 0.6f, num * num);
			return Mathf.Clamp(baseScale * num2, 0.1f, 5f);
		}

		private float CalculateViewingAngleInWorldSpace(Vector3 worldPosition)
		{
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_003a: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0042: Unknown result type (might be due to invalid IL or missing references)
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)_camera == (Object)null)
			{
				return 0f;
			}
			Vector3 forward = ((Component)_camera).transform.forward;
			Vector3 val = worldPosition - ((Component)_camera).transform.position;
			Vector3 normalized = ((Vector3)(ref val)).normalized;
			return Vector3.Angle(forward, normalized);
		}

		private Vector2 ViewportToCanvasPosition(Vector2 viewportPos)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			Vector2 sizeDelta = _canvasRect.sizeDelta;
			return new Vector2((viewportPos.x - 0.5f) * sizeDelta.x, (viewportPos.y - 0.5f) * sizeDelta.y);
		}
	}
	public class ReticleResolver
	{
		private readonly Dictionary<ReticleType, Func<GUIManager, GameObject>> _reticleGetters;

		public ReticleResolver()
		{
			_reticleGetters = new Dictionary<ReticleType, Func<GUIManager, GameObject>>
			{
				{
					ReticleType.Default,
					(GUIManager gui) => gui.reticleDefault
				},
				{
					ReticleType.X,
					(GUIManager gui) => gui.reticleX
				},
				{
					ReticleType.Climb,
					(GUIManager gui) => gui.reticleClimb
				},
				{
					ReticleType.ClimbJump,
					(GUIManager gui) => gui.reticleClimbJump
				},
				{
					ReticleType.Throw,
					(GUIManager gui) => gui.reticleThrow
				},
				{
					ReticleType.Reach,
					(GUIManager gui) => gui.reticleReach
				},
				{
					ReticleType.Spike,
					(GUIManager gui) => gui.reticleSpike
				},
				{
					ReticleType.Rope,
					(GUIManager gui) => gui.reticleRope
				},
				{
					ReticleType.ClimbTry,
					(GUIManager gui) => gui.reticleClimbTry
				},
				{
					ReticleType.Vine,
					(GUIManager gui) => gui.reticleVine
				},
				{
					ReticleType.Boost,
					(GUIManager gui) => gui.reticleBoost
				},
				{
					ReticleType.Shoot,
					(GUIManager gui) => gui.reticleShoot
				}
			};
		}

		public GameObject GetReticle(GUIManager guiManager, ReticleType reticleType)
		{
			if ((Object)(object)guiManager == (Object)null)
			{
				Plugin.Logger.LogWarning((object)"GUIManager is null, cannot resolve reticle");
				return null;
			}
			if (!_reticleGetters.TryGetValue(reticleType, out var value))
			{
				Plugin.Logger.LogWarning((object)$"Unknown reticle type: {reticleType}, falling back to Default");
				value = _reticleGetters[ReticleType.Default];
			}
			try
			{
				GameObject val = value(guiManager);
				if ((Object)(object)val == (Object)null)
				{
					Plugin.Logger.LogWarning((object)$"Reticle {reticleType} is null, falling back to Default");
					return _reticleGetters[ReticleType.Default](guiManager);
				}
				return val;
			}
			catch (Exception ex)
			{
				Plugin.Logger.LogWarning((object)$"Failed to get reticle {reticleType}: {ex.Message}, falling back to Default");
				return _reticleGetters[ReticleType.Default](guiManager);
			}
		}

		public GameObject GetConfiguredReticle(GUIManager guiManager)
		{
			return GetReticle(guiManager, PingItemsConfig.ReticleType.Value);
		}
	}
	public class ReticleScaleProvider
	{
		private readonly Dictionary<ReticleType, float> _baseScaleFactors;

		public ReticleScaleProvider()
		{
			_baseScaleFactors = new Dictionary<ReticleType, float>
			{
				{
					ReticleType.Default,
					0.75f
				},
				{
					ReticleType.X,
					1f
				},
				{
					ReticleType.Climb,
					0.25f
				},
				{
					ReticleType.ClimbJump,
					0.25f
				},
				{
					ReticleType.Throw,
					0.25f
				},
				{
					ReticleType.Reach,
					0.25f
				},
				{
					ReticleType.Spike,
					0.25f
				},
				{
					ReticleType.Rope,
					0.25f
				},
				{
					ReticleType.ClimbTry,
					0.25f
				},
				{
					ReticleType.Vine,
					0.25f
				},
				{
					ReticleType.Boost,
					0.25f
				},
				{
					ReticleType.Shoot,
					0.25f
				}
			};
		}

		public float GetNormalizedScaleFactor(ReticleType reticleType)
		{
			if (_baseScaleFactors.TryGetValue(reticleType, out var value))
			{
				return value;
			}
			Plugin.Logger.LogWarning((object)$"⚠\ufe0f Unknown reticle type for scaling: {reticleType}, using default scale");
			return _baseScaleFactors[ReticleType.Default];
		}

		public float GetFinalScale(ReticleType reticleType, float userScale)
		{
			float normalizedScaleFactor = GetNormalizedScaleFactor(reticleType);
			return userScale * normalizedScaleFactor;
		}

		public float GetConfiguredReticleSca