Decompiled source of FroggosGPS v1.2.1

Mods/Froggos-GPS.dll

Decompiled a day ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Text;
using FroggosGps;
using HarmonyLib;
using Il2Cpp;
using Il2CppInterop.Runtime.Injection;
using Il2CppInterop.Runtime.InteropTypes;
using Il2CppInterop.Runtime.InteropTypes.Arrays;
using Il2CppPathfinding;
using Il2CppScheduleOne.DevUtilities;
using Il2CppScheduleOne.Map;
using Il2CppScheduleOne.Math;
using Il2CppScheduleOne.NPCs;
using Il2CppScheduleOne.PlayerScripts;
using Il2CppScheduleOne.UI;
using Il2CppScheduleOne.UI.Compass;
using Il2CppScheduleOne.UI.Phone.Map;
using Il2CppScheduleOne.Vehicles.AI;
using Il2CppSystem;
using Il2CppSystem.Collections.Generic;
using Il2CppSystem.Reflection;
using MelonLoader;
using MelonLoader.Preferences;
using Microsoft.CodeAnalysis;
using S1API.PhoneApp;
using S1API.UI;
using S1API.Utils;
using UnityEngine;
using UnityEngine.AI;
using UnityEngine.EventSystems;
using UnityEngine.Events;
using UnityEngine.InputSystem;
using UnityEngine.InputSystem.Controls;
using UnityEngine.Rendering;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: MelonInfo(typeof(GpsMod), "Froggos-GPS", "1.2.1", "froggonater", null)]
[assembly: MelonGame("TVGS", "Schedule I")]
[assembly: MelonOptionalDependencies(new string[] { "S1API.Il2Cpp.MelonLoader" })]
[assembly: TargetFramework(".NETCoreApp,Version=v6.0", FrameworkDisplayName = ".NET 6.0")]
[assembly: AssemblyCompany("Froggos-GPS")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.2.1.0")]
[assembly: AssemblyInformationalVersion("1.2.1")]
[assembly: AssemblyProduct("Froggos-GPS")]
[assembly: AssemblyTitle("Froggos-GPS")]
[assembly: AssemblyVersion("1.2.1.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[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 FroggosGps
{
	internal class GpsConfig
	{
		public readonly MelonPreferences_Category Category;

		public readonly MelonPreferences_Entry<string> LineColor;

		public readonly MelonPreferences_Entry<float> LineOpacity;

		public readonly MelonPreferences_Entry<float> LineWidth;

		public readonly MelonPreferences_Entry<float> HeightOffset;

		public readonly MelonPreferences_Entry<bool> FlatLine;

		public readonly MelonPreferences_Entry<bool> DrawThroughWalls;

		public readonly MelonPreferences_Entry<float> MaxDrawDistance;

		public readonly MelonPreferences_Entry<bool> ShowBeacon;

		public readonly MelonPreferences_Entry<string> ClearKey;

		public readonly MelonPreferences_Entry<string> RightClickAction;

		public readonly MelonPreferences_Entry<float> RecalcInterval;

		public readonly MelonPreferences_Entry<float> OffRouteDistance;

		public readonly MelonPreferences_Entry<float> ArrivalRadius;

		public readonly MelonPreferences_Entry<bool> RoadsAndPathsOnly;

		public readonly MelonPreferences_Entry<bool> UseRoadsWhenDriving;

		public readonly MelonPreferences_Entry<bool> RoadNetworkAlways;

		public readonly MelonPreferences_Entry<bool> ShowOnMinimap;

		public readonly MelonPreferences_Entry<float> MinimapLineWidth;

		public readonly MelonPreferences_Entry<float> OffPathAreaCost;

		public readonly MelonPreferences_Entry<float> RoadAreaCost;

		public readonly MelonPreferences_Entry<bool> ShowOnMap;

		public readonly MelonPreferences_Entry<float> MapLineWidthMeters;

		public readonly MelonPreferences_Entry<bool> ShowOnCompass;

		public readonly MelonPreferences_Entry<bool> ShowHud;

		public readonly MelonPreferences_Entry<bool> NotifyOnArrival;

		public readonly MelonPreferences_Entry<bool> VerboseLogging;

		private bool _suppress;

		public event Action Changed;

		public GpsConfig()
		{
			Category = MelonPreferences.CreateCategory("Froggos-GPS", "Froggos-GPS");
			LineColor = Category.CreateEntry<string>("LineColor", "#00E5FF", (string)null, "Route color as hex (#RRGGBB).", false, false, (ValueValidator)null, (string)null);
			LineOpacity = Category.CreateEntry<float>("LineOpacity", 0.9f, (string)null, "Route opacity, 0.1 (very see-through) to 1 (solid).", false, false, (ValueValidator)null, (string)null);
			LineWidth = Category.CreateEntry<float>("LineWidth", 0.6f, (string)null, "Route line width in meters.", false, false, (ValueValidator)null, (string)null);
			HeightOffset = Category.CreateEntry<float>("HeightOffset", 0.25f, (string)null, "How far above the ground the line floats (meters).", false, false, (ValueValidator)null, (string)null);
			FlatLine = Category.CreateEntry<bool>("FlatLine", true, (string)null, "true = line lies flat on the ground like a road marking; false = ribbon that always faces the camera.", false, false, (ValueValidator)null, (string)null);
			DrawThroughWalls = Category.CreateEntry<bool>("DrawThroughWalls", false, (string)null, "Draw the route on top of everything (visible through buildings/hills).", false, false, (ValueValidator)null, (string)null);
			MaxDrawDistance = Category.CreateEntry<float>("MaxDrawDistance", 600f, (string)null, "Only draw this many meters of route ahead of you.", false, false, (ValueValidator)null, (string)null);
			ShowBeacon = Category.CreateEntry<bool>("ShowBeacon", true, (string)null, "Draw a tall light beam at the destination.", false, false, (ValueValidator)null, (string)null);
			ClearKey = Category.CreateEntry<string>("ClearKey", "G", (string)null, "Key that clears the route (UnityEngine.InputSystem.Key name, e.g. G, F7, Backquote).", false, false, (ValueValidator)null, (string)null);
			RightClickAction = Category.CreateEntry<string>("RightClickAction", "Clear", (string)null, "What right-clicking the phone map does: Clear or Set.", false, false, (ValueValidator)null, (string)null);
			RecalcInterval = Category.CreateEntry<float>("RecalcInterval", 1f, (string)null, "Refresh rate: seconds between route updates while moving.", false, false, (ValueValidator)null, (string)null);
			OffRouteDistance = Category.CreateEntry<float>("OffRouteDistance", 10f, (string)null, "Recalculate immediately when this far (meters) from the route.", false, false, (ValueValidator)null, (string)null);
			ArrivalRadius = Category.CreateEntry<float>("ArrivalRadius", 5f, (string)null, "Route clears when you are this close (meters) to the destination.", false, false, (ValueValidator)null, (string)null);
			RoadsAndPathsOnly = Category.CreateEntry<bool>("RoadsAndPathsOnly", true, (string)null, "On foot, keep the route on roads and sidewalks/paths (no shortcuts across grass or lots).", false, false, (ValueValidator)null, (string)null);
			UseRoadsWhenDriving = Category.CreateEntry<bool>("UseRoadsWhenDriving", true, (string)null, "Use the game's vehicle road graph when you're in a vehicle.", false, false, (ValueValidator)null, (string)null);
			RoadNetworkAlways = Category.CreateEntry<bool>("RoadNetworkAlways", true, (string)null, "Use the road network (quickest route by road) for every route, walking or driving. Falls back to NavMesh roads/paths when unavailable.", false, false, (ValueValidator)null, (string)null);
			ShowOnMinimap = Category.CreateEntry<bool>("ShowOnMinimap", true, (string)null, "Draw the route on the MultiMiniMap minimap (if that mod is installed).", false, false, (ValueValidator)null, (string)null);
			MinimapLineWidth = Category.CreateEntry<float>("MinimapLineWidth", 4f, (string)null, "Route thickness on the minimap, in pixels.", false, false, (ValueValidator)null, (string)null);
			OffPathAreaCost = Category.CreateEntry<float>("OffPathAreaCost", 3f, (string)null, "NavMesh cost for open ground when RoadsAndPathsOnly is off. Sidewalks/paths cost 1.", false, false, (ValueValidator)null, (string)null);
			RoadAreaCost = Category.CreateEntry<float>("RoadAreaCost", 1.5f, (string)null, "NavMesh cost for road surface when walking (1 = as good as a sidewalk; the game's NPCs use 5).", false, false, (ValueValidator)null, (string)null);
			ShowOnMap = Category.CreateEntry<bool>("ShowOnMap", true, (string)null, "Draw the route and destination on the phone map.", false, false, (ValueValidator)null, (string)null);
			MapLineWidthMeters = Category.CreateEntry<float>("MapLineWidthMeters", 6f, (string)null, "Thickness of the route on the phone map, in world meters.", false, false, (ValueValidator)null, (string)null);
			ShowOnCompass = Category.CreateEntry<bool>("ShowOnCompass", true, (string)null, "Show the destination on the HUD compass.", false, false, (ValueValidator)null, (string)null);
			ShowHud = Category.CreateEntry<bool>("ShowHud", true, (string)null, "Show distance and ETA to the destination on screen.", false, false, (ValueValidator)null, (string)null);
			NotifyOnArrival = Category.CreateEntry<bool>("NotifyOnArrival", true, (string)null, "Phone notification when you arrive.", false, false, (ValueValidator)null, (string)null);
			VerboseLogging = Category.CreateEntry<bool>("VerboseLogging", false, (string)null, "Log every recalculation.", false, false, (ValueValidator)null, (string)null);
			foreach (MelonPreferences_Entry entry in Category.Entries)
			{
				((MelonEventBase<LemonAction<object, object>>)(object)entry.OnEntryValueChangedUntyped).Subscribe((LemonAction<object, object>)delegate
				{
					RaiseChanged();
				}, 0, false);
			}
		}

		public void RaiseChanged()
		{
			if (_suppress)
			{
				return;
			}
			try
			{
				this.Changed?.Invoke();
			}
			catch (Exception ex)
			{
				GpsMod.Log.Error("Settings change handler failed: " + ex);
			}
		}

		public void Set<T>(MelonPreferences_Entry<T> entry, T value)
		{
			_suppress = true;
			try
			{
				entry.Value = value;
			}
			finally
			{
				_suppress = false;
			}
			Category.SaveToFile(false);
			RaiseChanged();
		}

		public Color BaseColor()
		{
			//IL_009f: Unknown result type (might be due to invalid IL or missing references)
			//IL_007e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0083: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a5: Unknown result type (might be due to invalid IL or missing references)
			string text = (LineColor.Value ?? "").Trim().TrimStart('#');
			try
			{
				if (text.Length == 6 || text.Length == 8)
				{
					float num = (float)Convert.ToInt32(text.Substring(0, 2), 16) / 255f;
					float num2 = (float)Convert.ToInt32(text.Substring(2, 2), 16) / 255f;
					float num3 = (float)Convert.ToInt32(text.Substring(4, 2), 16) / 255f;
					return new Color(num, num2, num3, 1f);
				}
			}
			catch
			{
			}
			return new Color(0f, 0.9f, 1f, 1f);
		}

		public Color ParseLineColor()
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			Color result = BaseColor();
			result.a = Mathf.Clamp(LineOpacity.Value, 0.05f, 1f);
			return result;
		}

		public static string ToHex(Color c)
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			return "#" + ((int)(c.r * 255f)).ToString("X2") + ((int)(c.g * 255f)).ToString("X2") + ((int)(c.b * 255f)).ToString("X2");
		}
	}
	public class GpsController : MonoBehaviour
	{
		private static GpsController s_instance;

		private GpsCore _core;

		private int _errorCount;

		private float _nextErrorLog;

		public GpsController(IntPtr ptr)
			: base(ptr)
		{
		}

		internal static void EnsureCreated()
		{
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)s_instance != (Object)null))
			{
				s_instance = new GameObject("Froggos-GPS").AddComponent<GpsController>();
				GpsMod.Log.Msg("GPS controller created.");
			}
		}

		private void Update()
		{
			try
			{
				if (_core == null)
				{
					_core = new GpsCore(((Component)this).gameObject);
				}
				_core.Update();
			}
			catch (Exception value)
			{
				_errorCount++;
				if (_errorCount <= 5 || Time.unscaledTime >= _nextErrorLog)
				{
					_nextErrorLog = Time.unscaledTime + 10f;
					GpsMod.Log.Error($"Update error #{_errorCount}: {value}");
				}
			}
		}

		private void OnDestroy()
		{
			try
			{
				_core?.Destroy();
			}
			catch (Exception ex)
			{
				GpsMod.Log.Error("Cleanup error: " + ex);
			}
			_core = null;
			if ((Object)(object)s_instance == (Object)(object)this)
			{
				s_instance = null;
			}
		}
	}
	internal class GpsCore
	{
		private readonly GameObject _host;

		private readonly RoutePlanner _planner;

		private readonly RouteRenderer _renderer;

		private readonly MapOverlay _map = new MapOverlay();

		private bool _hasDest;

		private Vector3 _dest;

		private GameObject _destObject;

		private Element _compassElement;

		private RectTransform _compassTemplate;

		private bool _compassFailed;

		private bool _forceRecalc;

		private float _lastCalcTime = -999f;

		private Vector3 _lastCalcPos;

		private RouteMode _lastMode;

		private bool _lastFailed;

		private string _lastFailureInfo;

		private bool _loggedFirstRoute;

		private int _recalcCount;

		private Key _clearKey = (Key)21;

		private string _parsedKeyName;

		private readonly GpsHud _hud;

		private string _destLabel = "";

		private List<Vector3> _lastRoutePoints;

		private Vector3 _speedSamplePos;

		private float _speedSampleTime;

		private float _speed;

		private float _nextHudUpdate;

		private bool _settingsDirty;

		public static Action UiTick;

		private Transform _followTarget;

		private float _nextFollowCheck;

		private const float FollowCheckInterval = 2f;

		private const float FollowMoveThreshold = 8f;

		private bool _currentComplete;

		private bool _roadFallbackLogged;

		public static GpsCore Instance { get; private set; }

		public bool HasDestination => _hasDest;

		public string DestinationLabel => _destLabel;

		public RouteMode CurrentMode => _lastMode;

		public bool RouteFailed => _lastFailed;

		public float RemainingMeters
		{
			get
			{
				if (!_renderer.HasRoute)
				{
					return 0f;
				}
				return _renderer.RemainingLength();
			}
		}

		public float EtaSeconds { get; private set; } = float.NaN;

		public GpsCore(GameObject host)
		{
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			_host = host;
			_planner = new RoutePlanner(host);
			_renderer = new RouteRenderer(host.transform);
			_hud = new GpsHud(host.transform);
			Instance = this;
			GpsMod.Cfg.Changed += OnSettingsChanged;
		}

		public void Update()
		{
			//IL_007e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0083: Unknown result type (might be due to invalid IL or missing references)
			//IL_008b: 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_0094: 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_00d8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e3: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e5: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ea: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ef: Unknown result type (might be due to invalid IL or missing references)
			//IL_029b: Unknown result type (might be due to invalid IL or missing references)
			//IL_028c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0226: Unknown result type (might be due to invalid IL or missing references)
			_planner.Tick();
			HandleHotkey();
			_map.HandleInput(this);
			if (_settingsDirty)
			{
				ApplySettings();
			}
			try
			{
				UiTick?.Invoke();
			}
			catch (Exception ex)
			{
				GpsMod.Verbose("Phone app tick failed: " + ex.Message);
			}
			Player local = Player.Local;
			if (!_hasDest || (Object)(object)local == (Object)null)
			{
				_hud.Hide();
				return;
			}
			bool inVehicle;
			Vector3 playerPosition = GetPlayerPosition(local, out inVehicle);
			UpdateFollow();
			UpdateSpeedAndHud(playerPosition, inVehicle);
			if (RoutePlanner.HorizontalDistance(playerPosition, _dest) <= GpsMod.Cfg.ArrivalRadius.Value && Mathf.Abs(playerPosition.y - _dest.y) < 6f)
			{
				GpsMod.Log.Msg("Arrived at destination " + RoutePlanner.Fmt(_dest) + ". Route cleared.");
				Notify("You have arrived", string.IsNullOrEmpty(_destLabel) ? "Destination reached" : _destLabel);
				ClearRoute(null);
				return;
			}
			RouteMode routeMode = ((GpsMod.Cfg.RoadNetworkAlways.Value || (inVehicle && GpsMod.Cfg.UseRoadsWhenDriving.Value)) ? RouteMode.Drive : RouteMode.Walk);
			float num = Time.unscaledTime - _lastCalcTime;
			float num2 = Mathf.Max(0.2f, GpsMod.Cfg.RecalcInterval.Value);
			string text = null;
			if (_forceRecalc)
			{
				text = "new destination";
			}
			else if (routeMode != _lastMode)
			{
				text = $"mode changed to {routeMode}";
			}
			else if (_lastFailed)
			{
				if (num >= Mathf.Max(num2, 3f))
				{
					text = "retry after failure";
				}
			}
			else if (num >= num2)
			{
				Vector3 val = playerPosition - _lastCalcPos;
				if (((Vector3)(ref val)).sqrMagnitude > 1f)
				{
					text = "interval";
				}
			}
			if (text == null && _renderer.HasRoute && num >= 0.3f)
			{
				float num3 = _renderer.DistanceFromRoute(playerPosition);
				if (num3 > GpsMod.Cfg.OffRouteDistance.Value)
				{
					text = $"off route by {num3:F1}m";
				}
			}
			if (text != null && !_planner.DriveInFlight)
			{
				Recalculate(playerPosition, routeMode, text);
			}
			_renderer.UpdateView(playerPosition);
		}

		private void UpdateSpeedAndHud(Vector3 pos, bool inVehicle)
		{
			//IL_005c: Unknown result type (might be due to invalid IL or missing references)
			//IL_005d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: 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_014f: Unknown result type (might be due to invalid IL or missing references)
			float unscaledTime = Time.unscaledTime;
			if (unscaledTime - _speedSampleTime >= 0.5f)
			{
				if (_speedSampleTime > 0f)
				{
					float num = RoutePlanner.HorizontalDistance(pos, _speedSamplePos) / (unscaledTime - _speedSampleTime);
					_speed = Mathf.Lerp(_speed, Mathf.Min(num, 60f), 0.3f);
				}
				_speedSamplePos = pos;
				_speedSampleTime = unscaledTime;
			}
			float remainingMeters = RemainingMeters;
			float num2 = (inVehicle ? 12f : 3.2f);
			EtaSeconds = ((remainingMeters > 0f) ? (remainingMeters / Mathf.Max(_speed, num2 * 0.6f)) : float.NaN);
			if (!GpsMod.Cfg.ShowHud.Value)
			{
				_hud.Hide();
			}
			else if (!(unscaledTime < _nextHudUpdate))
			{
				_nextHudUpdate = unscaledTime + 0.25f;
				string text = (string.IsNullOrEmpty(_destLabel) ? "" : ("  ·  " + _destLabel));
				string text2 = ((_lastFailed && !_renderer.HasRoute) ? ("GPS: no route found" + text) : (GpsHud.FormatDistance(remainingMeters) + "  ·  " + GpsHud.FormatEta(EtaSeconds) + text));
				_hud.Show(text2, GpsMod.Cfg.BaseColor());
			}
		}

		private static void Notify(string title, string subtitle)
		{
			if (!GpsMod.Cfg.NotifyOnArrival.Value)
			{
				return;
			}
			try
			{
				if (Singleton<NotificationsManager>.InstanceExists)
				{
					Singleton<NotificationsManager>.Instance.SendNotification(title, subtitle, GpsIcon.Get(), 5f, true);
				}
			}
			catch (Exception ex)
			{
				GpsMod.Verbose("Notification failed: " + ex.Message);
			}
		}

		private void OnSettingsChanged()
		{
			_settingsDirty = true;
		}

		private void ApplySettings()
		{
			//IL_004b: Unknown result type (might be due to invalid IL or missing references)
			_settingsDirty = false;
			_renderer.ApplyStyle();
			_map.ApplyStyle();
			if (_hasDest)
			{
				if (GpsMod.Cfg.ShowOnMap.Value && _lastRoutePoints != null)
				{
					_map.DrawRoute(_lastRoutePoints, _dest);
				}
				if (GpsMod.Cfg.ShowOnCompass.Value)
				{
					AddCompassMarker();
				}
				else
				{
					RemoveCompassMarker();
				}
				_forceRecalc = true;
			}
			if (!GpsMod.Cfg.ShowHud.Value)
			{
				_hud.Hide();
			}
			GpsMod.Verbose("Settings applied.");
		}

		public void OnMapOpened()
		{
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			if (_hasDest && _lastRoutePoints != null && GpsMod.Cfg.ShowOnMap.Value)
			{
				_map.DrawRoute(_lastRoutePoints, _dest);
			}
		}

		public void Reroute()
		{
			_forceRecalc = true;
		}

		internal bool TryGetMinimapRoute(out List<Vector3> points, out int start, out Vector3 destination, out Vector3 player, out MapProjection projection)
		{
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			//IL_003b: Unknown result type (might be due to invalid IL or missing references)
			//IL_006b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0070: Unknown result type (might be due to invalid IL or missing references)
			points = _renderer.DensePoints;
			start = _renderer.TrimIndex;
			destination = _dest;
			projection = _map.Projection;
			player = Vector3.zero;
			Player local = Player.Local;
			if (!_hasDest || (Object)(object)local == (Object)null || points.Count < 2)
			{
				return false;
			}
			player = ((Component)local).transform.position;
			if (!projection.Valid)
			{
				return projection.Calibrate();
			}
			return true;
		}

		private static Vector3 GetPlayerPosition(Player player, out bool inVehicle)
		{
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			inVehicle = player.IsInVehicle && (Object)(object)player.CurrentVehicle != (Object)null;
			if (inVehicle)
			{
				return ((Component)player.CurrentVehicle).transform.position;
			}
			return player.PlayerBasePosition;
		}

		private static bool IsTypingInUi()
		{
			try
			{
				EventSystem current = EventSystem.current;
				GameObject val = (((Object)(object)current != (Object)null) ? current.currentSelectedGameObject : null);
				if ((Object)(object)val == (Object)null)
				{
					return false;
				}
				InputField component = val.GetComponent<InputField>();
				return (Object)(object)component != (Object)null && component.isFocused;
			}
			catch
			{
				return false;
			}
		}

		private void HandleHotkey()
		{
			//IL_0051: Unknown result type (might be due to invalid IL or missing references)
			//IL_006a: 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)
			string value = GpsMod.Cfg.ClearKey.Value;
			if (value != _parsedKeyName)
			{
				_parsedKeyName = value;
				if (!Enum.TryParse<Key>(value, ignoreCase: true, out _clearKey))
				{
					GpsMod.Log.Warning("ClearKey '" + value + "' is not a valid InputSystem key name; using G.");
					_clearKey = (Key)21;
				}
			}
			Keyboard current = Keyboard.current;
			if (current != null && !IsTypingInUi() && ((ButtonControl)current[_clearKey]).wasPressedThisFrame && _hasDest)
			{
				ClearRoute($"{_clearKey} key");
			}
		}

		public void SetDestination(Vector2 worldXZ, string source)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			SetDestination(worldXZ, source, "");
			_followTarget = null;
		}

		public bool SetDestinationWorld(Vector3 world, string label)
		{
			//IL_0001: 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_000d: Unknown result type (might be due to invalid IL or missing references)
			SetDestination(new Vector2(world.x, world.z), "phone app", label);
			_followTarget = null;
			return _hasDest;
		}

		public bool SetDestinationFollow(Transform target, string label)
		{
			//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_0013: 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_001f: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)target == (Object)null)
			{
				return false;
			}
			Vector3 position = target.position;
			SetDestination(new Vector2(position.x, position.z), "phone app (following)", label);
			_followTarget = (_hasDest ? target : null);
			_nextFollowCheck = Time.unscaledTime + 2f;
			return _hasDest;
		}

		private void UpdateFollow()
		{
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			//IL_0048: 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_0074: 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_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_009f: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a0: 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_00be: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)_followTarget == (Object)null || Time.unscaledTime < _nextFollowCheck)
			{
				return;
			}
			_nextFollowCheck = Time.unscaledTime + 2f;
			Vector3 position;
			try
			{
				position = _followTarget.position;
			}
			catch
			{
				_followTarget = null;
				return;
			}
			if (RoutePlanner.HorizontalDistance(position, _dest) < 8f)
			{
				return;
			}
			Player local = Player.Local;
			float referenceY = (((Object)(object)local != (Object)null) ? local.PlayerBasePosition.y : position.y);
			if (_planner.ResolveDestination(position.x, position.z, referenceY, out var result, out var _))
			{
				_dest = result;
				if ((Object)(object)_destObject != (Object)null)
				{
					_destObject.transform.position = result;
				}
				_forceRecalc = true;
				GpsMod.Verbose($"Follow target '{_destLabel}' moved; destination now {RoutePlanner.Fmt(result)}.");
			}
		}

		private void SetDestination(Vector2 worldXZ, string source, string label)
		{
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: 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_0092: Unknown result type (might be due to invalid IL or missing references)
			//IL_00db: Unknown result type (might be due to invalid IL or missing references)
			//IL_00dc: Unknown result type (might be due to invalid IL or missing references)
			//IL_0127: Unknown result type (might be due to invalid IL or missing references)
			//IL_012c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0165: Unknown result type (might be due to invalid IL or missing references)
			//IL_0183: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_0203: Unknown result type (might be due to invalid IL or missing references)
			Player local = Player.Local;
			float referenceY = (((Object)(object)local != (Object)null) ? local.PlayerBasePosition.y : 0f);
			if (!_planner.ResolveDestination(worldXZ.x, worldXZ.y, referenceY, out var result, out var how))
			{
				GpsMod.Log.Warning($"Destination from {source} rejected: clicked ({worldXZ.x:F1}, {worldXZ.y:F1}) - {how}");
				return;
			}
			_destLabel = label ?? "";
			_lastRoutePoints = null;
			_dest = result;
			_hasDest = true;
			_forceRecalc = true;
			_lastFailed = false;
			_lastFailureInfo = null;
			_loggedFirstRoute = false;
			_recalcCount = 0;
			_planner.CancelDrive();
			float value = (((Object)(object)local != (Object)null) ? Vector3.Distance(local.PlayerBasePosition, result) : (-1f));
			GpsMod.Log.Msg($"Destination set from {source}: clicked XZ ({worldXZ.x:F1}, {worldXZ.y:F1}) -> {RoutePlanner.Fmt(result)} [{how}], {value:F0}m away.");
			EnsureDestObject();
			_destObject.transform.position = result;
			AddCompassMarker();
		}

		public void ClearRoute(string reason)
		{
			if (reason != null && _hasDest)
			{
				GpsMod.Log.Msg("Route cleared (" + reason + ").");
			}
			_hasDest = false;
			_forceRecalc = false;
			_planner.CancelDrive();
			_renderer.Clear();
			_map.ClearMap();
			_hud.Hide();
			_lastRoutePoints = null;
			_followTarget = null;
			_destLabel = "";
			EtaSeconds = float.NaN;
			RemoveCompassMarker();
		}

		private void Recalculate(Vector3 pos, RouteMode mode, string reason)
		{
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			//IL_0050: Unknown result type (might be due to invalid IL or missing references)
			//IL_0055: Unknown result type (might be due to invalid IL or missing references)
			//IL_0096: Unknown result type (might be due to invalid IL or missing references)
			//IL_009c: 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_006b: Unknown result type (might be due to invalid IL or missing references)
			_forceRecalc = false;
			_lastCalcTime = Time.unscaledTime;
			_lastCalcPos = pos;
			_lastMode = mode;
			_recalcCount++;
			Vector3 dest = _dest;
			if (mode == RouteMode.Drive)
			{
				if (_planner.RequestDrive(pos, dest, delegate(RouteResult r)
				{
					//IL_000e: 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_0079: 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)
					if (_hasDest && !(dest != _dest))
					{
						if (r.Points.Count < 2)
						{
							if (!_roadFallbackLogged)
							{
								_roadFallbackLogged = true;
								GpsMod.Log.Warning("Road network route failed (" + r.Info + "); using the NavMesh road/path route instead.");
							}
							OnRoute(SafePlanWalk(pos, dest), reason + " (road network fallback)");
						}
						else
						{
							OnRoute(r, reason);
						}
					}
				}))
				{
					return;
				}
				GpsMod.Log.Warning("Vehicle road graph unavailable; using on-foot NavMesh route while driving.");
			}
			OnRoute(SafePlanWalk(pos, dest), reason);
		}

		private RouteResult SafePlanWalk(Vector3 from, Vector3 to)
		{
			//IL_0006: 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)
			try
			{
				return _planner.PlanWalk(from, to);
			}
			catch (Exception ex)
			{
				return new RouteResult
				{
					Mode = RouteMode.Walk,
					Info = "exception: " + ex
				};
			}
		}

		private void OnRoute(RouteResult r, string reason)
		{
			//IL_01fe: Unknown result type (might be due to invalid IL or missing references)
			//IL_0215: Unknown result type (might be due to invalid IL or missing references)
			if (r == null || r.Points.Count < 2)
			{
				string text = r?.Info ?? "no result";
				if (!_lastFailed || text != _lastFailureInfo)
				{
					GpsMod.Log.Warning("Route FAILED (" + reason + "): " + text);
				}
				_lastFailed = true;
				_lastFailureInfo = text;
				return;
			}
			if ((reason == "interval" || reason.StartsWith("interval ")) && _renderer.HasRoute && !_lastFailed)
			{
				float num = _renderer.RemainingLength();
				float num2 = r.Length();
				bool num3 = num2 < num - Mathf.Max(25f, num * 0.1f);
				bool flag = !r.Complete && _currentComplete;
				if (!num3 || flag)
				{
					GpsMod.Verbose($"Kept current route ({num:F0}m left); candidate {num2:F0}m [{r.Mode}] wasn't clearly better.");
					return;
				}
				GpsMod.Verbose($"Switched to a shorter route: {num2:F0}m vs {num:F0}m left.");
			}
			bool lastFailed = _lastFailed;
			_lastFailed = false;
			_lastFailureInfo = null;
			_currentComplete = r.Complete;
			_roadFallbackLogged = r.Mode != RouteMode.Drive && _roadFallbackLogged;
			_lastRoutePoints = r.Points;
			_renderer.SetRoute(r.Points, _dest);
			_map.DrawRoute(r.Points, _dest);
			string text2 = $"Route found [{r.Mode}] ({reason}): {r.Points.Count} nodes, {r.Length():F0}m, {_renderer.DenseCount} line points, {r.Millis:F1}ms - {r.Info}";
			if (!_loggedFirstRoute || lastFailed || !r.Complete)
			{
				_loggedFirstRoute = true;
				GpsMod.Log.Msg(text2);
				return;
			}
			GpsMod.Verbose($"#{_recalcCount} " + text2);
		}

		private void EnsureDestObject()
		{
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: Expected O, but got Unknown
			if (!((Object)(object)_destObject != (Object)null))
			{
				_destObject = new GameObject("GPS_Destination");
				_destObject.transform.SetParent(_host.transform, false);
			}
		}

		private RectTransform GetCompassTemplate()
		{
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Expected O, but got Unknown
			//IL_0043: 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_0067: 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_0096: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)_compassTemplate != (Object)null)
			{
				return _compassTemplate;
			}
			GameObject val = new GameObject("GPS_CompassTemplateHolder");
			val.transform.SetParent(_host.transform, false);
			val.SetActive(false);
			GameObject val2 = new GameObject("GPS_CompassIcon");
			RectTransform val3 = val2.AddComponent<RectTransform>();
			((Transform)val3).SetParent(val.transform, false);
			val3.sizeDelta = new Vector2(16f, 16f);
			((Transform)val3).localRotation = Quaternion.Euler(0f, 0f, 45f);
			Image obj = val2.AddComponent<Image>();
			((Graphic)obj).color = GpsMod.Cfg.ParseLineColor();
			((Graphic)obj).raycastTarget = false;
			_compassTemplate = val3;
			return val3;
		}

		private void AddCompassMarker()
		{
			if (!GpsMod.Cfg.ShowOnCompass.Value || _compassFailed || _compassElement != null)
			{
				return;
			}
			try
			{
				if (Singleton<CompassManager>.InstanceExists)
				{
					_compassElement = Singleton<CompassManager>.Instance.AddElement(_destObject.transform, GetCompassTemplate(), true);
				}
			}
			catch (Exception ex)
			{
				_compassFailed = true;
				GpsMod.Log.Warning("Compass marker disabled (AddElement failed): " + ex.Message);
			}
		}

		private void RemoveCompassMarker()
		{
			if (_compassElement == null)
			{
				return;
			}
			try
			{
				if (Singleton<CompassManager>.InstanceExists)
				{
					Singleton<CompassManager>.Instance.RemoveElement(_compassElement, true);
				}
			}
			catch (Exception ex)
			{
				GpsMod.Verbose("Compass RemoveElement failed: " + ex.Message);
			}
			_compassElement = null;
		}

		public void Destroy()
		{
			GpsMod.Cfg.Changed -= OnSettingsChanged;
			ClearRoute(null);
			_renderer.Destroy();
			_map.Destroy();
			_hud.Destroy();
			if (Instance == this)
			{
				Instance = null;
			}
		}
	}
	internal class GpsHud
	{
		private readonly GameObject _root;

		private Text _text;

		private bool _fontResolved;

		public GpsHud(Transform parent)
		{
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Expected O, but got Unknown
			//IL_005e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0077: Unknown result type (might be due to invalid IL or missing references)
			//IL_007d: Expected O, but got Unknown
			//IL_00a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ae: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bf: 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_00e8: Unknown result type (might be due to invalid IL or missing references)
			//IL_014a: Unknown result type (might be due to invalid IL or missing references)
			//IL_015e: Unknown result type (might be due to invalid IL or missing references)
			_root = new GameObject("GPS_Hud");
			_root.transform.SetParent(parent, false);
			Canvas obj = _root.AddComponent<Canvas>();
			obj.renderMode = (RenderMode)0;
			obj.sortingOrder = 40;
			CanvasScaler obj2 = _root.AddComponent<CanvasScaler>();
			obj2.uiScaleMode = (ScaleMode)1;
			obj2.referenceResolution = new Vector2(1920f, 1080f);
			obj2.matchWidthOrHeight = 0.5f;
			GameObject val = new GameObject("GPS_HudText");
			RectTransform obj3 = val.AddComponent<RectTransform>();
			((Transform)obj3).SetParent(_root.transform, false);
			Vector2 val2 = default(Vector2);
			((Vector2)(ref val2))..ctor(0.5f, 1f);
			obj3.anchorMax = val2;
			obj3.anchorMin = val2;
			obj3.pivot = new Vector2(0.5f, 1f);
			obj3.anchoredPosition = new Vector2(0f, -95f);
			obj3.sizeDelta = new Vector2(700f, 44f);
			_text = val.AddComponent<Text>();
			_text.alignment = (TextAnchor)4;
			_text.fontSize = 26;
			((Graphic)_text).raycastTarget = false;
			_text.horizontalOverflow = (HorizontalWrapMode)1;
			Shadow obj4 = val.AddComponent<Shadow>();
			obj4.effectColor = new Color(0f, 0f, 0f, 0.85f);
			obj4.effectDistance = new Vector2(2f, -2f);
			_root.SetActive(false);
		}

		private void ResolveFont()
		{
			if (_fontResolved)
			{
				return;
			}
			_fontResolved = true;
			try
			{
				foreach (Text item in Object.FindObjectsOfType<Text>())
				{
					if ((Object)(object)item != (Object)null && (Object)(object)item != (Object)(object)_text && (Object)(object)item.font != (Object)null)
					{
						_text.font = item.font;
						return;
					}
				}
			}
			catch (Exception ex)
			{
				GpsMod.Verbose("HUD font lookup failed: " + ex.Message);
			}
			try
			{
				_text.font = Resources.GetBuiltinResource<Font>("LegacyRuntime.ttf");
			}
			catch
			{
			}
		}

		public void Show(string text, Color color)
		{
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_0046: Unknown result type (might be due to invalid IL or missing references)
			//IL_005b: 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)
			ResolveFont();
			if (!_root.activeSelf)
			{
				_root.SetActive(true);
			}
			_text.text = text;
			((Graphic)_text).color = new Color(Mathf.Lerp(color.r, 1f, 0.25f), Mathf.Lerp(color.g, 1f, 0.25f), Mathf.Lerp(color.b, 1f, 0.25f), 1f);
		}

		public void Hide()
		{
			if (_root.activeSelf)
			{
				_root.SetActive(false);
			}
		}

		public void Destroy()
		{
			if ((Object)(object)_root != (Object)null)
			{
				Object.Destroy((Object)(object)_root);
			}
		}

		public static string FormatDistance(float meters)
		{
			if (meters >= 1000f)
			{
				return $"{meters / 1000f:0.0} km";
			}
			return $"{Mathf.Round(meters / 5f) * 5f:0} m";
		}

		public static string FormatEta(float seconds)
		{
			if (float.IsNaN(seconds) || float.IsInfinity(seconds))
			{
				return "--";
			}
			if (seconds < 60f)
			{
				return "<1 min";
			}
			int num = Mathf.RoundToInt(seconds / 60f);
			if (num < 60)
			{
				return $"{num} min";
			}
			return $"{num / 60}h {num % 60:00}m";
		}
	}
	internal static class GpsIcon
	{
		private static Sprite s_sprite;

		public static Sprite Get()
		{
			//IL_00aa: 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_00ae: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_0134: Unknown result type (might be due to invalid IL or missing references)
			//IL_0136: Unknown result type (might be due to invalid IL or missing references)
			//IL_013d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0147: Unknown result type (might be due to invalid IL or missing references)
			//IL_0153: Unknown result type (might be due to invalid IL or missing references)
			//IL_015a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0160: Unknown result type (might be due to invalid IL or missing references)
			//IL_0162: Unknown result type (might be due to invalid IL or missing references)
			//IL_0186: Unknown result type (might be due to invalid IL or missing references)
			//IL_0190: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a7: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b1: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c4: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c9: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d7: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e3: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e9: Unknown result type (might be due to invalid IL or missing references)
			//IL_0205: Unknown result type (might be due to invalid IL or missing references)
			//IL_0214: Unknown result type (might be due to invalid IL or missing references)
			//IL_021e: Expected O, but got Unknown
			if ((Object)(object)s_sprite != (Object)null)
			{
				return s_sprite;
			}
			Color32[] array = (Color32[])(object)new Color32[16384];
			Color32 val = default(Color32);
			((Color32)(ref val))..ctor((byte)22, (byte)30, (byte)38, byte.MaxValue);
			Color32 val2 = default(Color32);
			((Color32)(ref val2))..ctor((byte)32, (byte)52, (byte)48, byte.MaxValue);
			Color32 col = default(Color32);
			((Color32)(ref col))..ctor((byte)0, (byte)229, byte.MaxValue, byte.MaxValue);
			Color32 col2 = default(Color32);
			((Color32)(ref col2))..ctor(byte.MaxValue, (byte)70, (byte)90, byte.MaxValue);
			Color32 col3 = default(Color32);
			((Color32)(ref col3))..ctor(byte.MaxValue, byte.MaxValue, byte.MaxValue, byte.MaxValue);
			for (int i = 0; i < 128; i++)
			{
				for (int j = 0; j < 128; j++)
				{
					float num = (float)i / 128f;
					array[i * 128 + j] = Color32.Lerp(val, val2, num);
				}
			}
			Vector2 val3 = default(Vector2);
			((Vector2)(ref val3))..ctor(22f, 18f);
			Vector2 val4 = default(Vector2);
			for (int k = 1; k <= 200; k++)
			{
				float num2 = (float)k / 200f;
				((Vector2)(ref val4))..ctor(22f + 62f * num2 + 18f * Mathf.Sin(num2 * 7.5f), 18f + 70f * num2);
				Stamp(array, 128, Vector2.Lerp(val3, val4, 0.5f), 6.5f, col);
				Stamp(array, 128, val4, 6.5f, col);
				val3 = val4;
			}
			Stamp(array, 128, new Vector2(86f, 96f), 17f, col2);
			Stamp(array, 128, new Vector2(86f, 96f), 7f, col3);
			Texture2D val5 = new Texture2D(128, 128, (TextureFormat)4, false)
			{
				filterMode = (FilterMode)1,
				wrapMode = (TextureWrapMode)1
			};
			val5.SetPixels32(new Il2CppStructArray<Color32>(array));
			val5.Apply();
			((Object)val5).hideFlags = (HideFlags)32;
			s_sprite = Sprite.Create(val5, new Rect(0f, 0f, 128f, 128f), new Vector2(0.5f, 0.5f));
			((Object)s_sprite).hideFlags = (HideFlags)32;
			return s_sprite;
		}

		private static void Stamp(Color32[] px, int n, Vector2 c, float r, Color32 col)
		{
			//IL_0001: 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_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0046: Unknown result type (might be due to invalid IL or missing references)
			//IL_0074: 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_00a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ae: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b7: Unknown result type (might be due to invalid IL or missing references)
			int num = Mathf.Max(0, (int)(c.x - r - 1f));
			int num2 = Mathf.Min(n - 1, (int)(c.x + r + 1f));
			int num3 = Mathf.Max(0, (int)(c.y - r - 1f));
			int num4 = Mathf.Min(n - 1, (int)(c.y + r + 1f));
			for (int i = num3; i <= num4; i++)
			{
				for (int j = num; j <= num2; j++)
				{
					float num5 = Vector2.Distance(new Vector2((float)j + 0.5f, (float)i + 0.5f), c);
					float num6 = Mathf.Clamp01(r - num5 + 0.5f);
					if (!(num6 <= 0f))
					{
						int num7 = i * n + j;
						px[num7] = Color32.Lerp(px[num7], col, num6);
					}
				}
			}
		}
	}
	public class GpsMod : MelonMod
	{
		internal static Instance Log;

		internal static GpsConfig Cfg;

		public override void OnInitializeMelon()
		{
			Log = ((MelonBase)this).LoggerInstance;
			Cfg = new GpsConfig();
			ClassInjector.RegisterTypeInIl2Cpp<GpsController>();
			Log.Msg("Froggos-GPS loaded. Open the phone Map app and left-click a spot to set a destination. Clear with [" + Cfg.ClearKey.Value + "] or right-click the map.");
			Log.Msg(IsS1ApiLoaded() ? "S1API found: the 'GPS' phone app (settings + places) will be added to the phone." : "S1API not installed: no GPS phone app; edit settings in UserData/MelonPreferences.cfg instead.");
		}

		public override void OnLateInitializeMelon()
		{
			MinimapBridge.TryPatch(((MelonBase)this).HarmonyInstance);
		}

		internal static bool IsS1ApiLoaded()
		{
			Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies();
			for (int i = 0; i < assemblies.Length; i++)
			{
				if (assemblies[i].GetName().Name == "S1API.Il2Cpp.MelonLoader")
				{
					return true;
				}
			}
			return false;
		}

		public override void OnSceneWasInitialized(int buildIndex, string sceneName)
		{
			Log.Msg($"Scene initialized: '{sceneName}' (index {buildIndex})");
			if (!(sceneName == "Menu"))
			{
				GpsController.EnsureCreated();
			}
		}

		internal static void Verbose(string msg)
		{
			if (Cfg != null && Cfg.VerboseLogging.Value)
			{
				Log.Msg("[verbose] " + msg);
			}
		}
	}
	[HarmonyPatch(typeof(MapApp), "SetOpen")]
	internal static class MapAppSetOpenPatch
	{
		private static void Postfix(MapApp __instance, bool open)
		{
			try
			{
				MapOverlay.OnMapAppSetOpen(__instance, open);
				if (open)
				{
					GpsCore.Instance?.OnMapOpened();
				}
			}
			catch (Exception ex)
			{
				GpsMod.Log.Error("MapApp.SetOpen postfix failed: " + ex);
			}
		}
	}
	public class GpsPhoneApp : PhoneApp
	{
		private sealed class Destination
		{
			public string Name;

			public string Kind;

			public Transform Follow;

			public Vector3 Fixed;

			public Vector3 Position
			{
				get
				{
					//IL_001b: Unknown result type (might be due to invalid IL or missing references)
					//IL_000f: Unknown result type (might be due to invalid IL or missing references)
					if (!((Object)(object)Follow != (Object)null))
					{
						return Fixed;
					}
					return Follow.position;
				}
			}
		}

		private static readonly Color BgColor = new Color(0.07f, 0.08f, 0.1f, 1f);

		private static readonly Color RowColor = new Color(1f, 1f, 1f, 0.04f);

		private static readonly Color ButtonColor = new Color(0.2f, 0.23f, 0.28f, 1f);

		private static readonly Color OnColor = new Color(0.16f, 0.62f, 0.36f, 1f);

		private static readonly Color OffColor = new Color(0.33f, 0.33f, 0.36f, 1f);

		private static readonly Color DangerColor = new Color(0.72f, 0.24f, 0.26f, 1f);

		private static readonly Color MutedText = new Color(0.72f, 0.75f, 0.8f, 1f);

		private static readonly (string Name, string Hex)[] Palette = new(string, string)[9]
		{
			("Cyan", "#00E5FF"),
			("Green", "#39FF14"),
			("Yellow", "#FFE600"),
			("Orange", "#FF8C00"),
			("Red", "#FF3B3B"),
			("Pink", "#FF4FD8"),
			("Purple", "#9D5CFF"),
			("Blue", "#2F7BFF"),
			("White", "#FFFFFF")
		};

		private static readonly float[] RefreshSteps = new float[7] { 0.25f, 0.5f, 1f, 1.5f, 2f, 3f, 5f };

		private static readonly float[] OpacitySteps = new float[10] { 0.1f, 0.2f, 0.3f, 0.4f, 0.5f, 0.6f, 0.7f, 0.8f, 0.9f, 1f };

		private static readonly float[] WidthSteps = new float[8] { 0.25f, 0.4f, 0.6f, 0.8f, 1f, 1.3f, 1.7f, 2.2f };

		private static readonly float[] MapWidthSteps = new float[6] { 3f, 4f, 6f, 8f, 10f, 14f };

		private static readonly float[] DrawDistSteps = new float[5] { 150f, 300f, 600f, 1000f, 2000f };

		private RectTransform _list;

		private Text _statusTitle;

		private Text _statusDetail;

		private GameObject _placesBox;

		private readonly List<Action> _refreshers = new List<Action>();

		private bool _wasOpen;

		private float _nextStatus;

		private RectTransform _frame;

		private RectTransform _container;

		private bool _fitted;

		private const float K = 1.6f;

		private readonly List<Destination> _destinations = new List<Destination>();

		private string _query = "";

		private bool _placesExpanded;

		private Text _placesToggleLabel;

		private const int MaxNearby = 20;

		private const int MaxResults = 30;

		protected override string AppName => "FroggosGPS";

		protected override string AppTitle => "Froggos GPS";

		protected override string IconLabel => "GPS";

		protected override string IconFileName => "FroggosGPS.png";

		protected override Sprite IconSprite => GpsIcon.Get();

		protected override EOrientation Orientation => (EOrientation)1;

		protected override void OnCreatedUI(GameObject container)
		{
			//IL_0034: 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_00bd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e0: Unknown result type (might be due to invalid IL or missing references)
			//IL_0138: Unknown result type (might be due to invalid IL or missing references)
			//IL_0147: Unknown result type (might be due to invalid IL or missing references)
			//IL_015b: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ae: Unknown result type (might be due to invalid IL or missing references)
			//IL_01cd: Unknown result type (might be due to invalid IL or missing references)
			//IL_0201: Unknown result type (might be due to invalid IL or missing references)
			//IL_023c: Unknown result type (might be due to invalid IL or missing references)
			//IL_029c: Unknown result type (might be due to invalid IL or missing references)
			//IL_02c8: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ea: Unknown result type (might be due to invalid IL or missing references)
			//IL_02f4: Expected O, but got Unknown
			//IL_0312: Unknown result type (might be due to invalid IL or missing references)
			//IL_031c: Expected O, but got Unknown
			//IL_0514: Unknown result type (might be due to invalid IL or missing references)
			_refreshers.Clear();
			GpsCore.UiTick = Tick;
			UIFactory.Panel("GPS_Backdrop", container.transform, BgColor, (Vector2?)null, (Vector2?)null, true);
			GameObject val = UIFactory.Panel("GPS_Bg", container.transform, BgColor, (Vector2?)null, (Vector2?)null, true);
			_frame = val.GetComponent<RectTransform>();
			_container = container.GetComponent<RectTransform>();
			_fitted = false;
			GameObject val2 = UIFactory.Panel("GPS_Header", val.transform, new Color(0.1f, 0.13f, 0.16f, 1f), (Vector2?)new Vector2(0f, 0.895f), (Vector2?)new Vector2(1f, 0.97f), false);
			Stretch(((Graphic)MakeText("GPS_Title", "Froggos GPS", val2.transform, 28, (TextAnchor)3, (FontStyle)1)).rectTransform, 24f);
			GameObject val3 = UIFactory.Panel("GPS_Body", val.transform, new Color(0f, 0f, 0f, 0f), (Vector2?)new Vector2(0f, 0.005f), (Vector2?)new Vector2(1f, 0.89f), false);
			ScrollRect scroll = default(ScrollRect);
			_list = UIFactory.ScrollableVerticalList("GPS_List", val3.transform, ref scroll);
			FitListToViewport(scroll);
			SetupScrolling(scroll, val3.GetComponent<RectTransform>());
			Section("ROUTE");
			_statusTitle = Label("No destination", 22, (FontStyle)1, Color.white, 34f);
			_statusDetail = Label("Open the Map app and left-click anywhere, or pick a place below.", 17, (FontStyle)0, MutedText, 48f);
			GameObject val4 = Row("GPS_RouteActions", 56f);
			Button("Clear route", val4.transform, DangerColor, 0f, delegate
			{
				GpsCore.Instance?.ClearRoute("phone app");
			});
			Button("Re-route", val4.transform, ButtonColor, 0f, delegate
			{
				GpsCore.Instance?.Reroute();
			});
			Section("DESTINATIONS");
			SearchRow();
			GameObject val5 = Row("GPS_PlacesActions", 56f);
			_placesToggleLabel = Button("Show nearby", val5.transform, ButtonColor, 0f, delegate
			{
				_placesExpanded = !_placesExpanded;
				RenderPlaces();
			});
			Button("Refresh", val5.transform, ButtonColor, 130f, delegate
			{
				CollectDestinations();
				RenderPlaces();
			});
			_placesBox = new GameObject("GPS_Places");
			((Transform)_placesBox.AddComponent<RectTransform>()).SetParent((Transform)(object)_list, false);
			UIFactory.VerticalLayoutOnGO(_placesBox, 6, new RectOffset());
			_placesBox.AddComponent<ContentSizeFitter>().verticalFit = (FitMode)2;
			GpsConfig cfg = GpsMod.Cfg;
			Section("LOOK");
			ColorRow();
			Stepper("Transparency", () => $"{Mathf.RoundToInt(cfg.LineOpacity.Value * 100f)}% solid", delegate(int d)
			{
				cfg.Set(cfg.LineOpacity, Step(OpacitySteps, cfg.LineOpacity.Value, d));
			});
			Stepper("Line width", () => $"{cfg.LineWidth.Value:0.##} m", delegate(int d)
			{
				cfg.Set(cfg.LineWidth, Step(WidthSteps, cfg.LineWidth.Value, d));
			});
			Stepper("Draw distance", () => $"{cfg.MaxDrawDistance.Value:0} m", delegate(int d)
			{
				cfg.Set(cfg.MaxDrawDistance, Step(DrawDistSteps, cfg.MaxDrawDistance.Value, d));
			});
			Toggle("Destination beam", cfg.ShowBeacon);
			Toggle("Flat on the ground", cfg.FlatLine);
			Toggle("See through walls", cfg.DrawThroughWalls);
			Section("MAP & HUD");
			Toggle("Show route on phone map", cfg.ShowOnMap);
			Stepper("Map line width", () => $"{cfg.MapLineWidthMeters.Value:0} m", delegate(int d)
			{
				cfg.Set(cfg.MapLineWidthMeters, Step(MapWidthSteps, cfg.MapLineWidthMeters.Value, d));
			});
			if (MinimapBridge.Available)
			{
				Toggle("Show on minimap (MultiMiniMap)", cfg.ShowOnMinimap);
			}
			Toggle("Distance / ETA on screen", cfg.ShowHud);
			Toggle("Compass marker", cfg.ShowOnCompass);
			Toggle("Arrival notification", cfg.NotifyOnArrival);
			Section("ROUTING");
			Stepper("Refresh rate", () => $"every {cfg.RecalcInterval.Value:0.##} s", delegate(int d)
			{
				cfg.Set(cfg.RecalcInterval, Step(RefreshSteps, cfg.RecalcInterval.Value, d));
			});
			Toggle("Quickest by road (always)", cfg.RoadNetworkAlways);
			Toggle("Fallback: roads & paths only", cfg.RoadsAndPathsOnly);
			Label("Clear route: [" + cfg.ClearKey.Value + "] or right-click the map. Settings save automatically.", 16, (FontStyle)2, MutedText, 40f);
			CollectDestinations();
			RenderPlaces();
			RefreshAll();
			GpsMod.Log.Msg("GPS phone app created.");
		}

		protected override void OnDestroyed()
		{
			if (GpsCore.UiTick == new Action(Tick))
			{
				GpsCore.UiTick = null;
			}
		}

		private void Tick()
		{
			bool flag;
			try
			{
				flag = ((PhoneApp)this).IsOpen();
			}
			catch
			{
				return;
			}
			if (!flag)
			{
				_wasOpen = false;
				return;
			}
			if (!_wasOpen)
			{
				_wasOpen = true;
				if (!_fitted)
				{
					FitToScreen();
				}
				CollectDestinations();
				RenderPlaces();
				RefreshAll();
			}
			if (Time.unscaledTime >= _nextStatus)
			{
				_nextStatus = Time.unscaledTime + 0.5f;
				RefreshStatus();
			}
		}

		private void FitToScreen()
		{
			//IL_0101: Unknown result type (might be due to invalid IL or missing references)
			//IL_0106: Unknown result type (might be due to invalid IL or missing references)
			//IL_010b: 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_011a: Unknown result type (might be due to invalid IL or missing references)
			//IL_011f: 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)
			//IL_012c: Unknown result type (might be due to invalid IL or missing references)
			//IL_012e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0135: Unknown result type (might be due to invalid IL or missing references)
			//IL_0169: Unknown result type (might be due to invalid IL or missing references)
			//IL_0170: Unknown result type (might be due to invalid IL or missing references)
			//IL_0196: Unknown result type (might be due to invalid IL or missing references)
			//IL_019d: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d1: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d8: Unknown result type (might be due to invalid IL or missing references)
			//IL_0238: Unknown result type (might be due to invalid IL or missing references)
			//IL_024e: Unknown result type (might be due to invalid IL or missing references)
			_fitted = true;
			if ((Object)(object)_frame == (Object)null || (Object)(object)_container == (Object)null)
			{
				return;
			}
			try
			{
				RectTransform val = null;
				string text = "";
				Transform parent = ((Transform)_container).parent;
				while ((Object)(object)parent != (Object)null && (Object)(object)val == (Object)null)
				{
					if ((Object)(object)((Component)parent).GetComponent<RectMask2D>() != (Object)null)
					{
						val = ((Il2CppObjectBase)parent).TryCast<RectTransform>();
						text = "RectMask2D";
					}
					else if ((Object)(object)((Component)parent).GetComponent<Mask>() != (Object)null)
					{
						val = ((Il2CppObjectBase)parent).TryCast<RectTransform>();
						text = "Mask";
					}
					else if ((Object)(object)((Component)parent).GetComponent<Canvas>() != (Object)null && ((Component)parent).GetComponent<Canvas>().isRootCanvas)
					{
						break;
					}
					parent = parent.parent;
				}
				if ((Object)(object)val == (Object)null)
				{
					Canvas componentInParent = ((Component)_container).GetComponentInParent<Canvas>();
					if ((Object)(object)componentInParent != (Object)null)
					{
						val = ((Component)componentInParent.rootCanvas).GetComponent<RectTransform>();
						text = "root canvas";
					}
				}
				if (!((Object)(object)val == (Object)null))
				{
					Il2CppStructArray<Vector3> val2 = new Il2CppStructArray<Vector3>(4L);
					val.GetWorldCorners(val2);
					Vector3 val3 = ((Transform)_container).InverseTransformPoint(((Il2CppArrayBase<Vector3>)(object)val2)[0]);
					Vector3 val4 = ((Transform)_container).InverseTransformPoint(((Il2CppArrayBase<Vector3>)(object)val2)[2]);
					Rect rect = _container.rect;
					float num = Mathf.Clamp(Mathf.Min(val3.x, val4.x) - ((Rect)(ref rect)).xMin, 0f, ((Rect)(ref rect)).width * 0.4f);
					float num2 = Mathf.Clamp(((Rect)(ref rect)).xMax - Mathf.Max(val3.x, val4.x), 0f, ((Rect)(ref rect)).width * 0.4f);
					float num3 = Mathf.Clamp(Mathf.Min(val3.y, val4.y) - ((Rect)(ref rect)).yMin, 0f, ((Rect)(ref rect)).height * 0.4f);
					float num4 = Mathf.Clamp(((Rect)(ref rect)).yMax - Mathf.Max(val3.y, val4.y), 0f, ((Rect)(ref rect)).height * 0.4f);
					if (num < 1f && num2 < 1f)
					{
						num = (num2 = ((Rect)(ref rect)).width * 0.06f);
						text += " (no overlap found, default side inset)";
					}
					_frame.offsetMin = new Vector2(num, num3);
					_frame.offsetMax = new Vector2(0f - num2, 0f - num4);
					GpsMod.Log.Msg($"GPS app fitted to {text} '{((Object)val).name}': container {((Rect)(ref rect)).width:0}x{((Rect)(ref rect)).height:0}, inset L{num:0} R{num2:0} B{num3:0} T{num4:0}.");
					LogLayout();
				}
			}
			catch (Exception ex)
			{
				GpsMod.Log.Warning("GPS app screen fit failed: " + ex.Message);
			}
		}

		private void LogLayout()
		{
			//IL_0161: Unknown result type (might be due to invalid IL or missing references)
			//IL_0166: Unknown result type (might be due to invalid IL or missing references)
			//IL_016a: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bf: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c4: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				if ((Object)(object)_list == (Object)null)
				{
					return;
				}
				StringBuilder stringBuilder = new StringBuilder("GPS app layout: ");
				Transform val = (Transform)(object)_list;
				int num = 0;
				StringBuilder stringBuilder2;
				StringBuilder.AppendInterpolatedStringHandler handler;
				while (num < 4 && (Object)(object)val != (Object)null && (Object)(object)val != (Object)(object)_container)
				{
					RectTransform val2 = ((Il2CppObjectBase)val).TryCast<RectTransform>();
					string value = (((Object)(object)((Component)val).GetComponent<Mask>() != (Object)null) ? " Mask" : "") + (((Object)(object)((Component)val).GetComponent<RectMask2D>() != (Object)null) ? " RectMask2D" : "");
					stringBuilder2 = stringBuilder;
					StringBuilder stringBuilder3 = stringBuilder2;
					handler = new StringBuilder.AppendInterpolatedStringHandler(7, 3, stringBuilder2);
					handler.AppendLiteral("'");
					handler.AppendFormatted(((Object)val).name);
					handler.AppendLiteral("' ");
					object value2;
					if (!((Object)(object)val2 != (Object)null))
					{
						value2 = "?";
					}
					else
					{
						Rect rect = val2.rect;
						value2 = ((object)((Rect)(ref rect)).size/*cast due to .constrained prefix*/).ToString();
					}
					handler.AppendFormatted((string?)value2);
					handler.AppendFormatted(value);
					handler.AppendLiteral(" <- ");
					stringBuilder3.Append(ref handler);
					num++;
					val = val.parent;
				}
				stringBuilder2 = stringBuilder;
				StringBuilder stringBuilder4 = stringBuilder2;
				handler = new StringBuilder.AppendInterpolatedStringHandler(16, 2, stringBuilder2);
				handler.AppendLiteral("rows=");
				handler.AppendFormatted(((Transform)_list).childCount);
				handler.AppendLiteral(", rotation=");
				Quaternion rotation = ((Transform)_container).rotation;
				handler.AppendFormatted<Vector3>(((Quaternion)(ref rotation)).eulerAngles);
				stringBuilder4.Append(ref handler);
				GpsMod.Log.Msg(stringBuilder.ToString());
			}
			catch (Exception ex)
			{
				GpsMod.Verbose("Layout log failed: " + ex.Message);
			}
		}

		private void RefreshAll()
		{
			foreach (Action refresher in _refreshers)
			{
				try
				{
					refresher();
				}
				catch (Exception ex)
				{
					GpsMod.Verbose("App refresh failed: " + ex.Message);
				}
			}
			RefreshStatus();
		}

		private void RefreshStatus()
		{
			if ((Object)(object)_statusTitle == (Object)null)
			{
				return;
			}
			GpsCore instance = GpsCore.Instance;
			if (instance == null || !instance.HasDestination)
			{
				_statusTitle.text = "No destination";
				_statusDetail.text = "Open the Map app and left-click anywhere, or pick a place below.";
				return;
			}
			_statusTitle.text = (string.IsNullOrEmpty(instance.DestinationLabel) ? "Map pin" : instance.DestinationLabel);
			if (instance.RouteFailed && instance.RemainingMeters <= 0f)
			{
				_statusDetail.text = "No route found yet - retrying...";
				return;
			}
			string value = ((instance.CurrentMode == RouteMode.Drive) ? "Road network" : "Roads & paths");
			_statusDetail.text = $"{GpsHud.FormatDistance(instance.RemainingMeters)}  ·  ETA {GpsHud.FormatEta(instance.EtaSeconds)}  ·  {value}";
		}

		private void CollectDestinations()
		{
			//IL_0027: 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_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0148: Unknown result type (might be due to invalid IL or missing references)
			//IL_014d: Unknown result type (might be due to invalid IL or missing references)
			//IL_017f: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a5: Unknown result type (might be due to invalid IL or missing references)
			//IL_0158: Unknown result type (might be due to invalid IL or missing references)
			//IL_0159: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f1: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f3: Unknown result type (might be due to invalid IL or missing references)
			_destinations.Clear();
			Player local = Player.Local;
			Vector3 a = (((Object)(object)local != (Object)null) ? ((Component)local).transform.position : Vector3.zero);
			try
			{
				if ((Object)(object)local != (Object)null && (Object)(object)local.LastDrivenVehicle != (Object)null && !local.IsInVehicle)
				{
					_destinations.Add(new Destination
					{
						Name = "Your vehicle",
						Kind = "vehicle",
						Follow = ((Component)local.LastDrivenVehicle).transform
					});
				}
			}
			catch (Exception ex)
			{
				GpsMod.Verbose("Vehicle destination failed: " + ex.Message);
			}
			HashSet<string> hashSet = new HashSet<string>();
			try
			{
				foreach (POI item2 in Object.FindObjectsOfType<POI>())
				{
					if ((Object)(object)item2 == (Object)null || !((Component)item2).gameObject.activeInHierarchy)
					{
						continue;
					}
					string text = item2.MainText;
					if (string.IsNullOrWhiteSpace(text))
					{
						text = item2.DefaultMainText;
					}
					if (string.IsNullOrWhiteSpace(text))
					{
						continue;
					}
					text = text.Replace("\n", " ").Trim();
					if (text.IndexOf("Main Text", StringComparison.OrdinalIgnoreCase) >= 0 || text.Equals("Text", StringComparison.OrdinalIgnoreCase))
					{
						continue;
					}
					Vector3 position = ((Component)item2).transform.position;
					if (!((Object)(object)local != (Object)null) || !(RoutePlanner.HorizontalDistance(a, position) < 2f))
					{
						string item = text + "@" + Mathf.RoundToInt(position.x / 10f) + "," + Mathf.RoundToInt(position.z / 10f);
						if (hashSet.Add(item))
						{
							_destinations.Add(new Destination
							{
								Name = text,
								Kind = "place",
								Fixed = position
							});
						}
					}
				}
			}
			catch (Exception ex2)
			{
				GpsMod.Verbose("POI destinations failed: " + ex2.Message);
			}
			int num = 0;
			try
			{
				List<NPC> nPCRegistry = NPCManager.NPCRegistry;
				if (nPCRegistry != null)
				{
					for (int i = 0; i < nPCRegistry.Count; i++)
					{
						NPC val = nPCRegistry[i];
						if (!((Object)(object)val == (Object)null))
						{
							string fullName = val.FullName;
							if (!string.IsNullOrWhiteSpace(fullName))
							{
								Transform follow = (((Object)(object)val.Movement != (Object)null) ? ((Component)val.Movement).transform : ((Component)val).transform);
								_destinations.Add(new Destination
								{
									Name = fullName.Trim(),
									Kind = "person",
									Follow = follow
								});
								num++;
							}
						}
					}
				}
			}
			catch (Exception ex3)
			{
				GpsMod.Verbose("NPC destinations failed: " + ex3.Message);
			}
			GpsMod.Verbose($"Destinations collected: {_destinations.Count} ({num} people).");
		}

		private void RenderPlaces()
		{
			//IL_00c4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c9: Unknown result type (might be due to invalid IL or missing references)
			//IL_0139: Unknown result type (might be due to invalid IL or missing references)
			//IL_013e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0149: Unknown result type (might be due to invalid IL or missing references)
			//IL_014a: Unknown result type (might be due to invalid IL or missing references)
			//IL_027f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0219: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)_placesBox == (Object)null)
			{
				return;
			}
			UIFactory.ClearChildren(_placesBox.transform);
			bool flag = !string.IsNullOrWhiteSpace(_query);
			if ((Object)(object)_placesToggleLabel != (Object)null)
			{
				_placesToggleLabel.text = (_placesExpanded ? "Hide nearby" : $"Show nearby ({_destinations.Count})");
			}
			if (!flag && !_placesExpanded)
			{
				UIFactory.FitContentHeight(_list);
				return;
			}
			Player local = Player.Local;
			Vector3 a = (((Object)(object)local != (Object)null) ? ((Component)local).transform.position : Vector3.zero);
			string text = (flag ? _query.Trim() : null);
			List<(Destination, float)> list = new List<(Destination, float)>();
			foreach (Destination destination in _destinations)
			{
				if ((text == null || destination.Name.IndexOf(text, StringComparison.OrdinalIgnoreCase) >= 0 || destination.Kind.IndexOf(text, StringComparison.OrdinalIgnoreCase) >= 0) && (text != null || !(destination.Kind == "person")))
				{
					Vector3 position;
					try
					{
						position = destination.Position;
					}
					catch
					{
						continue;
					}
					list.Add((destination, RoutePlanner.HorizontalDistance(a, position)));
				}
			}
			list.Sort(((Destination D, float Dist) tuple, (Destination D, float Dist) b) => tuple.Dist.CompareTo(b.Dist));
			int num = (flag ? 30 : 20);
			int num2 = 0;
			foreach (var item in list)
			{
				if (num2 >= num)
				{
					break;
				}
				PlaceRow(item.Item1, item.Item2);
				num2++;
			}
			if (num2 == 0)
			{
				Label(flag ? ("Nothing matches \"" + text + "\".") : "No places found. Map markers show up here.", 17, (FontStyle)2, MutedText, 34f, _placesBox.transform);
			}
			else if (list.Count > num2)
			{
				Label($"+{list.Count - num2} more - refine your search.", 15, (FontStyle)2, MutedText, 28f, _placesBox.transform);
			}
			UIFactory.FitContentHeight(_list);
		}

		private void PlaceRow(Destination d, float dist)
		{
			//IL_00a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d1: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = Row("GPS_Place", 58f, _placesBox.transform);
			string text = ((d.Kind == "person") ? "  (person)" : "");
			Flexible(((Component)MakeText("Name", d.Name + text, val.transform, 17, (TextAnchor)3, (FontStyle)0)).gameObject, 1f, 52f);
			Text obj = MakeText("Dist", GpsHud.FormatDistance(dist), val.transform, 16, (TextAnchor)5, (FontStyle)0);
			((Graphic)obj).color = MutedText;
			Fixed(((Component)obj).gameObject, 70f, 44f);
			Button("Go", val.transform, OnColor, 64f, delegate
			{
				//IL_0043: Unknown result type (might be due to invalid IL or missing references)
				GpsCore instance = GpsCore.Instance;
				if (instance != null)
				{
					if ((Object)(object)d.Follow != (Object)null)
					{
						instance.SetDestinationFollow(d.Follow, d.Name);
					}
					else
					{
						instance.SetDestinationWorld(d.Fixed, d.Name);
					}
					RefreshStatus();
				}
			});
		}

		private void SearchRow()
		{
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00be: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f5: Unknown result type (might be due to invalid IL or missing references)
			//IL_018e: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = Row("GPS_SearchRow", 56f);
			GameObject val2 = UIFactory.Panel("GPS_Search", val.transform, new Color(1f, 1f, 1f, 0.1f), (Vector2?)null, (Vector2?)null, false);
			LayoutElement orAddLayout = GetOrAddLayout(val2);
			orAddLayout.flexibleWidth = 1f;
			orAddLayout.preferredWidth = 0f;
			orAddLayout.minHeight = 70.4f;
			orAddLayout.preferredHeight = 70.4f;
			Text val3 = MakeText("Placeholder", "Search places & people...", val2.transform, 17, (TextAnchor)3, (FontStyle)2);
			((Graphic)val3).color = new Color(1f, 1f, 1f, 0.4f);
			Stretch(((Graphic)val3).rectTransform, 14f);
			Text val4 = MakeText("Text", "", val2.transform, 17, (TextAnchor)3, (FontStyle)0);
			((Graphic)val4).color = Color.white;
			val4.supportRichText = false;
			Stretch(((Graphic)val4).rectTransform, 14f);
			InputField input = val2.AddComponent<InputField>();
			input.textComponent = val4;
			input.placeholder = (Graphic)(object)val3;
			((Selectable)input).targetGraphic = (Graphic)(object)val2.GetComponent<Image>();
			input.lineType = (LineType)0;
			input.characterLimit = 40;
			EventHelper.AddListener<string>((Action<string>)delegate(string value)
			{
				_query = value ?? "";
				RenderPlaces();
			}, (UnityEvent<string>)(object)input.onValueChanged);
			Button("X", val.transform, ButtonColor, 52f, delegate
			{
				input.text = "";
				_query = "";
				RenderPlaces();
			});
		}

		private void Toggle(string label, MelonPreferences_Entry<bool> entry)
		{
			//IL_0058: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = Row("GPS_Toggle", 52f);
			Flexible(((Component)MakeText("Label", label, val.transform, 18, (TextAnchor)3, (FontStyle)0)).gameObject, 1f, 44f);
			var (val2, val3, txt) = UIFactory.ButtonWithLabel("Toggle", "", val.transform, OffColor, 128f, 70.4f);
			Fixed(val2, 80f, 44f);
			Image img = val2.GetComponent<Image>();
			Action refresh = delegate
			{
				//IL_004c: 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)
				txt.text = (entry.Value ? "ON" : "OFF");
				if ((Object)(object)img != (Object)null)
				{
					((Graphic)img).color = (entry.Value ? OnColor : OffColor);
				}
			};
			_refreshers.Add(refresh);
			EventHelper.AddListener((Action)delegate
			{
				GpsMod.Cfg.Set(entry, !entry.Value);
				refresh();
			}, (UnityEvent)(object)val3.onClick);
		}

		private void Stepper(string label, Func<string> value, Action<int> change)
		{
			//IL_0061: 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)
			GameObject val = Row("GPS_Stepper", 52f);
			Flexible(((Component)MakeText("Label", label, val.transform, 18, (TextAnchor)3, (FontStyle)0)).gameObject, 1f, 44f);
			Text v = null;
			Button("-", val.transform, ButtonColor, 44f, delegate
			{
				change(-1);
				v.text = value();
			});
			v = MakeText("Value", value(), val.transform, 17, (TextAnchor)4, (FontStyle)1);
			Fixed(((Component)v).gameObject, 100f, 44f);
			Button("+", val.transform, ButtonColor, 44f, delegate
			{
				change(1);
				v.text = value();
			});
			_refreshers.Add(delegate
			{
				v.text = value();
			});
		}

		private void ColorRow()
		{
			//IL_0016: 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_007e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0096: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00df: Unknown result type (might be due to invalid IL or missing references)
			Label("Color", 18, (FontStyle)0, Color.white, 30f);
			GameObject val = null;
			List<(string Hex, Text Mark)> swatches = new List<(string, Text)>();
			for (int i = 0; i < Palette.Length; i++)
			{
				var (text, text2) = Palette[i];
				if (i % 5 == 0)
				{
					val = Row("GPS_Colors", 56f);
				}
				Color val2 = HexToColor(text2);
				var (go, val3, val4) = UIFactory.ButtonWithLabel("Swatch_" + text, "", val.transform, val2, 76.8f, 70.4f);
				Fixed(go, 48f, 44f);
				((Graphic)val4).color = ((((Color)(ref val2)).grayscale > 0.6f) ? Color.black : Color.white);
				val4.fontStyle = (FontStyle)1;
				swatches.Add((text2, val4));
				string pick = text2;
				EventHelper.AddListener((Action)delegate
				{
					GpsMod.Cfg.Set(GpsMod.Cfg.LineColor, pick);
					RefreshAll();
				}, (UnityEvent)(object)val3.onClick);
			}
			_refreshers.Add(delegate
			{
				string text3 = (GpsMod.Cfg.LineColor.Value ?? "").Trim().ToUpperInvariant();
				foreach (var item in swatches)
				{
					var (text4, _) = item;
					item.Mark.text = ((text4 == text3) ? "X" : "");
				}
			});
		}

		private void Section(string title)
		{
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			Label(title, 18, (FontStyle)1, new Color(0.45f, 0.85f, 0.95f, 1f), 40f).alignment = (TextAnchor)6;
		}

		private Text Label(string text, int size, FontStyle style, Color color, float height, Transform parent = null)
		{
			//IL_0014: 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)
			Text obj = MakeText("GPS_Label", text, (Transform)(((object)parent) ?? ((object)_list)), size, (TextAnchor)3, style);
			((Graphic)obj).color = color;
			LayoutElement orAddLayout = GetOrAddLayout(((Component)obj).gameObject);
			orAddLayout.minHeight = height * 1.6f;
			orAddLayout.preferredHeight = height * 1.6f;
			orAddLayout.preferredWidth = 0f;
			orAddLayout.flexibleWidth = 1f;
			return obj;
		}

		private static Text MakeText(string name, string content, Transform parent, int size, TextAnchor anchor, FontStyle style = (FontStyle)0)
		{
			//IL_0010: 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)
			Text obj = UIFactory.Text(name, content, parent, Mathf.RoundToInt((float)size * 1.6f), anchor, style);
			ContentSizeFitter component = ((Component)obj).GetComponent<ContentSizeFitter>();
			if ((Object)(object)component != (Object)null)
			{
				component.horizontalFit = (FitMode)0;
				component.verticalFit = (FitMode)0;
				((Behaviour)component).enabled = false;
			}
			obj.horizontalOverflow = (HorizontalWrapMode)0;
			obj.verticalOverflow = (VerticalWrapMode)0;
			obj.resizeTextForBestFit = false;
			return obj;
		}

		private static void SetupScrolling(ScrollRect scroll, RectTransform body)
		{
			//IL_00a0: 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_00b6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00dc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fb: 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_0125: Unknown result type (might be due to invalid IL or missing references)
			//IL_0136: Unknown result type (might be due to invalid IL or missing references)
			//IL_014b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0155: Unknown result type (might be due to invalid IL or missing references)
			//IL_016f: Unknown result type (might be due to invalid IL or missing references)
			//IL_017e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0192: Unknown result type (might be due to invalid IL or missing references)
			//IL_019d: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c7: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d7: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e2: Unknown result type (might be due to invalid IL or missing references)
			//IL_0209: Unknown result type (might be due to invalid IL or missing references)
			//IL_0071: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)scroll == (Object)null || (Object)(object)body == (Object)null)
			{
				return;
			}
			scroll.scrollSensitivity = 72f;
			scroll.inertia = true;
			scroll.decelerationRate = 0.12f;
			scroll.movementType = (MovementType)2;
			if ((Object)(object)((Component)scroll).GetComponent<Mask>() == (Object)null && (Object)(object)((Component)scroll).GetComponent<RectMask2D>() == (Object)null)
			{
				bool flag = (Object)(object)((Component)scroll).GetComponent<Image>() != (Object)null;
				if (!flag)
				{
					Image obj = ((Component)scroll).gameObject.AddComponent<Image>();
					((Graphic)obj).color = Color.white;
					((Graphic)obj).raycastTarget = true;
				}
				((Component)scroll).gameObject.AddComponent<Mask>().showMaskGraphic = flag;
			}
			float num = 14.400001f;
			RectTransform component = ((Component)scroll).GetComponent<RectTransform>();
			component.anchorMin = Vector2.zero;
			component.anchorMax = Vector2.one;
			component.offsetMin = Vector2.zero;
			component.offsetMax = new Vector2(0f - (num + 6f), 0f);
			GameObject val = new GameObject("GPS_Scrollbar");
			RectTransform val2 = val.AddComponent<RectTransform>();
			((Transform)val2).SetParent((Transform)(object)body, false);
			val2.anchorMin = new Vector2(1f, 0f);
			val2.anchorMax = new Vector2(1f, 1f);
			val2.pivot = new Vector2(1f, 0.5f);
			val2.sizeDelta = new Vector2(num, -8f);
			val2.anchoredPosition = new Vector2(-2f, 0f);
			((Graphic)val.AddComponent<Image>()).color = new Color(1f, 1f, 1f, 0.06f);
			RectTransform val3 = new GameObject("Sliding Area").AddComponent<RectTransform>();
			((Transform)val3).SetParent((Transform)(object)val2, false);
			val3.anchorMin = Vector2.zero;
			val3.anchorMax = Vector2.one;
			val3.offsetMin = Vector2.zero;
			val3.offsetMax = Vector2.zero;
			GameObject val4 = new GameObject("Handle");
			RectTransform val5 = val4.AddComponent<RectTransform>();
			((Transform)val5).SetParent((Transform)(object)val3, false);
			val5.offsetMin = Vector2.zero;
			val5.offsetMax = Vector2.zero;
			Image val6 = val4.AddComponent<Image>();
			((Graphic)val6).color = new Color(0.45f, 0.85f, 0.95f, 0.75f);
			Scrollbar val7 = val.AddComponent<Scrollbar>();
			val7.handleRect = val5;
			((Selectable)val7).targetGraphic = (Graphic)(object)val6;
			val7.direction = (Direction)2;
			scroll.verticalScrollbar = val7;
			scroll.verticalScrollbarVisibility = (ScrollbarVisibility)0;
		}

		private void FitListToViewport(ScrollRect scroll)
		{
			//IL_0020: 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_0054: 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_0079: 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_009e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ed: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f7: Expected O, but got Unknown
			if ((Object)(object)scroll != (Object)null)
			{
				scroll.horizontal = false;
			}
			_list.anchorMin = new Vector2(0f, 1f);
			_list.anchorMax = new Vector2(1f, 1f);
			_list.pivot = new Vector2(0.5f, 1f);
			_list.sizeDelta = new Vector2(0f, _list.sizeDelta.y);
			_list.anchoredPosition = new Vector2(0f, _list.anchoredPosition.y);
			ContentSizeFitter component = ((Component)_list).GetComponent<ContentSizeFitter>();
			if ((Object)(object)component != (Object)null)
			{
				component.horizontalFit = (FitMode)0;
			}
			VerticalLayoutGroup component2 = ((Component)_list).GetComponent<VerticalLayoutGroup>();
			if ((Object)(object)component2 != (Object)null)
			{
				((HorizontalOrVerticalLayoutGroup)component2).childControlWidth = true;
				((HorizontalOrVerticalLayoutGroup)component2).childForceExpandWidth = true;
				((LayoutGroup)component2).padding = new RectOffset(8, 8, 6, 16);
				((HorizontalOrVerticalLayoutGroup)component2).spacing = 6f;
			}
		}

		private GameObject Row(string name, float height, Transform parent = null)
		{
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			GameObject obj = UIFactory.Panel(name, (Transform)(((object)parent) ?? ((object)_list)), RowColor, (Vector2?)null, (Vector2?)null, false);
			UIFactory.HorizontalLayoutOnGO(obj, Mathf.RoundToInt(16f), Mathf.RoundToInt(22.4f), Mathf.RoundToInt(16f), 4, 4, (TextAnchor)3);
			HorizontalLayoutGroup component = obj.GetComponent<HorizontalLayoutGroup>();
			if ((Object)(object)component != (Object)null)
			{
				((HorizontalOrVerticalLayoutGroup)component).childControlWidth = true;
				((HorizontalOrVerticalLayoutGroup)component).childControlHeight = true;
				((HorizontalOrVerticalLayoutGroup)component).childForceExpandWidth = false;
				((HorizontalOrVerticalLayoutGroup)component).childForceExpandHeight = false;
			}
			LayoutElement orAddLayout = GetOrAddLayout(obj);
			orAddLayout.minHeight = height * 1.6f;
			orAddLayout.preferredHeight = height * 1.6f;
			orAddLayout.flexibleWidth = 1f;
			return obj;
		}

		private static Text Button(string label, Transform parent, Color color, float width, Action onClick)
		{
			//IL_002d: 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)
			bool flag = width <= 0f;
			var (go, val, val2) = UIFactory.ButtonWithLabel("GPS_Btn", label, parent, color, (flag ? 100f : width) * 1.6f, 70.4f);
			if (flag)
			{
				LayoutElement orAddLayout = GetOrAddLayout(go);
				orAddLayout.minWidth = 96f;
				orAddLayout.preferredWidth = 0f;
				orAddLayout.flexibleWidth = 1f;
				orAddLayout.minHeight = 70.4f;
				orAddLayout.preferredHeight = 70.4f;
			}
			else
			{
				Fixed(go, width, 44f);
			}
			((Graphic)val2).color = Color.white;
			val2.fontSize = Mathf.RoundToInt(27.2f);
			EventHelper.AddListener((Action)delegate
			{
				try
				{
					onClick();
				}
				catch (Exception value)
				{
					GpsMod.Log.Error($"GPS app button '{label}' failed: {value}");
				}
			}, (UnityEvent)(object)val.onClick);
			return val2;
		}

		private static void Fixed(GameObject go, float w, float h)
		{
			LayoutElement orAddLayout = GetOrAddLayout(go);
			orAddLayout.minWidth = w * 1.6f;
			orAddLayout.preferredWidth = w * 1.6f;
			orAddLayout.flexibleWidth = 0f;
			orAddLayout.minHeight = h * 1.6f;
			orAddLayout.preferredHeight = h * 1.6f;
		}

		private static void Flexible(GameObject go, float flex, float h)
		{
			LayoutElement orAddLayout = GetOrAddLayout(go);
			orAddLayout.flexibleWidth = flex;
			orAddLayout.minWidth = 96f;
			orAddLayout.preferredWidth = 0f;
			orAddLayout.minHeight = h * 1.6f;
			orAddLayout.preferredHeight = h * 1.6f;
		}

		private static LayoutElement GetOrAddLayout(GameObject go)
		{
			LayoutElement val = go.GetComponent<LayoutElement>();
			if ((Object)(object)val == (Object)null)
			{
				val = go.AddComponent<LayoutElement>();
			}
			return val;
		}

		private static void Stretch(RectTransform rt, float padLeft)
		{
			//IL_0001: 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_001d: 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)
			rt.anchorMin = Vector2.zero;
			rt.anchorMax = Vector2.one;
			rt.offsetMin = new Vector2(padLeft, 0f);
			rt.offsetMax = new Vector2(0f - padLeft, 0f);
		}

		private static float Step(float[] steps, float current, int dir)
		{
			int num = 0;
			for (int i = 1; i < steps.Length; i++)
			{
				if (Mathf.Abs(steps[i] - current) < Mathf.Abs(steps[num] - current))
				{
					num = i;
				}
			}
			return steps[Mathf.Clamp(num + dir, 0, steps.Length - 1)];
		}

		private static Color HexToColor(string hex)
		{
			//IL_0050: Unknown result type (might be due to invalid IL or missing references)
			string text = hex.TrimStart('#');
			return new Color((float)Convert.ToInt32(text.Substring(0, 2), 16) / 255f, (float)Convert.ToInt32(text.Substring(2, 2), 16) / 255f, (float)Convert.ToInt32(text.Substring(4, 2), 16) / 255f, 1f);
		}
	}
	internal class MapProjection
	{
		private Vector2 _m0;

		private Vector2 _a;

		private Vector2 _b;

		private float _det;

		private bool _logged;

		public bool Valid { get; private set; }

		public Vector2 PerMeterX => _a;

		public Vector2 PerMeterZ => _b;

		public float UnitsPerMeter { get; private set; } = 1f;

		public static MapPositionUtility Util
		{
			get
			{
				if (!Singleton<MapPositionUtility>.InstanceExists)
				{
					return null;
				}
				return Singleton<MapPositionUtility>.Instance;
			}
		}

		public bool Calibrate()
		{
			//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_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_004f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0054: 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_006a: 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_0074: Unknown result type (might be due to invalid IL or missing references)
			//IL_0077: Unknown result type (might be due to invalid IL or missing references)
			//IL_0078: Unknown result type (might be due to invalid IL or missing references)
			//IL_007e: Unknown result type (might be due to invalid IL or missing references)
			//IL_007f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0080: 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_0095: Unknown result type (might be due to invalid IL or missing references)
			//IL_0096: Unknown result type (might be due to invalid IL or missing references)
			//IL_0097: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a6: Unknown result type (might be due to invalid IL or missing references)
			//IL_0120: 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_012c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0131: Unknown result type (might be due to invalid IL or missing references)
			//IL_0137: Unknown result type (might be due to invalid IL or missing references)
			//IL_0141: Unknown result type (might be due to invalid IL or missing references)
			//IL_0146: Unknown result type (might be due to invalid IL or missing references)
			//IL_014b: Unknown result type (might be due to invalid IL or missing references)
			//IL_014d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0152: Unknown result type (might be due to invalid IL or missing references)
			//IL_017e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0193: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ac: Unknown result type (might be due to invalid IL or missing references)
			//IL_0257: Unknown result type (might be due to invalid IL or missing references)
			MapPositionUtility util = Util;
			if ((Object)(object)util == (Object)null)
			{
				Valid = false;
				return false;
			}
			Vector2 mapPosition = util.GetMapPosition(Vector3.zero);
			Vector2 mapPosition2 = util.GetMapPosition(new Vector3(1000f, 0f, 0f));
			Vector2 mapPosition3 = util.GetMapPosition(new Vector3(0f, 0f, 1000f));
			Vector2 mapPosition4 = util.GetMapPosition(new Vector3(1000f, 0f, 1000f));
			_m0 = mapPosition;
			_a = (mapPosition2 - mapPosition) / 1000f;
			_b = (mapPosition3 - mapPosition) / 1000f;
			_det = _a.x * _b.y - _b.x * _a.y;
			Valid = Mathf.Abs(_det) > 1E-12f;
			UnitsPerMeter = Mathf.Sqrt(Mathf.Abs(_det));
			if (!_logged)
			{
				_logged = true;
				Vector2 val = mapPosition + _a * 1000f + _b * 1000f - mapPosition4;
				float magnitude = ((Vector2)(ref val)).magnitude;
				GpsMod.Log.Msg($"Map projection: origin={mapPosition}, perMeterX={_a}, perMeterZ={_b}, scale={UnitsPerMeter:F4} map units/m, linearity error={magnitude:F4} ({((magnitude < 0.5f) ? "OK" : "NON-LINEAR, clicks may be off")}). OriginPoint={(((Object)(object)util.OriginPoint != (Object)null) ? RoutePlanner.Fmt(util.OriginPoint.position) : "null")}, MapDimensions={util.MapDimensions}, conversionFactor={util.conversionFactor}");
				if (!Valid)
				{
					GpsMod.Log.Error("Map projection is degenerate; map clicks can't be converted to world positions.");
				}
			}
			return Valid;
		}

		public Vector2 WorldToMap(Vector3 world)
		{
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: 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_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_0037: 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)
			MapPositionUtility util = Util;
			if (!((Object)(object)util != (Object)null))
			{
				return _m0 + _a * world.x + _b * world.z;
			}
			return util.GetMapPosition(world);
		}

		public Vector2 MapToWorldXZ(Vector2 m)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: 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_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_004b: 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)
			Vector2 val = m - _m0;
			float num = (val.x * _b.y - _b.x * val.y) / _det;
			float num2 = (_a.x * val.y - val.x * _a.y) / _det;
			return new Vector2(num, num2);
		}
	}
	internal class MapOverlay
	{
		private static MapApp s_app;

		private readonly MapProjection _proj = new MapProjection();

		private RectTransform _layer;

		private readonly List<Image> _segments = new List<Image>();

		private Image _destMarker;

		private int _usedSegments;

		private Vector2 _downPos;

		private float _downTime;

		private bool _leftDownOnMap;

		private bool _checkedPoiAlignment;

		private bool _loggedDraw;

		private static MapApp App
		{
			get
			{
				if ((Object)(object)s_app != (Object)null)
				{
					return s_app;
				}
				if (PlayerSingleton<MapApp>.InstanceExists)
				{
					s_app = PlayerSingleton<MapApp>.Instance;
				}
				return s_app;
			}
		}

		public MapProjection Projection => _proj;

		public static void OnMapAppSetOpen(MapApp app, bool open)
		{
			s_app = app;
			GpsMod.Verbose($"MapApp.SetOpen({open})");
		}

		public void HandleInput(GpsCore core)
		{
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_0050: Unknown result type (might be due to invalid IL or missing references)
			//IL_0051: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e3: 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_007f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0084: Unknown result type (might be due to invalid IL or missing references)
			//IL_0089: 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_0114: 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_00bd: Unknown result type (might be due to invalid IL or missing references)
			MapApp app = App;
			if ((Object)(object)app == (Object)null || !((App<MapApp>)(object)app).isOpen)
			{
				_leftDownOnMap = false;
				return;
			}
			Mouse current = Mouse.current;
			if (current == null)
			{
				return;
			}
			Vector2 val = ((InputControl<Vector2>)(object)((Pointer)current).position).ReadValue();
			if (current.leftButton.wasPressedThisFrame)
			{
				_leftDownOnMap = IsOverMap(app, val);
				_downPos = val;
				_downTime = Time.unscaledTime;
			}
			if (current.leftButton.wasReleasedThisFrame && _leftDownOnMap)
			{
				_leftDownOnMap = false;
				Vector2 val2 = val - _downPos;
				if (((Vector2)(ref val2)).magnitude <= 8f && Time.unscaledTime - _downTime < 0.6f)
				{
					if (TryScreenToWorldXZ(app, val, out var worldXZ))
					{
						core.SetDestination(worldXZ, "map left-click");
					}
				}
				else
				{
					GpsMod.Verbose("Map drag ignored (not a click).");
				}
			}
			if (!current.rightButton.wasPressedThisFrame || !IsOverMap(app, val))
			{
				return;
			}
			if (string.Equals(GpsMod.Cfg.RightClickAction.Value, "Set", StringComparison.OrdinalIgnoreCase))
			{
				if (TryScreenToWorldXZ(app, val, out var worldXZ2))
				{
					core.SetDestination(worldXZ2, "map right-click");
				}
			}
			else
			{
				core.ClearRoute("map right-click");
			}
		}

		private static Camera GetUICamera(RectTransform rt)
		{