Decompiled source of CompassWaypointsClock v0.1.8

BepInEx/plugins/CompassWaypointsClock/CompassWaypointsClock.dll

Decompiled a week ago
using System;
using System.Collections.Generic;
using System.IO;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Security.Cryptography;
using System.Text;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using HarmonyLib;
using TMPro;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.Events;
using UnityEngine.UI;

[assembly: InternalsVisibleTo("Assembly-CSharp-Editor")]
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: AssemblyMetadata("AI_Assisted_Creation", "Coded with the assistance of ChatGPT 6.0; packaged with OpenAI Codex.")]
[assembly: AssemblyMetadata("AI_Model_Vendor", "OpenAI")]
[assembly: AssemblyVersion("0.0.0.0")]
namespace CompassWaypointsClock;

internal sealed class ArrivalSound
{
	private AudioSource source;

	private AudioClip clip;

	internal static float[] Samples(int rate)
	{
		float[] array = new float[(int)Math.Round((double)rate * 0.24)];
		for (int i = 0; i < array.Length; i++)
		{
			double num = (double)i / (double)rate;
			double num2 = Math.Sin(Math.PI * (double)i / (double)(array.Length - 1));
			array[i] = (float)(0.24 * num2 * num2 * (Math.Sin(Math.PI * 1760.0 * num) + 0.4 * Math.Sin(Math.PI * 2640.0 * num)));
		}
		return array;
	}

	internal void Play(GameObject owner, float volume)
	{
		if (!(volume <= 0f))
		{
			if (!Object.op_Implicit((Object)(object)source))
			{
				source = owner.AddComponent<AudioSource>();
				source.playOnAwake = false;
				source.spatialBlend = 0f;
				source.loop = false;
			}
			if (!Object.op_Implicit((Object)(object)clip))
			{
				float[] array = Samples(44100);
				clip = AudioClip.Create("Waypoint arrival", array.Length, 1, 44100, false);
				typeof(AudioClip).GetMethod("SetData", new Type[2]
				{
					typeof(float[]),
					typeof(int)
				}).Invoke(clip, new object[2] { array, 0 });
			}
			source.PlayOneShot(clip, Mathf.Clamp01(volume));
		}
	}

	internal void Dispose()
	{
		if (Object.op_Implicit((Object)(object)source))
		{
			Object.Destroy((Object)(object)source);
		}
		if (Object.op_Implicit((Object)(object)clip))
		{
			Object.Destroy((Object)(object)clip);
		}
	}
}
internal static class Controls
{
	private static readonly MethodInfo MapPosition = AccessTools.Method(typeof(Minimap), "ScreenToWorldPoint", (Type[])null, (Type[])null);

	private static readonly PropertyInfo PinRadius = AccessTools.Property(typeof(Minimap), "PinInteractRadius");

	private static float nextHint;

	internal static string BlockReason()
	{
		Player localPlayer = Player.m_localPlayer;
		GameObject val = (Object.op_Implicit((Object)(object)EventSystem.current) ? EventSystem.current.currentSelectedGameObject : null);
		if (Object.op_Implicit((Object)(object)val) && val.activeInHierarchy && (Object.op_Implicit((Object)(object)val.GetComponentInParent<TMP_InputField>()) || Object.op_Implicit((Object)(object)val.GetComponentInParent<InputField>())))
		{
			return "text field has focus";
		}
		if (!Object.op_Implicit((Object)(object)localPlayer))
		{
			return "no local player";
		}
		if (((Character)localPlayer).IsDead())
		{
			return "player is dead";
		}
		if (((Character)localPlayer).IsTeleporting())
		{
			return "teleport in progress";
		}
		if (((Character)localPlayer).InCutscene())
		{
			return "cutscene or sleep in progress";
		}
		if (TextInput.IsVisible())
		{
			return "text entry is open";
		}
		if (UnifiedPopup.WasVisibleThisFrame())
		{
			return "popup is open";
		}
		if (Console.IsVisible())
		{
			return "console is open";
		}
		if (Menu.IsVisible())
		{
			return "menu is open";
		}
		if (StoreGui.IsVisible())
		{
			return "store is open";
		}
		if (InventoryGui.IsVisible())
		{
			return "inventory is open";
		}
		if (Object.op_Implicit((Object)(object)Chat.instance) && Chat.instance.HasFocus())
		{
			return "chat has focus";
		}
		return null;
	}

	internal static bool Blocked()
	{
		return BlockReason() != null;
	}

	internal static bool MapChord()
	{
		//IL_0048: Unknown result type (might be due to invalid IL or missing references)
		//IL_004e: Invalid comparison between Unknown and I4
		//IL_0068: Unknown result type (might be due to invalid IL or missing references)
		//IL_006d: Unknown result type (might be due to invalid IL or missing references)
		Plugin instance = Plugin.Instance;
		Minimap instance2 = Minimap.instance;
		if (Object.op_Implicit((Object)(object)instance) && instance.Active && instance.EnableWaypoints.Value && !Blocked() && Object.op_Implicit((Object)(object)instance2) && (int)instance2.m_mode == 2 && Object.op_Implicit((Object)(object)instance2.m_mapImageLarge) && RectTransformUtility.RectangleContainsScreenPoint(((Graphic)instance2.m_mapImageLarge).rectTransform, Vector2.op_Implicit(ZInput.pointerPosition), (Camera)null) && (ZInput.GetKey((KeyCode)306, true) || ZInput.GetKey((KeyCode)305, true)) && !ZInput.GetKey((KeyCode)308, true) && !ZInput.GetKey((KeyCode)307, true) && !ZInput.GetKey((KeyCode)304, true))
		{
			return !ZInput.GetKey((KeyCode)303, true);
		}
		return false;
	}

	internal static bool Dispatch(Plugin plugin, string action, Vector3 position, float radius)
	{
		//IL_0020: Unknown result type (might be due to invalid IL or missing references)
		if (action == "OnMapDblClick")
		{
			plugin.Add(position, checkHeight: false, "Waypoint " + (plugin.Engine.Document.Points.Count + 1));
		}
		else if (action == "OnMapLeftClick" && Time.unscaledTime >= nextHint)
		{
			nextHint = Time.unscaledTime + 3f;
			plugin.Notice("Hold Ctrl and double-left-click to add a waypoint");
		}
		else if (action == "RemovePinUnderPointer")
		{
			int index = plugin.Engine.FindNearest(position.x, position.z, radius);
			if (index >= 0)
			{
				plugin.Change(() => plugin.Engine.Remove(index, plugin.Now), plugin.Engine.Label(index) + " removed");
			}
			else
			{
				plugin.Notice("No waypoint near the cursor");
			}
		}
		return false;
	}

	internal static bool Handle(Minimap map, string action)
	{
		//IL_0085: 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_009c: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a3: Unknown result type (might be due to invalid IL or missing references)
		try
		{
			if (!MapChord())
			{
				Plugin instance = Plugin.Instance;
				if (Object.op_Implicit((Object)(object)instance) && (ZInput.GetKey((KeyCode)306, true) || ZInput.GetKey((KeyCode)305, true)))
				{
					instance.Notice((!instance.EnableWaypoints.Value) ? "Waypoints disabled in config" : ((!instance.Active) ? "Waypoint storage unavailable - check the log" : ("Waypoint input blocked: " + (BlockReason() ?? "use Ctrl only over the large map"))));
				}
				return true;
			}
			Vector3 position = (Vector3)MapPosition.Invoke(map, new object[1] { ZInput.pointerPosition });
			return Dispatch(Plugin.Instance, action, position, (float)PinRadius.GetValue(map, null));
		}
		catch (Exception ex)
		{
			Plugin.Instance.Notice("Waypoint action failed: " + ex.Message);
			return false;
		}
	}
}
[HarmonyPatch]
internal static class MapWaypointControls
{
	private static IEnumerable<MethodBase> TargetMethods()
	{
		try
		{
			string[] array = new string[3] { "OnMapDblClick", "OnMapLeftClick", "RemovePinUnderPointer" };
			foreach (string name in array)
			{
				yield return AccessTools.Method(typeof(Minimap), name, (Type[])null, (Type[])null);
			}
		}
		finally
		{
		}
	}

	private static bool Prefix(Minimap __instance, MethodBase __originalMethod)
	{
		return Controls.Handle(__instance, __originalMethod.Name);
	}
}
internal sealed class Display
{
	private sealed class CompassTarget
	{
		internal Vector3 Position;

		internal Sprite Icon;

		internal Color Colour;
	}

	private readonly Plugin plugin;

	private GameObject root;

	private GameObject compass;

	private GameObject clock;

	private RectTransform hud;

	private RectTransform mapUi;

	private Toggle removeToggle;

	private GameObject removeCheck;

	private GameObject filterButton;

	private GameObject filterPanel;

	private TextMeshProUGUI mapHint;

	private Image nextDiamond;

	private string mapStatus;

	private float statusUntil;

	private readonly List<Toggle> filterToggles = new List<Toggle>();

	private readonly List<GameObject> filterChecks = new List<GameObject>();

	private bool filtersOpen;

	private TMP_FontAsset font;

	private TextMeshProUGUI time;

	private TextMeshProUGUI target;

	private TextMeshProUGUI heading;

	private TextMeshProUGUI destination;

	private readonly List<TextMeshProUGUI> bearings = new List<TextMeshProUGUI>();

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

	private readonly List<CompassTarget> nearby = new List<CompassTarget>();

	private static readonly FieldInfo MapPins = AccessTools.Field(typeof(Minimap), "m_pins");

	private int previousHeading = -1;

	private float nextText;

	private float nextPinScan;

	private string appliedCompassColour;

	private string appliedClockColour;

	private Color compassColour = HudStyle.DefaultColour;

	internal void SetStatus(string value)
	{
		mapStatus = value;
		statusUntil = Time.unscaledTime + 6f;
	}

	internal Display(Plugin owner)
	{
		//IL_003f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0044: Unknown result type (might be due to invalid IL or missing references)
		plugin = owner;
	}

	internal void Invalidate()
	{
		nextPinScan = 0f;
	}

	private static RectTransform Rect(string name, Transform parent, Vector2 anchor, Vector2 position, Vector2 size)
	{
		//IL_0016: Unknown result type (might be due to invalid IL or missing references)
		//IL_001c: Expected O, but got Unknown
		//IL_002d: 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_002f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0035: Unknown result type (might be due to invalid IL or missing references)
		//IL_0046: 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_0058: Unknown result type (might be due to invalid IL or missing references)
		GameObject val = new GameObject(name, new Type[1] { typeof(RectTransform) });
		RectTransform component = val.GetComponent<RectTransform>();
		((Transform)component).SetParent(parent, false);
		Vector2 anchorMin = (component.anchorMax = anchor);
		component.anchorMin = anchorMin;
		component.pivot = new Vector2(0.5f, 0.5f);
		component.anchoredPosition = position;
		component.sizeDelta = size;
		return component;
	}

	private TextMeshProUGUI Text(string name, Transform parent, Vector2 position, Vector2 size, string value, float fontSize)
	{
		//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_0012: 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)
		RectTransform val = Rect(name, parent, new Vector2(0.5f, 0.5f), position, size);
		((Component)val).gameObject.SetActive(false);
		TextMeshProUGUI val2 = ((Component)val).gameObject.AddComponent<TextMeshProUGUI>();
		((TMP_Text)val2).font = font;
		((TMP_Text)val2).fontSize = fontSize;
		((TMP_Text)val2).text = value;
		((TMP_Text)val2).richText = false;
		((Graphic)val2).raycastTarget = false;
		((TMP_Text)val2).alignment = (TextAlignmentOptions)514;
		((TMP_Text)val2).overflowMode = (TextOverflowModes)1;
		((TMP_Text)val2).textWrappingMode = (TextWrappingModes)0;
		((Graphic)val2).color = new Color(0.92f, 0.85f, 0.68f);
		((Component)val).gameObject.SetActive(true);
		return val2;
	}

	private bool Build()
	{
		//IL_00bf: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c9: Expected O, but got Unknown
		//IL_0102: Unknown result type (might be due to invalid IL or missing references)
		//IL_0132: 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_0146: Unknown result type (might be due to invalid IL or missing references)
		//IL_016b: 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_017f: Unknown result type (might be due to invalid IL or missing references)
		//IL_01af: Unknown result type (might be due to invalid IL or missing references)
		//IL_01be: Unknown result type (might be due to invalid IL or missing references)
		//IL_0200: Unknown result type (might be due to invalid IL or missing references)
		//IL_020f: Unknown result type (might be due to invalid IL or missing references)
		//IL_02b4: Unknown result type (might be due to invalid IL or missing references)
		//IL_02c3: Unknown result type (might be due to invalid IL or missing references)
		//IL_02f8: Unknown result type (might be due to invalid IL or missing references)
		//IL_0307: Unknown result type (might be due to invalid IL or missing references)
		//IL_033a: Unknown result type (might be due to invalid IL or missing references)
		//IL_033f: Unknown result type (might be due to invalid IL or missing references)
		//IL_034e: Unknown result type (might be due to invalid IL or missing references)
		//IL_03c6: Unknown result type (might be due to invalid IL or missing references)
		//IL_03cb: Unknown result type (might be due to invalid IL or missing references)
		//IL_03da: Unknown result type (might be due to invalid IL or missing references)
		//IL_041a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0463: Unknown result type (might be due to invalid IL or missing references)
		//IL_0472: Unknown result type (might be due to invalid IL or missing references)
		//IL_0481: Unknown result type (might be due to invalid IL or missing references)
		//IL_04a7: Unknown result type (might be due to invalid IL or missing references)
		//IL_04b6: Unknown result type (might be due to invalid IL or missing references)
		//IL_04e0: Unknown result type (might be due to invalid IL or missing references)
		//IL_04e5: Unknown result type (might be due to invalid IL or missing references)
		//IL_04ea: Unknown result type (might be due to invalid IL or missing references)
		//IL_04ff: Unknown result type (might be due to invalid IL or missing references)
		//IL_0515: Unknown result type (might be due to invalid IL or missing references)
		//IL_051a: Unknown result type (might be due to invalid IL or missing references)
		//IL_051b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0522: Unknown result type (might be due to invalid IL or missing references)
		//IL_053e: Unknown result type (might be due to invalid IL or missing references)
		//IL_054d: Unknown result type (might be due to invalid IL or missing references)
		//IL_055c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0588: Unknown result type (might be due to invalid IL or missing references)
		//IL_05ab: Unknown result type (might be due to invalid IL or missing references)
		//IL_05c1: Unknown result type (might be due to invalid IL or missing references)
		//IL_05d0: Unknown result type (might be due to invalid IL or missing references)
		//IL_05df: Unknown result type (might be due to invalid IL or missing references)
		//IL_060a: Unknown result type (might be due to invalid IL or missing references)
		//IL_062d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0632: Unknown result type (might be due to invalid IL or missing references)
		//IL_0641: Unknown result type (might be due to invalid IL or missing references)
		//IL_0659: Unknown result type (might be due to invalid IL or missing references)
		//IL_0697: Unknown result type (might be due to invalid IL or missing references)
		//IL_06a6: Unknown result type (might be due to invalid IL or missing references)
		//IL_0727: Unknown result type (might be due to invalid IL or missing references)
		//IL_0736: Unknown result type (might be due to invalid IL or missing references)
		//IL_075a: Unknown result type (might be due to invalid IL or missing references)
		//IL_075f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0764: Unknown result type (might be due to invalid IL or missing references)
		//IL_077c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0792: Unknown result type (might be due to invalid IL or missing references)
		//IL_07a8: Unknown result type (might be due to invalid IL or missing references)
		//IL_07be: Unknown result type (might be due to invalid IL or missing references)
		//IL_07d4: Unknown result type (might be due to invalid IL or missing references)
		//IL_0802: Unknown result type (might be due to invalid IL or missing references)
		//IL_0832: Unknown result type (might be due to invalid IL or missing references)
		//IL_0847: Unknown result type (might be due to invalid IL or missing references)
		//IL_0866: Unknown result type (might be due to invalid IL or missing references)
		//IL_0885: Unknown result type (might be due to invalid IL or missing references)
		font = ((Object.op_Implicit((Object)(object)InventoryGui.instance) && Object.op_Implicit((Object)(object)InventoryGui.instance.m_playerName)) ? InventoryGui.instance.m_playerName.font : TMP_Settings.defaultFontAsset);
		if (!Object.op_Implicit((Object)(object)font))
		{
			return false;
		}
		bearings.Clear();
		mapMarkers.Clear();
		previousHeading = -1;
		appliedCompassColour = (appliedClockColour = null);
		root = new GameObject("Compass Waypoints and Clock", new Type[4]
		{
			typeof(RectTransform),
			typeof(Canvas),
			typeof(CanvasScaler),
			typeof(GraphicRaycaster)
		});
		Canvas component = root.GetComponent<Canvas>();
		component.renderMode = (RenderMode)0;
		component.sortingOrder = 75;
		CanvasScaler component2 = root.GetComponent<CanvasScaler>();
		component2.uiScaleMode = (ScaleMode)1;
		component2.referenceResolution = new Vector2(1920f, 1080f);
		component2.matchWidthOrHeight = 0.5f;
		hud = Rect("HUD", root.transform, new Vector2(0.5f, 1f), Vector2.zero, new Vector2(620f, 110f));
		compass = ((Component)Rect("Compass", (Transform)(object)hud, new Vector2(0.5f, 0.5f), Vector2.zero, new Vector2(600f, 60f))).gameObject;
		heading = Text("Heading", compass.transform, new Vector2(0f, 20f), new Vector2(90f, 24f), "", 15f);
		for (int i = 0; i < 16; i++)
		{
			bearings.Add(Text("Bearing" + i, compass.transform, Vector2.zero, new Vector2(52f, 24f), (i % 2 == 0) ? (new string[8] { "N", "NE", "E", "SE", "S", "SW", "W", "NW" })[i / 2] : "·", (i % 2 == 0) ? 18 : 14));
		}
		target = Text("Destination", compass.transform, new Vector2(0f, -29f), new Vector2(590f, 24f), "", 16f);
		destination = Text("Waypoint bearing", compass.transform, new Vector2(0f, -13f), new Vector2(30f, 20f), "◆", 14f);
		RectTransform val = Rect("Next waypoint diamond", compass.transform, new Vector2(0.5f, 0.5f), Vector2.zero, new Vector2(20f, 20f));
		nextDiamond = ((Component)val).gameObject.AddComponent<Image>();
		((Graphic)nextDiamond).raycastTarget = false;
		nextDiamond.sprite = MarkerSprites.Get(MarkerKind.Waypoints);
		((Component)nextDiamond).gameObject.SetActive(false);
		for (int j = 0; j < 16; j++)
		{
			RectTransform val2 = Rect("Map pin " + j, compass.transform, new Vector2(0.5f, 0.5f), Vector2.zero, new Vector2(18f, 18f));
			Image val3 = ((Component)val2).gameObject.AddComponent<Image>();
			((Graphic)val3).raycastTarget = false;
			val3.preserveAspect = true;
			((Graphic)val3).color = new Color(1f, 1f, 1f, 0.65f);
			((Component)val3).gameObject.SetActive(false);
			mapMarkers.Add(val3);
		}
		clock = ((Component)Rect("Clock", (Transform)(object)hud, new Vector2(0.5f, 0.5f), new Vector2(0f, -58f), new Vector2(300f, 28f))).gameObject;
		time = Text("Time", clock.transform, Vector2.zero, new Vector2(300f, 28f), "", 20f);
		mapUi = Rect("CWC map controls", root.transform, Vector2.zero, Vector2.zero, Vector2.zero);
		mapUi.anchorMax = Vector2.one;
		RectTransform obj = mapUi;
		Vector2 offsetMin = (mapUi.offsetMax = Vector2.zero);
		obj.offsetMin = offsetMin;
		RectTransform val4 = Rect("Remove visited waypoints", (Transform)(object)mapUi, new Vector2(0f, 1f), new Vector2(165f, -36f), new Vector2(290f, 36f));
		((Graphic)((Component)val4).gameObject.AddComponent<Image>()).color = new Color(0.055f, 0.07f, 0.065f, 0.9f);
		removeToggle = ((Component)val4).gameObject.AddComponent<Toggle>();
		removeToggle.toggleTransition = (ToggleTransition)0;
		RectTransform val5 = Rect("Checkbox", (Transform)(object)val4, new Vector2(0.5f, 0.5f), new Vector2(-124f, 0f), new Vector2(20f, 20f));
		Image val6 = ((Component)val5).gameObject.AddComponent<Image>();
		((Graphic)val6).color = new Color(0.3f, 0.34f, 0.3f);
		((Graphic)val6).raycastTarget = false;
		Image val7 = ((Component)Rect("Check", (Transform)(object)val5, new Vector2(0.5f, 0.5f), Vector2.zero, new Vector2(10f, 10f))).gameObject.AddComponent<Image>();
		((Graphic)val7).color = HudStyle.DefaultColour;
		((Graphic)val7).raycastTarget = false;
		((Selectable)removeToggle).targetGraphic = (Graphic)(object)val6;
		removeCheck = ((Component)val7).gameObject;
		Text("Label", (Transform)(object)val4, new Vector2(12f, 0f), new Vector2(245f, 30f), "Remove visited waypoints", 17f);
		removeToggle.SetIsOnWithoutNotify(plugin.AutoRemoveVisited.Value);
		removeCheck.SetActive(plugin.AutoRemoveVisited.Value);
		((UnityEvent<bool>)(object)removeToggle.onValueChanged).AddListener((UnityAction<bool>)delegate(bool value)
		{
			removeCheck.SetActive(value);
			plugin.AutoRemoveVisited.Value = value;
			plugin.Notice(value ? "Visited waypoints will be removed" : "Visited waypoints will stay on the map");
		});
		((Component)val4).gameObject.SetActive(false);
		mapHint = Text("Waypoint controls", (Transform)(object)mapUi, Vector2.zero, new Vector2(1150f, 64f), "Ctrl + double-left-click: add waypoint   |   Ctrl + right-click: remove waypoint", 18f);
		RectTransform val8 = Rect("Waypoint hint panel", (Transform)(object)mapUi, Vector2.zero, Vector2.zero, Vector2.zero);
		val8.anchorMin = new Vector2(0f, 0f);
		val8.anchorMax = new Vector2(1f, 0f);
		val8.pivot = new Vector2(0.5f, 0f);
		val8.offsetMin = new Vector2(24f, 100f);
		val8.offsetMax = new Vector2(-180f, 170f);
		Image val9 = ((Component)val8).gameObject.AddComponent<Image>();
		((Graphic)val9).color = new Color(0.04f, 0.05f, 0.04f, 0.85f);
		((Graphic)val9).raycastTarget = false;
		((Transform)((TMP_Text)mapHint).rectTransform).SetParent((Transform)(object)val8, false);
		((TMP_Text)mapHint).rectTransform.anchorMin = Vector2.zero;
		((TMP_Text)mapHint).rectTransform.anchorMax = Vector2.one;
		((TMP_Text)mapHint).rectTransform.offsetMin = new Vector2(12f, 6f);
		((TMP_Text)mapHint).rectTransform.offsetMax = new Vector2(-12f, -6f);
		((TMP_Text)mapHint).enableAutoSizing = true;
		((TMP_Text)mapHint).fontSizeMin = 12f;
		((TMP_Text)mapHint).fontSizeMax = 18f;
		((TMP_Text)mapHint).textWrappingMode = (TextWrappingModes)1;
		((Component)mapHint).gameObject.SetActive(false);
		BuildFilters();
		return true;
	}

	private void BuildFilters()
	{
		//IL_002b: Unknown result type (might be due to invalid IL or missing references)
		//IL_003a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0049: 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_00ab: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b5: Expected O, but got Unknown
		//IL_00bc: Unknown result type (might be due to invalid IL or missing references)
		//IL_00cb: 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_0104: Unknown result type (might be due to invalid IL or missing references)
		//IL_0113: Unknown result type (might be due to invalid IL or missing references)
		//IL_0149: Unknown result type (might be due to invalid IL or missing references)
		//IL_0164: Unknown result type (might be due to invalid IL or missing references)
		//IL_0173: Unknown result type (might be due to invalid IL or missing references)
		//IL_0199: 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_01f1: Unknown result type (might be due to invalid IL or missing references)
		//IL_0200: Unknown result type (might be due to invalid IL or missing references)
		//IL_02da: Unknown result type (might be due to invalid IL or missing references)
		//IL_02ec: Unknown result type (might be due to invalid IL or missing references)
		//IL_02fb: Unknown result type (might be due to invalid IL or missing references)
		//IL_0326: Unknown result type (might be due to invalid IL or missing references)
		//IL_034a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0362: Unknown result type (might be due to invalid IL or missing references)
		//IL_0367: Unknown result type (might be due to invalid IL or missing references)
		//IL_0376: Unknown result type (might be due to invalid IL or missing references)
		//IL_03a2: Unknown result type (might be due to invalid IL or missing references)
		filterToggles.Clear();
		filterChecks.Clear();
		RectTransform val = Rect("Marker filters", (Transform)(object)mapUi, new Vector2(0f, 1f), new Vector2(165f, -79f), new Vector2(290f, 34f));
		filterButton = ((Component)val).gameObject;
		Image val2 = filterButton.AddComponent<Image>();
		((Graphic)val2).color = new Color(0.055f, 0.07f, 0.065f, 0.94f);
		Button val3 = filterButton.AddComponent<Button>();
		((Selectable)val3).targetGraphic = (Graphic)(object)val2;
		((UnityEvent)val3.onClick).AddListener((UnityAction)delegate
		{
			filtersOpen = !filtersOpen;
		});
		Text("Label", (Transform)(object)val, Vector2.zero, new Vector2(270f, 30f), "Marker filters", 17f);
		RectTransform val4 = Rect("Marker filter choices", (Transform)(object)mapUi, new Vector2(0f, 1f), new Vector2(165f, -349f), new Vector2(290f, 496f));
		filterPanel = ((Component)val4).gameObject;
		((Graphic)filterPanel.AddComponent<Image>()).color = new Color(0.055f, 0.07f, 0.065f, 0.96f);
		Text("Map heading", (Transform)(object)val4, new Vector2(25f, 225f), new Vector2(65f, 24f), "Map", 15f);
		Text("Compass heading", (Transform)(object)val4, new Vector2(100f, 225f), new Vector2(85f, 24f), "Compass", 15f);
		for (int num = 0; num < Enum.GetValues(typeof(MarkerKind)).Length; num++)
		{
			MarkerKind kind = (MarkerKind)num;
			float num2 = 187 - num * 34;
			Text("Category", (Transform)(object)val4, new Vector2(-66f, num2), new Vector2(126f, 26f), (kind == MarkerKind.SavedPins) ? "Saved pins" : ((kind == MarkerKind.OtherPins) ? "Other icons" : kind.ToString()), 16f);
			for (int num3 = 0; num3 < 2; num3++)
			{
				ConfigEntry<bool> setting = ((num3 == 0) ? plugin.Markers[kind].Map : plugin.Markers[kind].Compass);
				RectTransform val5 = Rect(string.Concat(kind, " ", (num3 == 0) ? "map" : "compass"), (Transform)(object)val4, new Vector2(0.5f, 0.5f), new Vector2((float)((num3 == 0) ? 25 : 100), num2), new Vector2(26f, 26f));
				Image val6 = ((Component)val5).gameObject.AddComponent<Image>();
				((Graphic)val6).color = new Color(0.3f, 0.34f, 0.3f);
				Toggle val7 = ((Component)val5).gameObject.AddComponent<Toggle>();
				((Selectable)val7).targetGraphic = (Graphic)(object)val6;
				val7.toggleTransition = (ToggleTransition)0;
				GameObject check = ((Component)Rect("Checked", (Transform)(object)val5, new Vector2(0.5f, 0.5f), Vector2.zero, new Vector2(14f, 14f))).gameObject;
				Image val8 = check.AddComponent<Image>();
				((Graphic)val8).raycastTarget = false;
				((Graphic)val8).color = HudStyle.DefaultColour;
				val7.SetIsOnWithoutNotify(setting.Value);
				check.SetActive(setting.Value);
				((UnityEvent<bool>)(object)val7.onValueChanged).AddListener((UnityAction<bool>)delegate(bool value)
				{
					setting.Value = value;
					check.SetActive(value);
					plugin.Notice(string.Concat(kind, " ", ((ConfigEntryBase)setting).Definition.Key, ": ", value ? "on" : "off"));
				});
				filterToggles.Add(val7);
				filterChecks.Add(check);
			}
		}
		filterButton.SetActive(false);
		filterPanel.SetActive(false);
	}

	internal void UpdateFilters(bool mapOpen)
	{
		//IL_0061: Unknown result type (might be due to invalid IL or missing references)
		//IL_0071: Unknown result type (might be due to invalid IL or missing references)
		//IL_0087: Unknown result type (might be due to invalid IL or missing references)
		//IL_008c: Unknown result type (might be due to invalid IL or missing references)
		//IL_008d: 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)
		Minimap instance = Minimap.instance;
		if (mapOpen && Object.op_Implicit((Object)(object)instance) && Object.op_Implicit((Object)(object)instance.m_mapImageLarge))
		{
			if ((Object)(object)((Transform)mapUi).parent != (Object)(object)((Component)instance.m_mapImageLarge).transform)
			{
				((Transform)mapUi).SetParent(((Component)instance.m_mapImageLarge).transform, false);
			}
			mapUi.anchorMin = Vector2.zero;
			mapUi.anchorMax = Vector2.one;
			RectTransform obj = mapUi;
			Vector2 offsetMin = (mapUi.offsetMax = Vector2.zero);
			obj.offsetMin = offsetMin;
			((Transform)mapUi).SetAsLastSibling();
		}
		else if ((Object)(object)((Transform)mapUi).parent != (Object)(object)root.transform)
		{
			((Transform)mapUi).SetParent(root.transform, false);
		}
		((Component)mapUi).gameObject.SetActive(mapOpen && Object.op_Implicit((Object)(object)instance) && Object.op_Implicit((Object)(object)instance.m_mapImageLarge));
		((Component)mapHint).gameObject.SetActive(mapOpen);
		((TMP_Text)mapHint).text = ((!plugin.EnableWaypoints.Value) ? "Waypoints disabled in config" : ((!plugin.Active) ? "Waypoint storage unavailable - check the log" : "Ctrl + double-left-click: add waypoint   |   Ctrl + right-click: remove waypoint"));
		if (Time.unscaledTime < statusUntil && !string.IsNullOrEmpty(mapStatus))
		{
			TextMeshProUGUI obj2 = mapHint;
			((TMP_Text)obj2).text = ((TMP_Text)obj2).text + "\n" + mapStatus;
		}
		filterButton.SetActive(mapOpen);
		filterPanel.SetActive(mapOpen && filtersOpen);
		for (int i = 0; i < filterToggles.Count; i++)
		{
			MarkerRule markerRule = plugin.Markers[(MarkerKind)(i / 2)];
			bool flag = ((i % 2 == 0) ? markerRule.Map.Value : markerRule.Compass.Value);
			filterToggles[i].SetIsOnWithoutNotify(flag);
			filterChecks[i].SetActive(flag);
		}
	}

	internal void Tick()
	{
		//IL_00c8: 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_00ed: Unknown result type (might be due to invalid IL or missing references)
		//IL_003f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0045: Invalid comparison between Unknown and I4
		//IL_0196: Unknown result type (might be due to invalid IL or missing references)
		//IL_019c: Invalid comparison between Unknown and I4
		//IL_013e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0144: Invalid comparison between Unknown and I4
		//IL_01d0: 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_0258: Unknown result type (might be due to invalid IL or missing references)
		//IL_0662: Unknown result type (might be due to invalid IL or missing references)
		//IL_0667: Unknown result type (might be due to invalid IL or missing references)
		//IL_03b2: Unknown result type (might be due to invalid IL or missing references)
		//IL_03c8: Unknown result type (might be due to invalid IL or missing references)
		//IL_03f0: Unknown result type (might be due to invalid IL or missing references)
		//IL_040b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0410: Unknown result type (might be due to invalid IL or missing references)
		//IL_0450: Unknown result type (might be due to invalid IL or missing references)
		//IL_046d: Unknown result type (might be due to invalid IL or missing references)
		//IL_04d7: Unknown result type (might be due to invalid IL or missing references)
		//IL_034b: Unknown result type (might be due to invalid IL or missing references)
		//IL_037a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0548: Unknown result type (might be due to invalid IL or missing references)
		if (!Object.op_Implicit((Object)(object)root) && !Build())
		{
			return;
		}
		bool flag = Object.op_Implicit((Object)(object)Player.m_localPlayer) && !((Character)Player.m_localPlayer).IsDead() && ((Object.op_Implicit((Object)(object)Minimap.instance) && (int)Minimap.instance.m_mode == 2) || (Object.op_Implicit((Object)(object)Hud.instance) && Hud.instance.IsVisible()));
		root.SetActive(flag);
		if (!flag)
		{
			if (Object.op_Implicit((Object)(object)mapUi))
			{
				((Component)mapUi).gameObject.SetActive(false);
			}
			return;
		}
		hud.anchoredPosition = new Vector2(0f, 0f - plugin.TopOffset.Value - 25f * plugin.HudScale.Value);
		((Transform)hud).localScale = Vector3.one * plugin.HudScale.Value;
		ApplyVisibility();
		ApplyColours();
		((Component)removeToggle).gameObject.SetActive(plugin.Active && plugin.EnableWaypoints.Value && Object.op_Implicit((Object)(object)Minimap.instance) && (int)Minimap.instance.m_mode == 2);
		removeToggle.SetIsOnWithoutNotify(plugin.AutoRemoveVisited.Value);
		removeCheck.SetActive(plugin.AutoRemoveVisited.Value);
		UpdateFilters(Object.op_Implicit((Object)(object)Minimap.instance) && (int)Minimap.instance.m_mode == 2);
		Camera mainCamera = Utils.GetMainCamera();
		float num = ((plugin.CameraHeading.Value && Object.op_Implicit((Object)(object)mainCamera)) ? ((Component)mainCamera).transform.eulerAngles.y : ((Component)Player.m_localPlayer).transform.eulerAngles.y);
		if (plugin.ShowCompass.Value)
		{
			for (int i = 0; i < bearings.Count; i++)
			{
				float num2 = NavigationMath.Delta((float)i * 22.5f, num);
				TextMeshProUGUI val = bearings[i];
				((Component)val).gameObject.SetActive(Math.Abs(num2) <= 90f);
				((TMP_Text)val).rectTransform.anchoredPosition = new Vector2(num2 * 3f, 0f);
				((TMP_Text)val).alpha = compassColour.a * Mathf.Clamp01((94f - Math.Abs(num2)) / 18f);
			}
			int num3 = Mathf.RoundToInt(num) % 360;
			if (previousHeading != num3)
			{
				((TMP_Text)heading).text = num3.ToString("000") + "°";
				previousHeading = num3;
			}
			List<Waypoint> points = plugin.Engine.Document.Points;
			int activeIndex = plugin.Engine.ActiveIndex;
			bool flag2 = plugin.Active && plugin.EnableWaypoints.Value && activeIndex >= 0 && plugin.Markers[MarkerKind.Waypoints].InCompassRange(((Component)Player.m_localPlayer).transform.position, new Vector3(points[activeIndex].X, points[activeIndex].Y, points[activeIndex].Z));
			((Component)destination).gameObject.SetActive(flag2);
			((Graphic)destination).color = plugin.Markers[MarkerKind.Waypoints].GetColour();
			((Graphic)target).color = ((Graphic)destination).color;
			((Component)nextDiamond).gameObject.SetActive(flag2);
			((Graphic)nextDiamond).color = ((Graphic)destination).color;
			if (flag2)
			{
				Vector3 position = ((Component)Player.m_localPlayer).transform.position;
				float distance = NavigationMath.Distance(points[activeIndex].X - position.x, points[activeIndex].Z - position.z);
				((Graphic)nextDiamond).rectTransform.sizeDelta = Vector2.one * (20f * plugin.Markers.IconScale(distance));
				float num4 = NavigationMath.Delta(NavigationMath.Bearing(points[activeIndex].X - position.x, points[activeIndex].Z - position.z), num);
				((TMP_Text)destination).rectTransform.anchoredPosition = new Vector2(Mathf.Clamp(num4, -90f, 90f) * 3f, -13f);
				((TMP_Text)destination).text = ((num4 < -90f) ? "‹" : ((num4 > 90f) ? "›" : ""));
				((Component)nextDiamond).gameObject.SetActive(Math.Abs(num4) <= 90f);
				((Graphic)nextDiamond).rectTransform.anchoredPosition = ((TMP_Text)destination).rectTransform.anchoredPosition;
			}
			UpdateMapMarkers(num);
		}
		if (!(Time.unscaledTime >= nextText))
		{
			return;
		}
		nextText = Time.unscaledTime + 0.1f;
		if (plugin.ShowClock.Value)
		{
			((TMP_Text)time).text = ((!Object.op_Implicit((Object)(object)EnvMan.instance)) ? "--" : (plugin.VagueTime.Value ? NavigationMath.VagueClock(EnvMan.instance.GetDayFraction()) : NavigationMath.Clock(EnvMan.instance.GetDayFraction(), plugin.TwelveHour.Value)));
		}
		if (plugin.ShowCompass.Value)
		{
			RouteDocument document = plugin.Engine.Document;
			int activeIndex2 = plugin.Engine.ActiveIndex;
			if (!((Component)destination).gameObject.activeSelf)
			{
				((TMP_Text)target).text = "";
				return;
			}
			Waypoint waypoint = document.Points[activeIndex2];
			Vector3 position2 = ((Component)Player.m_localPlayer).transform.position;
			float num5 = NavigationMath.Delta(NavigationMath.Bearing(waypoint.X - position2.x, waypoint.Z - position2.z), num);
			((TMP_Text)target).text = ((num5 < -8f) ? "‹ " : ((num5 > 8f) ? "› " : "◆ ")) + "Next Waypoint · " + Mathf.RoundToInt(NavigationMath.Distance(waypoint.X - position2.x, waypoint.Z - position2.z)) + " m";
		}
	}

	internal void ApplyVisibility()
	{
		//IL_0070: Unknown result type (might be due to invalid IL or missing references)
		compass.SetActive(plugin.ShowCompass.Value);
		clock.SetActive(plugin.ShowClock.Value);
		clock.GetComponent<RectTransform>().anchoredPosition = new Vector2(0f, plugin.ShowCompass.Value ? (0f - plugin.ClockOffset.Value) : 0f);
	}

	internal void ApplyColours()
	{
		//IL_011b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0071: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a7: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ac: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ad: 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_00b4: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b5: Unknown result type (might be due to invalid IL or missing references)
		//IL_00bc: Unknown result type (might be due to invalid IL or missing references)
		if (appliedCompassColour != plugin.CompassColour.Value)
		{
			appliedCompassColour = plugin.CompassColour.Value;
			if (!HudStyle.TryColour(appliedCompassColour, out compassColour))
			{
				plugin.Notice("Invalid CompassColor; using default warm white");
			}
			foreach (TextMeshProUGUI bearing in bearings)
			{
				((Graphic)bearing).color = compassColour;
			}
			TextMeshProUGUI obj = heading;
			TextMeshProUGUI obj2 = target;
			Color val = (((Graphic)destination).color = compassColour);
			Color color = (((Graphic)obj2).color = val);
			((Graphic)obj).color = color;
		}
		if (appliedClockColour != plugin.ClockColour.Value)
		{
			appliedClockColour = plugin.ClockColour.Value;
			if (!HudStyle.TryColour(appliedClockColour, out var colour))
			{
				plugin.Notice("Invalid ClockColor; using default warm white");
			}
			((Graphic)time).color = colour;
		}
	}

	private void Consider(Vector3 pos, Vector3 origin, Sprite icon, Color colour)
	{
		//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_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_00a3: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a4: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b1: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b3: Unknown result type (might be due to invalid IL or missing references)
		Vector2 val = new Vector2(pos.x - origin.x, pos.z - origin.z);
		float sqrMagnitude = ((Vector2)(ref val)).sqrMagnitude;
		int i;
		for (i = 0; i < nearby.Count; i++)
		{
			Vector2 val2 = new Vector2(nearby[i].Position.x - origin.x, nearby[i].Position.z - origin.z);
			if (!(((Vector2)(ref val2)).sqrMagnitude <= sqrMagnitude))
			{
				break;
			}
		}
		if (i < 16)
		{
			nearby.Insert(i, new CompassTarget
			{
				Position = pos,
				Icon = icon,
				Colour = colour
			});
			if (nearby.Count > 16)
			{
				nearby.RemoveAt(16);
			}
		}
	}

	private void UpdateMapMarkers(float direction)
	{
		//IL_000a: 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_0081: Unknown result type (might be due to invalid IL or missing references)
		//IL_0088: Unknown result type (might be due to invalid IL or missing references)
		//IL_0095: Unknown result type (might be due to invalid IL or missing references)
		//IL_009a: Unknown result type (might be due to invalid IL or missing references)
		//IL_00be: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c3: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ca: Unknown result type (might be due to invalid IL or missing references)
		//IL_03b4: Unknown result type (might be due to invalid IL or missing references)
		//IL_03d2: Unknown result type (might be due to invalid IL or missing references)
		//IL_0428: Unknown result type (might be due to invalid IL or missing references)
		//IL_0445: Unknown result type (might be due to invalid IL or missing references)
		//IL_01ab: 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_01b7: Unknown result type (might be due to invalid IL or missing references)
		//IL_01bc: Unknown result type (might be due to invalid IL or missing references)
		//IL_01db: Unknown result type (might be due to invalid IL or missing references)
		//IL_01dd: Unknown result type (might be due to invalid IL or missing references)
		//IL_01e4: Unknown result type (might be due to invalid IL or missing references)
		//IL_0287: Unknown result type (might be due to invalid IL or missing references)
		//IL_028d: Invalid comparison between Unknown and I4
		//IL_0291: Unknown result type (might be due to invalid IL or missing references)
		//IL_0298: Invalid comparison between Unknown and I4
		//IL_029c: Unknown result type (might be due to invalid IL or missing references)
		//IL_029f: Unknown result type (might be due to invalid IL or missing references)
		//IL_02ae: Unknown result type (might be due to invalid IL or missing references)
		//IL_02b3: Unknown result type (might be due to invalid IL or missing references)
		//IL_02bd: Unknown result type (might be due to invalid IL or missing references)
		Vector3 position = ((Component)Player.m_localPlayer).transform.position;
		if (Time.unscaledTime >= nextPinScan)
		{
			nextPinScan = Time.unscaledTime + 0.25f;
			nearby.Clear();
			foreach (TrackedObject value in plugin.Tracker.Objects.Values)
			{
				MarkerKind kind = (MarkerKind)value.Record.Kind;
				MarkerRule markerRule = plugin.Markers[kind];
				if (markerRule.InCompassRange(position, value.Record.Position))
				{
					Color colour = markerRule.GetColour();
					if (value.LastSeen)
					{
						colour.a *= 0.65f;
					}
					Consider(value.Record.Position, position, MarkerSprites.Get(kind), colour);
				}
			}
			if (plugin.Active && plugin.EnableWaypoints.Value)
			{
				MarkerRule markerRule2 = plugin.Markers[MarkerKind.Waypoints];
				Vector3 val = default(Vector3);
				foreach (Waypoint point in plugin.Engine.Document.Points)
				{
					if (plugin.Engine.ActiveIndex >= 0 && point == plugin.Engine.Document.Points[plugin.Engine.ActiveIndex])
					{
						continue;
					}
					((Vector3)(ref val))..ctor(point.X, point.Y, point.Z);
					if (markerRule2.InCompassRange(position, val))
					{
						Color colour2 = markerRule2.GetColour();
						if (point.Visited)
						{
							colour2.a *= 0.5f;
						}
						Consider(val, position, MarkerSprites.Get(MarkerKind.Waypoints), colour2);
					}
				}
			}
			Minimap instance = Minimap.instance;
			List<PinData> list = ((Object.op_Implicit((Object)(object)instance) && MapPins != null) ? (MapPins.GetValue(instance) as List<PinData>) : null);
			if (list != null)
			{
				foreach (PinData item in list)
				{
					MarkerRule markerRule3 = plugin.Markers[MarkerSettings.Category(item)];
					if (!item.m_checked && Object.op_Implicit((Object)(object)item.m_icon) && (int)item.m_type != 8 && (int)item.m_type != 13 && markerRule3.InCompassRange(position, item.m_pos))
					{
						Consider(item.m_pos, position, item.m_icon, markerRule3.GetColour());
					}
				}
			}
		}
		for (int i = 0; i < mapMarkers.Count; i++)
		{
			Image val2 = mapMarkers[i];
			bool flag = i < nearby.Count;
			float num = (flag ? NavigationMath.Delta(NavigationMath.Bearing(nearby[i].Position.x - position.x, nearby[i].Position.z - position.z), direction) : 0f);
			((Component)val2).gameObject.SetActive(flag && Math.Abs(num) <= 90f);
			if (flag)
			{
				val2.sprite = nearby[i].Icon;
				((Graphic)val2).color = nearby[i].Colour;
				((Graphic)val2).rectTransform.anchoredPosition = new Vector2(num * 3f, -13f);
				float distance = NavigationMath.Distance(nearby[i].Position.x - position.x, nearby[i].Position.z - position.z);
				((Graphic)val2).rectTransform.sizeDelta = Vector2.one * (18f * plugin.Markers.IconScale(distance));
			}
		}
		if (((TMP_Text)destination).transform.GetSiblingIndex() != compass.transform.childCount - 1)
		{
			((TMP_Text)destination).transform.SetAsLastSibling();
		}
	}

	internal void Hide()
	{
		if (Object.op_Implicit((Object)(object)root))
		{
			root.SetActive(false);
		}
		if (Object.op_Implicit((Object)(object)mapUi))
		{
			((Component)mapUi).gameObject.SetActive(false);
		}
	}

	internal void Reset()
	{
		if (Object.op_Implicit((Object)(object)mapUi))
		{
			Object.Destroy((Object)(object)((Component)mapUi).gameObject);
		}
		mapUi = null;
		if (Object.op_Implicit((Object)(object)root))
		{
			Object.Destroy((Object)(object)root);
		}
		root = null;
		bearings.Clear();
		mapMarkers.Clear();
		nearby.Clear();
		filterToggles.Clear();
		filterChecks.Clear();
		filtersOpen = false;
		previousHeading = -1;
		appliedCompassColour = (appliedClockColour = null);
	}
}
internal static class HudStyle
{
	internal static readonly Color DefaultColour = new Color(47f / 51f, 0.8509804f, 0.6784314f, 1f);

	internal static bool TryColour(string value, out Color colour)
	{
		//IL_015b: 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)
		string text = (value ?? "").Trim().ToLowerInvariant();
		switch (text)
		{
		case "gold":
			text = "#D4AF37";
			break;
		case "amber":
			text = "#FFBF00";
			break;
		case "ivory":
			text = "#FFFFF0";
			break;
		case "warmwhite":
		case "warm white":
			text = "#EBD9AD";
			break;
		case "gray":
			text = "grey";
			break;
		case "transparent":
			text = "#00000000";
			break;
		}
		if (text.Length == 3 || text.Length == 4 || text.Length == 6 || text.Length == 8)
		{
			bool flag = true;
			string text2 = text;
			foreach (char character in text2)
			{
				if (!Uri.IsHexDigit(character))
				{
					flag = false;
					break;
				}
			}
			if (flag)
			{
				text = "#" + text;
			}
		}
		if (ColorUtility.TryParseHtmlString(text, ref colour))
		{
			return true;
		}
		colour = DefaultColour;
		return false;
	}
}
internal enum MarkerKind
{
	Ships,
	Carts,
	Portals,
	Waypoints,
	SavedPins,
	Beds,
	Bosses,
	Deaths,
	Players,
	Events,
	Pings,
	Locations,
	OtherPins
}
internal sealed class MarkerRule
{
	internal readonly ConfigEntry<bool> Map;

	internal readonly ConfigEntry<bool> Compass;

	internal readonly ConfigEntry<string> Colour;

	internal readonly ConfigEntry<float> Range;

	private string cached;

	private Color colour;

	internal MarkerRule(ConfigFile config, MarkerKind kind, bool map, bool compass, string defaultColour, ConfigEntry<float> range)
	{
		string text = "Markers - " + kind;
		Map = config.Bind<bool>(text, "ShowOnMap", map, "Show this category on the map. This changes visibility, never deletes objects or saved pins.");
		Compass = config.Bind<bool>(text, "ShowOnCompass", compass, "Show this category on the compass independently of its map filter.");
		Colour = config.Bind<string>(text, "Color", defaultColour, "Hex RGB/RGBA or a colour name, such as yellow, cyan, gold or red. Applies to map icons, labels and compass markers.");
		Range = range;
	}

	internal Color GetColour()
	{
		//IL_0058: Unknown result type (might be due to invalid IL or missing references)
		if (cached != Colour.Value)
		{
			cached = Colour.Value;
			if (!HudStyle.TryColour(cached, out colour) && Object.op_Implicit((Object)(object)Plugin.Instance))
			{
				Plugin.Instance.Notice("Invalid marker colour; using warm white");
			}
		}
		return colour;
	}

	internal bool InCompassRange(Vector3 origin, Vector3 position)
	{
		if (Compass.Value)
		{
			return NavigationMath.Distance(position.x - origin.x, position.z - origin.z) <= Range.Value;
		}
		return false;
	}
}
internal sealed class MarkerSettings
{
	private readonly MarkerRule[] rules;

	internal readonly ConfigEntry<float> CompassRange;

	internal readonly ConfigEntry<float> MarkerMinSize;

	internal readonly ConfigEntry<float> MarkerMaxSize;

	internal MarkerRule this[MarkerKind kind] => rules[(int)kind];

	internal float IconScale(float distance)
	{
		float num = Mathf.Min(MarkerMinSize.Value, MarkerMaxSize.Value);
		float num2 = Mathf.Max(MarkerMinSize.Value, MarkerMaxSize.Value);
		return Mathf.Lerp(num2, num, Mathf.Clamp01(distance / CompassRange.Value));
	}

	internal MarkerSettings(ConfigFile config, string defaultColour = "#EBD9AD", bool savedCompass = true)
	{
		//IL_0031: Unknown result type (might be due to invalid IL or missing references)
		//IL_003b: Expected O, but got Unknown
		//IL_006b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0075: Expected O, but got Unknown
		//IL_00a5: Unknown result type (might be due to invalid IL or missing references)
		//IL_00af: Expected O, but got Unknown
		CompassRange = config.Bind<float>("Display", "CompassRange", 300f, new ConfigDescription("Shared maximum horizontal distance in metres for all compass marker categories, including waypoints. Does not limit map visibility.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 20000f), new object[0]));
		MarkerMinSize = config.Bind<float>("Display", "MarkerMinSize", 0.5f, new ConfigDescription("Global compass icon size at the range limit, relative to original size: 0.5 = 50%, 0.1 = 10%. Applies to all categories and waypoint diamonds. If min exceeds max, the two bounds are treated in ascending order.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.05f, 5f), new object[0]));
		MarkerMaxSize = config.Bind<float>("Display", "MarkerMaxSize", 1.2f, new ConfigDescription("Global compass icon size up close, relative to original size: 1.2 = 120%, 2 = 200%. Icons scale smoothly using CompassRange. Equal minimum and maximum give a fixed size.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.05f, 5f), new object[0]));
		rules = new MarkerRule[13]
		{
			new MarkerRule(config, MarkerKind.Ships, map: true, compass: true, "yellow", CompassRange),
			new MarkerRule(config, MarkerKind.Carts, map: true, compass: true, "cyan", CompassRange),
			new MarkerRule(config, MarkerKind.Portals, map: true, compass: true, "red", CompassRange),
			new MarkerRule(config, MarkerKind.Waypoints, map: true, compass: true, defaultColour, CompassRange),
			new MarkerRule(config, MarkerKind.SavedPins, map: true, savedCompass, defaultColour, CompassRange),
			new MarkerRule(config, MarkerKind.Beds, map: true, compass: true, defaultColour, CompassRange),
			new MarkerRule(config, MarkerKind.Bosses, map: true, compass: true, defaultColour, CompassRange),
			new MarkerRule(config, MarkerKind.Deaths, map: true, compass: true, defaultColour, CompassRange),
			new MarkerRule(config, MarkerKind.Players, map: true, compass: true, defaultColour, CompassRange),
			new MarkerRule(config, MarkerKind.Events, map: true, compass: true, defaultColour, CompassRange),
			new MarkerRule(config, MarkerKind.Pings, map: true, compass: true, defaultColour, CompassRange),
			new MarkerRule(config, MarkerKind.Locations, map: true, compass: true, defaultColour, CompassRange),
			new MarkerRule(config, MarkerKind.OtherPins, map: true, compass: true, defaultColour, CompassRange)
		};
	}

	internal static void RemoveObsoleteSettings(ConfigFile config)
	{
		string[] array = new string[3] { "RouteManager", "AddAtFeet", "AddAtAim" };
		foreach (string text in array)
		{
			config.Remove(((ConfigEntryBase)config.Bind<string>("Controls", text, "", (ConfigDescription)null)).Definition);
		}
		config.Remove(((ConfigEntryBase)config.Bind<string>("Waypoints", "AutomaticArrival", "", (ConfigDescription)null)).Definition);
		config.Remove(((ConfigEntryBase)config.Bind<string>("Display", "MarkerScale", "", (ConfigDescription)null)).Definition);
		foreach (MarkerKind value in Enum.GetValues(typeof(MarkerKind)))
		{
			config.Remove(((ConfigEntryBase)config.Bind<string>("Markers - " + value, "CompassRange", "", (ConfigDescription)null)).Definition);
		}
	}

	internal static MarkerKind Category(PinData pin)
	{
		//IL_0001: Unknown result type (might be due to invalid IL or missing references)
		//IL_0007: Expected I4, but got Unknown
		switch ((int)pin.m_type)
		{
		case 0:
		case 1:
		case 2:
		case 3:
		case 6:
			return MarkerKind.SavedPins;
		case 4:
			return MarkerKind.Deaths;
		case 5:
			return MarkerKind.Beds;
		case 9:
			return MarkerKind.Bosses;
		case 10:
			return MarkerKind.Players;
		case 7:
		case 12:
			return MarkerKind.Pings;
		case 11:
		case 13:
			return MarkerKind.Events;
		case 14:
		case 15:
		case 16:
		case 17:
			return MarkerKind.Locations;
		default:
			return MarkerKind.OtherPins;
		}
	}
}
internal static class MarkerSprites
{
	private static readonly Sprite[] sprites = (Sprite[])(object)new Sprite[4];

	internal static Sprite Get(MarkerKind kind)
	{
		//IL_0477: Unknown result type (might be due to invalid IL or missing references)
		//IL_047e: Expected O, but got Unknown
		//IL_04c8: Unknown result type (might be due to invalid IL or missing references)
		//IL_04d7: Unknown result type (might be due to invalid IL or missing references)
		//IL_004e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0053: Unknown result type (might be due to invalid IL or missing references)
		//IL_0264: Unknown result type (might be due to invalid IL or missing references)
		//IL_0269: Unknown result type (might be due to invalid IL or missing references)
		//IL_0290: Unknown result type (might be due to invalid IL or missing references)
		//IL_0295: Unknown result type (might be due to invalid IL or missing references)
		//IL_044f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0454: Unknown result type (might be due to invalid IL or missing references)
		//IL_030e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0313: Unknown result type (might be due to invalid IL or missing references)
		//IL_0376: Unknown result type (might be due to invalid IL or missing references)
		//IL_037b: Unknown result type (might be due to invalid IL or missing references)
		int num = Math.Min((int)kind, 3);
		if (Object.op_Implicit((Object)(object)sprites[num]))
		{
			return sprites[num];
		}
		Color32[] array = (Color32[])(object)new Color32[4096];
		for (int i = 0; i < 64; i++)
		{
			for (int j = 0; j < 64; j++)
			{
				float num2 = 100f;
				switch (num)
				{
				case 0:
				{
					Vector2 val5 = new Vector2((float)(j - 32), (float)(i - 52));
					num2 = Math.Abs(((Vector2)(ref val5)).magnitude - 6f);
					num2 = Math.Min(num2, Line(j, i, 32f, 46f, 32f, 12f));
					num2 = Math.Min(num2, Line(j, i, 23f, 37f, 41f, 37f));
					num2 = Math.Min(num2, Line(j, i, 12f, 29f, 18f, 18f));
					num2 = Math.Min(num2, Line(j, i, 18f, 18f, 32f, 12f));
					num2 = Math.Min(num2, Line(j, i, 32f, 12f, 46f, 18f));
					num2 = Math.Min(num2, Line(j, i, 46f, 18f, 52f, 29f));
					num2 = Math.Min(num2, Line(j, i, 12f, 29f, 12f, 20f));
					num2 = Math.Min(num2, Line(j, i, 52f, 29f, 52f, 20f));
					break;
				}
				case 1:
				{
					num2 = Math.Min(Line(j, i, 11f, 44f, 50f, 44f), Line(j, i, 11f, 44f, 16f, 25f));
					num2 = Math.Min(num2, Line(j, i, 16f, 25f, 45f, 25f));
					num2 = Math.Min(num2, Line(j, i, 45f, 25f, 50f, 44f));
					num2 = Math.Min(num2, Line(j, i, 50f, 44f, 59f, 49f));
					float val6 = num2;
					Vector2 val7 = new Vector2((float)(j - 20), (float)(i - 15));
					num2 = Math.Min(val6, Math.Abs(((Vector2)(ref val7)).magnitude - 5f));
					float val8 = num2;
					Vector2 val9 = new Vector2((float)(j - 42), (float)(i - 15));
					num2 = Math.Min(val8, Math.Abs(((Vector2)(ref val9)).magnitude - 5f));
					break;
				}
				case 2:
					num2 = Math.Min(Line(j, i, 14f, 10f, 14f, 36f), Line(j, i, 50f, 10f, 50f, 36f));
					if (i >= 36)
					{
						float val = num2;
						Vector2 val2 = new Vector2((float)(j - 32), (float)(i - 36));
						num2 = Math.Min(val, Math.Abs(((Vector2)(ref val2)).magnitude - 18f));
					}
					num2 = Math.Min(num2, Line(j, i, 10f, 10f, 54f, 10f));
					if (i >= 21 && i <= 39)
					{
						float val3 = num2;
						Vector2 val4 = new Vector2((float)(j - 32) * 1.6f, (float)(i - 30));
						num2 = Math.Min(val3, Math.Abs(((Vector2)(ref val4)).magnitude - 10f));
					}
					break;
				default:
					num2 = Math.Min(Math.Min(Line(j, i, 32f, 55f, 52f, 32f), Line(j, i, 52f, 32f, 32f, 9f)), Math.Min(Line(j, i, 32f, 9f, 12f, 32f), Line(j, i, 12f, 32f, 32f, 55f)));
					break;
				}
				ref Color32 reference = ref array[i * 64 + j];
				reference = new Color32(byte.MaxValue, byte.MaxValue, byte.MaxValue, (byte)(255f * Mathf.Clamp01(3f - num2)));
			}
		}
		Texture2D val10 = new Texture2D(64, 64, (TextureFormat)4, false);
		((Object)val10).name = "CWC " + kind;
		val10.SetPixels32(array);
		val10.Apply();
		((Texture)val10).wrapMode = (TextureWrapMode)1;
		sprites[num] = Sprite.Create(val10, new Rect(0f, 0f, 64f, 64f), new Vector2(0.5f, 0.5f), 64f);
		return sprites[num];
	}

	private static float Line(float x, float y, float ax, float ay, float bx, float by)
	{
		//IL_001c: 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_001e: Unknown result type (might be due to invalid IL or missing references)
		//IL_001f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0032: 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)
		Vector2 val = default(Vector2);
		((Vector2)(ref val))..ctor(x - ax, y - ay);
		Vector2 val2 = default(Vector2);
		((Vector2)(ref val2))..ctor(bx - ax, by - ay);
		Vector2 val3 = val - val2 * Mathf.Clamp01(Vector2.Dot(val, val2) / ((Vector2)(ref val2)).sqrMagnitude);
		return ((Vector2)(ref val3)).magnitude;
	}

	internal static void Release()
	{
		for (int i = 0; i < sprites.Length; i++)
		{
			if (Object.op_Implicit((Object)(object)sprites[i]))
			{
				Object.Destroy((Object)(object)sprites[i].texture);
				Object.Destroy((Object)(object)sprites[i]);
				sprites[i] = null;
			}
		}
	}
}
public static class NavigationApi
{
	public const int ApiVersion = 1;

	public static bool IsReady
	{
		get
		{
			if (Object.op_Implicit((Object)(object)Plugin.Instance) && Plugin.Instance.Active)
			{
				return Plugin.Instance.EnableWaypoints.Value;
			}
			return false;
		}
	}

	public static Waypoint[] GetRoute()
	{
		if (!IsReady)
		{
			return new Waypoint[0];
		}
		return Plugin.Instance.Engine.Document.Points.ConvertAll((Waypoint p) => p.Copy()).ToArray();
	}

	public static bool TryAppend(string label, Vector3 position, bool checkHeight)
	{
		if (!IsReady)
		{
			return false;
		}
		Plugin instance = Plugin.Instance;
		Waypoint waypoint = new Waypoint();
		waypoint.Name = NavigationMath.Clean(label);
		waypoint.X = position.x;
		waypoint.Y = position.y;
		waypoint.Z = position.z;
		waypoint.CheckHeight = checkHeight;
		Waypoint waypoint2 = waypoint;
		if (string.IsNullOrEmpty(waypoint2.Name) || !instance.Engine.Add(waypoint2, instance.Now))
		{
			return false;
		}
		instance.Commit();
		if (!instance.Active)
		{
			return false;
		}
		instance.Notice("Waypoint added: " + waypoint2.Name);
		return true;
	}
}
internal sealed class ObjectMapView
{
	private sealed class Marker
	{
		internal RectTransform Root;

		internal Image Icon;

		internal TMP_Text Text;

		internal string Label;

		internal bool Stale;
	}

	private readonly Plugin plugin;

	private readonly Dictionary<string, Marker> markers = new Dictionary<string, Marker>();

	private readonly HashSet<string> shown = new HashSet<string>();

	private RectTransform overlay;

	private RawImage image;

	private static readonly MarkerKind[] Priority = new MarkerKind[3]
	{
		MarkerKind.Ships,
		MarkerKind.Portals,
		MarkerKind.Carts
	};

	private int revision = -1;

	private readonly List<string> waypointLabels = new List<string>();

	internal ObjectMapView(Plugin owner)
	{
		plugin = owner;
	}

	internal static bool Project(Vector3 position, int textureSize, float pixelSize, Rect uv, Rect rect, out Vector2 local)
	{
		//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_0061: 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_00b0: Unknown result type (might be due to invalid IL or missing references)
		local = Vector2.zero;
		if (textureSize <= 0 || pixelSize <= 0f || ((Rect)(ref uv)).width <= 0f || ((Rect)(ref uv)).height <= 0f)
		{
			return false;
		}
		Vector2 val = default(Vector2);
		((Vector2)(ref val))..ctor((position.x / pixelSize + (float)(textureSize / 2)) / (float)textureSize, (position.z / pixelSize + (float)(textureSize / 2)) / (float)textureSize);
		if (!((Rect)(ref uv)).Contains(val))
		{
			return false;
		}
		local = new Vector2((val.x - ((Rect)(ref uv)).xMin) / ((Rect)(ref uv)).width * ((Rect)(ref rect)).width, (val.y - ((Rect)(ref uv)).yMin) / ((Rect)(ref uv)).height * ((Rect)(ref rect)).height);
		return true;
	}

	internal void Draw()
	{
		//IL_001b: 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_0030: Invalid comparison between Unknown and I4
		//IL_00da: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ea: Unknown result type (might be due to invalid IL or missing references)
		//IL_0100: Unknown result type (might be due to invalid IL or missing references)
		//IL_0105: Unknown result type (might be due to invalid IL or missing references)
		//IL_0106: Unknown result type (might be due to invalid IL or missing references)
		//IL_010d: 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_01eb: Unknown result type (might be due to invalid IL or missing references)
		//IL_037d: Unknown result type (might be due to invalid IL or missing references)
		Minimap instance = Minimap.instance;
		if (!Object.op_Implicit((Object)(object)instance) || !Object.op_Implicit((Object)(object)Player.m_localPlayer) || (int)instance.m_mode == 0)
		{
			Hide();
			return;
		}
		RawImage val = (((int)instance.m_mode == 2) ? instance.m_mapImageLarge : instance.m_mapImageSmall);
		if (!Object.op_Implicit((Object)(object)val))
		{
			Hide();
			return;
		}
		if ((Object)(object)image != (Object)(object)val || !Object.op_Implicit((Object)(object)overlay))
		{
			image = val;
			if (!Object.op_Implicit((Object)(object)overlay))
			{
				overlay = new GameObject("CWC object markers", new Type[2]
				{
					typeof(RectTransform),
					typeof(RectMask2D)
				}).GetComponent<RectTransform>();
			}
			((Transform)overlay).SetParent(((Component)image).transform, false);
			overlay.anchorMin = Vector2.zero;
			overlay.anchorMax = Vector2.one;
			RectTransform obj = overlay;
			Vector2 offsetMin = (overlay.offsetMax = Vector2.zero);
			obj.offsetMin = offsetMin;
		}
		((Component)overlay).gameObject.SetActive(true);
		shown.Clear();
		TMP_FontAsset val2 = ((Object.op_Implicit((Object)(object)InventoryGui.instance) && Object.op_Implicit((Object)(object)InventoryGui.instance.m_playerName)) ? InventoryGui.instance.m_playerName.font : TMP_Settings.defaultFontAsset);
		if (!Object.op_Implicit((Object)(object)val2))
		{
			return;
		}
		MarkerKind[] priority = Priority;
		foreach (MarkerKind markerKind in priority)
		{
			if (!plugin.Markers[markerKind].Map.Value)
			{
				continue;
			}
			foreach (KeyValuePair<ZDOID, TrackedObject> @object in plugin.Tracker.Objects)
			{
				TrackedObject value = @object.Value;
				if (value.Record.Kind == (int)markerKind)
				{
					DrawOne(value.Key, value.Record.Position, markerKind, value.Record.Name, value.LastSeen, val2, instance);
				}
			}
		}
		if (plugin.Active && revision != plugin.Engine.Revision)
		{
			revision = plugin.Engine.Revision;
			waypointLabels.Clear();
			for (int j = 0; j < plugin.Engine.Document.Points.Count; j++)
			{
				waypointLabels.Add(plugin.Engine.Label(j) + (plugin.Engine.Document.Points[j].Visited ? " (visited)" : ""));
			}
		}
		if (plugin.Active && plugin.EnableWaypoints.Value && plugin.Markers[MarkerKind.Waypoints].Map.Value)
		{
			for (int k = 0; k < plugin.Engine.Document.Points.Count; k++)
			{
				Waypoint waypoint = plugin.Engine.Document.Points[k];
				DrawOne(waypoint.Id, new Vector3(waypoint.X, waypoint.Y, waypoint.Z), MarkerKind.Waypoints, waypointLabels[k], stale: false, val2, instance);
			}
		}
		foreach (KeyValuePair<string, Marker> marker in markers)
		{
			if (!shown.Contains(marker.Key))
			{
				((Component)marker.Value.Root).gameObject.SetActive(false);
			}
		}
	}

	private void DrawOne(string key, Vector3 position, MarkerKind kind, string label, bool stale, TMP_FontAsset font, Minimap map)
	{
		//IL_0012: Unknown result type (might be due to invalid IL or missing references)
		//IL_0027: Unknown result type (might be due to invalid IL or missing references)
		//IL_0037: Unknown result type (might be due to invalid IL or missing references)
		//IL_0205: Unknown result type (might be due to invalid IL or missing references)
		//IL_008e: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a8: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ad: 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_00b5: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c7: Unknown result type (might be due to invalid IL or missing references)
		//IL_0114: 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_014b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0267: Unknown result type (might be due to invalid IL or missing references)
		//IL_026c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0291: Unknown result type (might be due to invalid IL or missing references)
		//IL_0293: Unknown result type (might be due to invalid IL or missing references)
		//IL_0294: Unknown result type (might be due to invalid IL or missing references)
		//IL_029b: Unknown result type (might be due to invalid IL or missing references)
		//IL_02af: Unknown result type (might be due to invalid IL or missing references)
		//IL_02b5: Invalid comparison between Unknown and I4
		if (shown.Count < 512 && Project(position, map.m_textureSize, map.m_pixelSize, image.uvRect, ((Graphic)image).rectTransform.rect, out var local))
		{
			shown.Add(key);
			if (!markers.TryGetValue(key, out var value))
			{
				RectTransform component = new GameObject("CWC " + kind, new Type[1] { typeof(RectTransform) }).GetComponent<RectTransform>();
				((Transform)component).SetParent((Transform)(object)overlay, false);
				Vector2 anchorMin = (component.anchorMax = Vector2.zero);
				component.anchorMin = anchorMin;
				component.sizeDelta = new Vector2(28f, 28f);
				Image val = ((Component)component).gameObject.AddComponent<Image>();
				val.sprite = MarkerSprites.Get(kind);
				((Graphic)val).raycastTarget = false;
				val.preserveAspect = true;
				RectTransform component2 = new GameObject("Label", new Type[1] { typeof(RectTransform) }).GetComponent<RectTransform>();
				((Transform)component2).SetParent((Transform)(object)component, false);
				component2.anchoredPosition = new Vector2(0f, -26f);
				component2.sizeDelta = new Vector2(200f, 24f);
				((Component)component2).gameObject.SetActive(false);
				TextMeshProUGUI val2 = ((Component)component2).gameObject.AddComponent<TextMeshProUGUI>();
				((TMP_Text)val2).font = font;
				((TMP_Text)val2).fontSize = 14f;
				((TMP_Text)val2).alignment = (TextAlignmentOptions)514;
				((TMP_Text)val2).richText = false;
				((Graphic)val2).raycastTarget = false;
				((TMP_Text)val2).textWrappingMode = (TextWrappingModes)0;
				((TMP_Text)val2).overflowMode = (TextOverflowModes)1;
				((Component)component2).gameObject.SetActive(true);
				Marker marker = new Marker();
				marker.Root = component;
				marker.Icon = val;
				marker.Text = (TMP_Text)(object)val2;
				value = marker;
				markers.Add(key, value);
			}
			((Component)value.Root).gameObject.SetActive(true);
			value.Root.anchoredPosition = local;
			if (value.Label != label || value.Stale != stale)
			{
				value.Label = label;
				value.Stale = stale;
				value.Text.text = label + (stale ? " (last seen)" : "");
			}
			Color colour = plugin.Markers[kind].GetColour();
			if (stale)
			{
				colour.a *= 0.65f;
			}
			Image icon = value.Icon;
			Color color = (((Graphic)value.Text).color = colour);
			((Graphic)icon).color = color;
			((Component)value.Text).gameObject.SetActive((int)map.m_mode == 2);
		}
	}

	internal void Hide()
	{
		if (Object.op_Implicit((Object)(object)overlay))
		{
			((Component)overlay).gameObject.SetActive(false);
		}
	}

	internal void Reset()
	{
		if (Object.op_Implicit((Object)(object)overlay))
		{
			Object.Destroy((Object)(object)((Component)overlay).gameObject);
		}
		overlay = null;
		image = null;
		markers.Clear();
		shown.Clear();
		revision = -1;
		waypointLabels.Clear();
	}
}
internal sealed class TrackedObject
{
	internal TrackedRecord Record;

	internal Component Live;

	internal bool LastSeen = true;

	internal string Key;
}
internal sealed class ObjectTracker
{
	internal readonly Dictionary<ZDOID, TrackedObject> Objects = new Dictionary<ZDOID, TrackedObject>();

	private readonly Plugin plugin;

	private long world;

	private long character;

	private string path;

	private bool dirty;

	private bool readOnly;

	private bool limitWarned;

	private float nextUpdate;

	private float nextSave;

	internal ObjectTracker(Plugin owner)
	{
		plugin = owner;
	}

	internal void Begin(long w, long c)
	{
		//IL_0085: Unknown result type (might be due to invalid IL or missing references)
		End();
		world = w;
		character = c;
		if (w == 0 || c == 0)
		{
			return;
		}
		path = Path.Combine(Paths.ConfigPath, "CompassWaypointsClock", w.ToString("X16") + "-" + c.ToString("X16") + ".objects");
		try
		{
			bool recovered;
			TrackedDocument trackedDocument = TrackedStore.Load(path, w, c, out recovered);
			TrackedRecord[] records = trackedDocument.Records;
			foreach (TrackedRecord trackedRecord in records)
			{
				Objects[trackedRecord.Uid] = new TrackedObject
				{
					Record = trackedRecord,
					Key = trackedRecord.User + ":" + trackedRecord.Id
				};
			}
			if (recovered)
			{
				plugin.Notice("Recovered tracked-object backup; damaged cache preserved");
			}
		}
		catch (Exception ex)
		{
			readOnly = true;
			plugin.Notice("Tracked-object cache could not be read; keeping its files untouched. Loaded objects still display. " + ex.Message);
		}
		Ship[] array = Object.FindObjectsByType<Ship>((FindObjectsSortMode)0);
		foreach (Ship component in array)
		{
			Observe((Component)(object)component);
		}
		Vagon[] array2 = Object.FindObjectsByType<Vagon>((FindObjectsSortMode)0);
		foreach (Vagon component2 in array2)
		{
			Observe((Component)(object)component2);
		}
		TeleportWorld[] array3 = Object.FindObjectsByType<TeleportWorld>((FindObjectsSortMode)0);
		foreach (TeleportWorld component3 in array3)
		{
			Observe((Component)(object)component3);
		}
	}

	internal void Observe(Component component)
	{
		//IL_002e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0033: Unknown result type (might be due to invalid IL or missing references)
		//IL_0062: 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)
		if (world == 0 || !Object.op_Implicit((Object)(object)component))
		{
			return;
		}
		ZNetView component2 = component.GetComponent<ZNetView>();
		if (Object.op_Implicit((Object)(object)component2))
		{
			ZDO zDO = component2.GetZDO();
			if (zDO != null && !(zDO.m_uid == ZDOID.None))
			{
				MarkerKind kind = ((!(component is Ship)) ? ((component is Vagon) ? MarkerKind.Carts : MarkerKind.Portals) : MarkerKind.Ships);
				string name = Name(component, kind);
				Upsert(zDO.m_uid, zDO.GetPrefab(), kind, name, component.transform.position, component);
			}
		}
	}

	internal void Upsert(ZDOID id, int prefab, MarkerKind kind, string name, Vector3 position, Component live)
	{
		//IL_0006: 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_0126: Unknown result type (might be due to invalid IL or missing references)
		//IL_012b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0081: Unknown result type (might be due to invalid IL or missing references)
		//IL_0100: Unknown result type (might be due to invalid IL or missing references)
		if (!Objects.TryGetValue(id, out var value))
		{
			if (Objects.Count >= 4096)
			{
				if (!limitWarned)
				{
					plugin.Notice("Tracked-object limit reached; existing markers retained");
					limitWarned = true;
				}
				return;
			}
			TrackedRecord trackedRecord = new TrackedRecord();
			trackedRecord.User = ((ZDOID)(ref id)).UserID;
			trackedRecord.Id = ((ZDOID)(ref id)).ID;
			trackedRecord.Prefab = prefab;
			trackedRecord.Kind = (int)kind;
			trackedRecord.Name = NavigationMath.Clean(name);
			trackedRecord.Position = position;
			TrackedRecord trackedRecord2 = trackedRecord;
			TrackedDocument trackedDocument = new TrackedDocument();
			trackedDocument.World = 1L;
			trackedDocument.Character = 1L;
			trackedDocument.Records = new TrackedRecord[1] { trackedRecord2 };
			TrackedStore.Validate(trackedDocument, 1L, 1L);
			TrackedObject trackedObject = new TrackedObject();
			trackedObject.Record = trackedRecord2;
			trackedObject.Key = ((ZDOID)(ref id)).UserID + ":" + ((ZDOID)(ref id)).ID;
			value = trackedObject;
			Objects.Add(id, value);
			dirty = true;
		}
		else if (value.Record.Prefab != prefab)
		{
			Forget(id);
			Upsert(id, prefab, kind, name, position, live);
			return;
		}
		value.Live = live;
		value.LastSeen = !Object.op_Implicit((Object)(object)live);
	}

	private static string Name(Component component, MarkerKind kind)
	{
		//IL_0005: Unknown result type (might be due to invalid IL or missing references)
		switch (kind)
		{
		case MarkerKind.Portals:
		{
			string text = ((TeleportWorld)component).GetText();
			if (!string.IsNullOrWhiteSpace(text))
			{
				return NavigationMath.Clean(text);
			}
			return "Portal";
		}
		case MarkerKind.Carts:
			return "Cart";
		default:
		{
			string prefabName = Utils.GetPrefabName(component.gameObject);
			return prefabName switch
			{
				"VikingShip" => "Longship", 
				"Karve" => "Karve", 
				"Raft" => "Raft", 
				"Drakkar" => "Drakkar", 
				_ => NavigationMath.Clean(prefabName), 
			};
		}
		}
	}

	internal void Tick()
	{
		//IL_006e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0073: Unknown result type (might be due to invalid IL or missing references)
		//IL_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_0097: 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_00c5: Unknown result type (might be due to invalid IL or missing references)
		if (world == 0 || Time.unscaledTime < nextUpdate)
		{
			return;
		}
		nextUpdate = Time.unscaledTime + 0.25f;
		foreach (TrackedObject value in Objects.Values)
		{
			value.LastSeen = !Object.op_Implicit((Object)(object)value.Live);
			if (!value.LastSeen)
			{
				Vector3 position = value.Live.transform.position;
				string text = Name(value.Live, (MarkerKind)value.Record.Kind);
				Vector3 val = position - value.Record.Position;
				if (((Vector3)(ref val)).sqrMagnitude > 0.01f || value.Record.Name != text)
				{
					value.Record.Position = position;
					value.Record.Name = text;
					dirty = true;
				}
			}
		}
		if (Time.unscaledTime >= nextSave)
		{
			nextSave = Time.unscaledTime + 15f;
			Flush();
		}
	}

	internal void Forget(ZDOID id)
	{
		//IL_0006: Unknown result type (might be due to invalid IL or missing references)
		if (Objects.Remove(id))
		{
			dirty = true;
		}
	}

	private void Flush()
	{
		if (!dirty || readOnly || world == 0)
		{
			return;
		}
		try
		{
			List<TrackedRecord> list = new List<TrackedRecord>();
			foreach (TrackedObject value in Objects.Values)
			{
				list.Add(value.Record);
			}
			TrackedStore.Save(path, new TrackedDocument
			{
				World = world,
				Character = character,
				Records = list.ToArray()
			});
			dirty = false;
		}
		catch (Exception ex)
		{
			readOnly = true;
			plugin.Notice("Could not save tracked objects; previous cache preserved. " + ex.Message);
		}
	}

	internal void End()
	{
		Flush();
		Objects.Clear();
		world = (character = 0L);
		dirty = (readOnly = (limitWarned = false));
		nextUpdate = (nextSave = 0f);
	}
}
[HarmonyPatch]
internal static class DiscoverTrackedObject
{
	private static IEnumerable<MethodBase> TargetMethods()
	{
		try
		{
			Type[] array = new Type[3]
			{
				typeof(Ship),
				typeof(Vagon),
				typeof(TeleportWorld)
			};
			foreach (Type type in array)
			{
				yield return AccessTools.Method(type, "Awake", (Type[])null, (Type[])null);
			}
		}
		finally
		{
		}
	}

	private static void Postfix(Component __instance)
	{
		Plugin instance = Plugin.Instance;
		if (Object.op_Implicit((Object)(object)instance) && instance.Tracker != null)
		{
			try
			{
				instance.Tracker.Observe(__instance);
			}
			catch (Exception ex)
			{
				instance.Notice("Object discovery failed: " + ex.Message);
			}
		}
	}
}
[HarmonyPatch(typeof(ZDOMan), "HandleDestroyedZDO")]
internal static class RemoveDestroyedTrackedObject
{
	private static void Postfix(ZDOID uid)
	{
		//IL_001c: Unknown result type (might be due to invalid IL or missing references)
		Plugin instance = Plugin.Instance;
		if (Object.op_Implicit((Object)(object)instance) && instance.Tracker != null)
		{
			instance.Tracker.Forget(uid);
		}
	}
}
[BepInPlugin("au.tyvalheim.compasswaypointsclock", "Compass Waypoints and Clock", "0.1.8")]
public sealed class Plugin : BaseUnityPlugin
{
	public const string Id = "au.tyvalheim.compasswaypointsclock";

	internal static Plugin Instance;

	internal ConfigEntry<bool> ShowCompass;

	internal ConfigEntry<bool> ShowClock;

	internal ConfigEntry<bool> TwelveHour;

	internal ConfigEntry<bool> CameraHeading;

	internal ConfigEntry<bool> AutoRemoveVisited;

	internal ConfigEntry<bool> Diagnostics;

	internal ConfigEntry<bool> EnableWaypoints;

	internal ConfigEntry<bool> VagueTime;

	internal ConfigEntry<bool> ArrivalChime;

	internal ConfigEntry<float> ArrivalVolume;

	private readonly ArrivalSound arrivalSound = new ArrivalSound();

	internal ConfigEntry<string> CompassColour;

	internal ConfigEntry<string> ClockColour;

	internal ConfigEntry<float> Radius;

	internal ConfigEntry<float> HeightTolerance;

	internal ConfigEntry<float> HudScale;

	internal ConfigEntry<float> TopOffset;

	internal ConfigEntry<float> ClockOffset;

	internal RouteEngine Engine;

	internal Display View;

	internal MarkerSettings Markers;

	internal ObjectTracker Tracker;

	internal ObjectMapView ObjectMap;

	private Harmony harmony;

	private long world;

	private long character;

	private string path;

	private bool storageFault;

	private float nextArrival;

	private Vector3 lastPosition;

	private bool havePosition;

	private int savedRevision;

	private bool displayFault;

	internal bool Active
	{
		get
		{
			if (Engine != null)
			{
				return !storageFault;
			}
			return false;
		}
	}

	internal double Now => Time.unscaledTime;

	private void Awake()
	{
		//IL_014d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0157: Expected O, but got Unknown
		//IL_018c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0196: Expected O, but got Unknown
		//IL_01cb: Unknown result type (might be due to invalid IL or missing references)
		//IL_01d5: Expected O, but got Unknown
		//IL_026d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0277: Expected O, but got Unknown
		//IL_02ac: Unknown result type (might be due to invalid IL or missing references)
		//IL_02b6: Expected O, but got Unknown
		//IL_02eb: Unknown result type (might be due to invalid IL or missing references)
		//IL_02f5: Expected O, but got Unknown
		//IL_03b2: Unknown result type (might be due to invalid IL or missing references)
		//IL_03bc: Expected O, but got Unknown
		Instance = this;
		((BaseUnityPlugin)this).Config.SaveOnConfigSet = false;
		ShowCompass = ((BaseUnityPlugin)this).Config.Bind<bool>("Display", "ShowCompass", true, "Display the compass independently of the clock.");
		ShowClock = ((BaseUnityPlugin)this).Config.Bind<bool>("Display", "ShowClock", true, "Display the clock independently of the compass. Clock-only mode is supported.");
		TwelveHour = ((BaseUnityPlugin)this).Config.Bind<bool>("Display", "TwelveHourClock", false, "Use 12-hour time with am/pm.");
		VagueTime = ((BaseUnityPlugin)this).Config.Bind<bool>("Display", "VagueClock", false, "Show descriptions such as Early morning, Midday or Late night instead of exact time. Overrides TwelveHourClock when enabled.");
		CompassColour = ((BaseUnityPlugin)this).Config.Bind<string>("Display", "CompassColor", "#EBD9AD", "Compass text/marker colour: hex RGB or RGBA (#RGB, #RGBA, #RRGGBB, #RRGGBBAA), or a common name such as white, cyan, gold, amber or ivory. # is optional.");
		ClockColour = ((BaseUnityPlugin)this).Config.Bind<string>("Display", "ClockColor", "#EBD9AD", "Independent clock colour; accepts the same hex formats and colour names as CompassColor.");
		CameraHeading = ((BaseUnityPlugin)this).Config.Bind<bool>("Display", "CameraHeading", true, "Use camera direction; false uses character direction.");
		ConfigEntry<bool> val = ((BaseUnityPlugin)this).Config.Bind<bool>("Display", "ShowMapPins", true, "Show up to sixteen nearby saved map pins on the compass. Checked pins are omitted.");
		HudScale = ((BaseUnityPlugin)this).Config.Bind<float>("Display", "Scale", 1f, new ConfigDescription("HUD scale.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.5f, 2f), new object[0]));
		TopOffset = ((BaseUnityPlugin)this).Config.Bind<float>("Display", "TopOffset", 24f, new ConfigDescription("Distance below the top edge, in reference pixels.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 400f), new object[0]));
		ClockOffset = ((BaseUnityPlugin)this).Config.Bind<float>("Display", "ClockOffset", 50f, new ConfigDescription("Clock distance below the compass in reference pixels. Smaller values move the clock up. Clock-only mode remains at the HUD origin.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(35f, 200f), new object[0]));
		AutoRemoveVisited = ((BaseUnityPlugin)this).Config.Bind<bool>("Waypoints", "AutoRemoveVisited", true, "Remove reached waypoints and renumber the remainder. False keeps reached markers on the map and guides you to the next unvisited waypoint.");
		EnableWaypoints = ((BaseUnityPlugin)this).Config.Bind<bool>("Waypoints", "Enabled", true, "Enable route controls and route map markers. Disable for a plain compass/clock. Automatic arrival also pauses while the compass is hidden.");
		ArrivalChime = ((BaseUnityPlugin)this).Config.Bind<bool>("Waypoints", "ArrivalChime", true, "Play a short chime when reaching the next waypoint.");
		ArrivalVolume = ((BaseUnityPlugin)this).Config.Bind<float>("Waypoints", "ArrivalVolume", 0.5f, new ConfigDescription("Arrival chime volume.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1f), new object[0]));
		Radius = ((BaseUnityPlugin)this).Config.Bind<float>("Waypoints", "ArrivalRadius", 10f, new ConfigDescription("Horizontal arrival distance in metres.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 100f), new object[0]));
		HeightTolerance = ((BaseUnityPlugin)this).Config.Bind<float>("Waypoints", "HeightTolerance", 15f, new ConfigDescription("Vertical tolerance for terrain/feet placements. Map placements use horizontal distance.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 100f), new object[0]));
		Diagnostics = ((BaseUnityPlugin)this).Config.Bind<bool>("Diagnostics", "DetailedLogging", true, "Extra diagnostic logging for this test release. User-facing messages always log.");
		Markers = new MarkerSettings(((BaseUnityPlugin)this).Config, CompassColour.Value, val.Value);
		((BaseUnityPlugin)this).Config.Remove(((ConfigEntryBase)val).Definition);
		MarkerSettings.RemoveObsoleteSettings(((BaseUnityPlugin)this).Config);
		((BaseUnityPlugin)this).Config.Save();
		((BaseUnityPlugin)this).Config.SaveOnConfigSet = true;
		Tracker = new ObjectTracker(this);
		ObjectMap = new ObjectMapView(this);
		View = new Display(this);
		((BaseUnityPlugin)this).Config.SettingChanged += delegate
		{
			SettingsChanged();
		};
		harmony = new Harmony("au.tyvalheim.compasswaypointsclock");
		harmony.PatchAll();
		((BaseUnityPlugin)this).Logger.LogInfo((object)("Compass Waypoints and Clock 0.1.8 ready; diagnostics=" + Diagnostics.Value));
		if (Chainloader.PluginInfos.ContainsKey("neobotics.valheim_mod.hudcompass") || Chainloader.PluginInfos.ContainsKey("aedenthorn.ClockMod"))
		{
			((BaseUnityPlugin)this).Logger.LogWarning((object)"HUDCompass or Clock Mod is also loaded. Disable duplicate HUD elements or remove the replaced mod for testing.");
		}
	}

	internal void SettingsChanged()
	{
		if (View != null)
		{
			View.Invalidate();
		}
		SavedPinStyle.RequestRefresh(Minimap.instance);
	}

	private void Update()
	{
		//IL_0075: Unknown result type (might be due to invalid IL or missing references)
		//IL_007a: 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_00da: 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)
		//IL_00e4: Unknown result type (might be due to invalid IL or missing references)
		//IL_00fe: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ff: 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_00c4: Invalid comparison between Unknown and I4
		try
		{
			Session();
			Tracker.Tick();
			if (Engine == null || !Object.op_Implicit((Object)(object)Player.m_localPlayer) || displayFault)
			{
				View.Hide();
				return;
			}
			Vector3 position;
			bool eligible;
			if (Active && Time.unscaledTime >= nextArrival)
			{
				nextArrival = Time.unscaledTime + 0.1f;
				Player localPlayer = Player.m_localPlayer;
				position = ((Component)localPlayer).transform.position;
				eligible = EnableWaypoints.Value && ShowCompass.Value && !((Character)localPlayer).IsDead() && !((Character)localPlayer).IsTeleporting() && !((Character)localPlayer).InCutscene() && (!Object.op_Implicit((Object)(object)Minimap.instance) || (int)Minimap.instance.m_mode != 2);
				if (havePosition)
				{
					Vector3 val = position - lastPosition;
					if (!(((Vector3)(ref val)).sqrMagnitude > 10000f))
					{
						goto IL_00f6;
					}
				}
				eligible = false;
				goto IL_00f6;
			}
			goto IL_01b7;
			IL_00f6:
			havePosition = true;
			lastPosition = position;
			Waypoint waypoint = Engine.Arrive(position.x, position.y, position.z, Radius.Value, HeightTolerance.Value, Now, eligible, AutoRemoveVisited.Value);
			if (waypoint != null)
			{
				Commit();
				Notice(waypoint.Name + " reached");
				if (ArrivalChime.Value)
				{
					try
					{
						arrivalSound.Play(((Component)this).gameObject, ArrivalVolume.Value);
					}
					catch (Exception ex)
					{
						((BaseUnityPlugin)this).Logger.LogWarning((object)("Arrival chime unavailable: " + ex.Message));
					}
				}
			}
			goto IL_01b7;
			IL_01b7:
			View.Tick();
		}
		catch (Exception ex2)
		{
			((BaseUnityPlugin)this).Logger.LogError((object)("Update failed; HUD and navigation suspended until next session: " + ex2));
			storageFault = true;
			displayFault = true;
			View.Hide();
		}
	}

	private void Session()
	{
		Player localPlayer = Player.m_localPlayer;
		long num = ((Object.op_Implicit((Object)(object)localPlayer) && Object.op_Implicit((Object)(object)ZNet.instance)) ? ZNet.instance.GetWorldUID() : 0);
		long num2 = (Object.op_Implicit((Object)(object)localPlayer) ? localPlayer.GetPlayerID() : 0);
		if (num == world && num2 == character)
		{
			return;
		}
		View.Reset();
		ObjectMap.Reset();
		Tracker.Begin(num, num2);
		Engine = null;
		havePosition = false;
		storageFault = false;
		displayFault = false;
		world = num;
		character = num2;
		if (num == 0 || num2 == 0)
		{
			return;
		}
		path = Path.Combine(Paths.ConfigPath, "CompassWaypointsClock", num.ToString("X16") + "-" + num2.ToString("X16") + ".cwc");
		try
		{
			string recovery;
			RouteDocument routeDocument = RouteStore.Load(path, num, num2, out recovery);
			routeDocument.Paused = false;
			Engine = new RouteEngine(routeDocument);
			savedRevision = Engine.Revision;
			Engine.ResetArrival(Now);
			if (recovery != null)
			{
				Notice(recovery);
			}
			if (Diagnostics.Value)
			{
				((BaseUnityPlugin)this).Logger.LogInfo((object)("Session loaded: " + Engine.Document.Points.Count + " waypoints, " + Engine.Document.Plans.Count + " saved routes."));
			}
		}
		catch (Exception ex)
		{
			Engine = new RouteEngine(new RouteDocument
			{
				World = num,
				Character = num2
			});
			storageFault = true;
			((BaseUnityPlugin)this).Logger.LogError((object)ex);
			Notice("Route storage could not be loaded. Navigation disabled to protect saved routes; compass and clock remain available.");
		}
	}

	internal void Commit()
	{
		if (!Active || savedRevision == Engine.Revision)
		{
			return;
		}
		try
		{
			RouteStore.Save(path, Engine.Document);
			savedRevision = Engine.Revision;
			View.Invalidate();
			if (Diagnostics.Value)
			{
				((BaseUnityPlugin)this).Logger.LogInfo((object)("Route saved: revision " + savedRevision));
			}
		}
		catch (Exception ex)
		{
			storageFault = true;
			((BaseUnityPlugin)this).Logger.LogError((object)ex);
			Notice("Route save failed. Navigation suspended; previous file preserved. Check the log before restarting.");
		}
	}

	internal void Change(Func<bool> action, string message)
	{
		if (!Active)
		{
			return;
		}
		try
		{
			if (action())
			{
				Commit();
				if (!storageFault)
				{
					Notice(message);
				}
			}
			else
			{
				Notice("No change: check the selection, name or route limit.");
			}
		}
		catch (Exception ex)
		{
			((BaseUnityPlugin)this).Logger.LogError((object)ex);
			Notice("Could not change route. See the log for details.");
		}
	}

	internal void Add(Vector3 pos, bool checkHeight, string name)
	{
		//IL_0007: Unknown result type (might be due to invalid IL or missing references)
		//IL_0008: Unknown result type (might be due to invalid IL or missing references)
		Change(() => Engine.Add(new Waypoint
		{
			X = pos.x,
			Y = pos.y,
			Z = pos.z,
			CheckHeight = checkHeight,
			Name = NavigationMath.Clean(name)
		}, Now), "Waypoint added: " + name);
	}

	internal void Notice(string text)
	{
		((BaseUnityPlugin)this).Logger.LogInfo((object)text);
		if (View != null)
		{
			View.SetStatus(text);
		}
		if (Object.op_Implicit((Object)(object)Player.m_localPlayer))
		{
			((Character)Player.m_localPlayer).Message((MessageType)1, text, 0, (Sprite)null, false);
		}
	}

	private void OnDestroy()
	{
		arrivalSound.Dispose();
		if (Tracker != null)
		{
			Tracker.End();
		}
		if (ObjectMap != null)
		{
			ObjectMap.Reset();
		}
		if (View != null)
		{
			View.Reset();
		}
		MarkerSprites.Release();
		if (harmony != null)
		{
			harmony.UnpatchSelf();
		}
		if ((Object)(object)Instance == (Object)(object)this)
		{
			Instance = null;
		}
	}

	private void LateUpdate()
	{
		if (ObjectMap == null)
		{
			return;
		}
		try
		{
			if (Engine != null && !displayFault)
			{
				ObjectMap.Draw();
			}
			else
			{
				ObjectMap.Hide();
			}
		}
		catch (Exception ex)
		{
			ObjectMap.Hide();
			((BaseUnityPlugin)this).Logger.LogError((object)("Object map rendering suspended: " + ex));
			displayFault = true;
		}
	}
}
public sealed class Waypoint
{
	public string Id = Guid.NewGuid().ToString("N");

	public string Name = "Waypoint";

	public float X;

	public float Y;

	public float Z;

	public bool CheckHeight = true;

	public bool Visited;

	public Waypoint Copy()
	{
		return (Waypoint)MemberwiseClone();
	}
}
public sealed class SavedRoute
{
	public string Name;

	public readonly List<Waypoint> Points = new List<Waypoint>();
}
public sealed class RouteDocument
{
	public long World;

	public long Character;

	public bool Paused;

	public readonly List<Waypoint> Points = new List<Waypoint>();

	public readonly List<SavedRoute> Plans = new List<SavedRoute>();
}
public static class NavigationMath
{
	public static bool Finite(float n)
	{
		if (!float.IsNaN(n))
		{
			return !float.IsInfinity(n);
		}
		return false;
	}

	public static float Bearing(float dx, float dz)
	{
		return (float)(Math.Atan2(dx, dz) * 180.0 / Math.PI + 360.0) % 360f;
	}

	public static float Delta(float bearing, float heading)
	{
		return ((bearing - heading + 540f) % 360f + 360f) % 360f - 180f;
	}

	public static float Distance(float dx, float dz)
	{
		return (float)Math.Sqrt((double)dx * (double)dx + (double)dz * (double)dz);
	}

	public static string Clean(string value)
	{
		if (value == null)
		{
			return "";
		}
		List<char> list = new List<char>();
		string text = value.Trim();
		foreach (char c in text)
		{
			if (!char.IsControl(c) && c != '<' && c != '>' && !char.IsSurrogate(c) && list.Count < 48)
			{
				list.Add(c);
			}
		}
		return new string(list.ToArray());
	}

	public static bool Valid(Waypoint p)
	{
		if (p != null && p.Id != null && p.Id.Length == 32 && IsId(p.Id) && p.Name != null && p.Name.Length <= 48 && p.Name == Clean(p.Name) && Finite(p.X) && Finite(p.Y) && Finite(p.Z) && Math.Abs(p.X) <= 50000f && Math.Abs(p.Y) <= 50000f)
		{
			return Math.Abs(p.Z) <= 50000f;
		}
		return false;
	}

	private static bool IsId(string s)
	{
		Guid result;
		return Guid.TryParseExact(s, "N", out result);
	}

	public static string Clock(float fraction, bool twelveHour)
	{
		if (!Finite(fraction))
		{
			return "--:--";
		}
		int num = ((int)Math.Floor(((double)fraction - Math.Floor(fraction)) * 1440.0) + 1440) % 1440;
		int num2 = num / 60;
		if (twelveHour)
		{
			return (num2 + 11) % 12 + 1 + ":" + (num % 60).ToString("00") + ((num2 < 12) ? " am" : " pm");
		}
		return num2.ToString("00") + ":" + (num % 60).ToString("00");
	}

	public static string VagueClock(float fraction)
	{
		if (!Finite(fraction))
		{
			return "--";
		}
		float num = (float)((double)fraction - Math.Floor(fraction)) * 24f;
		if (num >= 23f || num < 1f)
		{
			return "Midnight";
		}
		if (num < 4f)
		{
			return "Late night";
		}
		if (num < 7f)
		{
			return "Early morning";
		}
		if (num < 10f)
		{
			return "Morning";
		}
		if (num < 12f)
		{
			return "Late morning";
		}
		if (num < 14f)
		{
			return "Midday";
		}
		if (num < 17f)
		{
			return "Afternoon";
		}
		if (num < 20f)
		{
			return "Evening";
		}
		if (num < 22f)
		{
			return "Late evening";
		}
		return "Night";
	}
}
public sealed class RouteEngine
{
	public const int MaxPoints = 128;

	public const int MaxPlans = 16;

	private readonly Stack<RouteDocument> undo = new Stack<RouteDocument>();

	private double armedAt;

	private double insideSince = -1.0;

	private string tracking;

	public RouteDocument Document { get; private set; }

	public int Revision { get; private set; }

	public int ActiveIndex => Document.Points.FindIndex((Waypoint p) => !p.Visited);

	public string Label(int index)
	{
		return "Waypoint " + (index + 1);
	}

	public int FindNearest(float x, float z, float radius)
	{
		int result = -1;
		float num = radius;
		if (!NavigationMath.Finite(x) || !NavigationMath.Finite(z) || !NavigationMath.Finite(radius) || radius < 0f)
		{
			return result;
		}
		for (int i = 0; i < Document.Points.Count; i++)
		{
			Waypoint waypoint = Document.Points[i];
			float num2 = NavigationMath.Distance(waypoint.X - x, waypoint.Z - z);
			if (num2 <= num)
			{
				num = num2;
				result = i;
			}
		}
		return result;
	}

	public RouteEngine(RouteDocument doc)
	{
		Validate(doc);
		Document = Clone(doc);
	}

	public static void Validate(RouteDocument doc)
	{
		if (doc == null || doc.World == 0 || doc.Character == 0 || doc.Plans.Count > 16)
		{
			throw new ArgumentException("Invalid route document");
		}
		ValidatePoints(doc.Points);
		HashSet<string> hashSet = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
		foreach (SavedRoute plan in doc.Plans)
		{
			if (plan == null || string.IsNullOrEmpty(plan.Name) || plan.Name != NavigationMath.Clean(plan.Name) || !hashSet.Add(plan.Name))
			{
				throw new ArgumentException("Invalid saved route name");
			}
			ValidatePoints(plan.Points);
		}
	}

	private static void ValidatePoints(List<Waypoint> points)
	{
		if (points.Count > 128)
		{
			throw new ArgumentException("Too many waypoints");
		}
		HashSet<string> hashSet = new HashSet<string>();
		foreach (Waypoint point in points)
		{
			if (!NavigationMath.Valid(point) || !hashSet.Add(point.Id))
			{
				throw new ArgumentException("Invalid or duplicate waypoint");
			}
		}
	}

	public static RouteDocument Clone(RouteDocument d)
	{
		RouteDocument routeDocument = new RouteDocument();
		routeDocument.World = d.World;
		routeDocument.Character = d.Character;
		routeDocument.Paused = d.Paused;
		RouteDocument routeDocument2 = routeDocument;
		foreach (Waypoint point in d.Points)
		{
			routeDocument2.Points.Add(point.Copy());
		}
		foreach (SavedRoute plan in d.Plans)
		{
			SavedRoute savedRoute = new SavedRoute();
			savedRoute.Name = plan.Name;
			SavedRoute savedRoute2 = savedRoute;
			foreach (Waypoint point2 in plan.Points)
			{
				savedRoute2.Points.Add(point2.Copy());
			}
			routeDocument2.Plans.Add(savedRoute2);
		}
		return routeDocument2;
	}

	private void Before(double now)
	{
		if (undo.Count == 20)
		{
			RouteDocument[] array = undo.ToArray();
			undo.Clear();
			for (int num = 18; num >= 0; num--)
			{
				undo.Push(array[num]);
			}
		}
		undo.Push(Clone(Document));
		Revision++;
		ResetArrival(now);
	}

	public void ResetArrival(double now)
	{
		tracking = null;
		insideSince = -1.0;
		armedAt = now + 2.0;
	}

	public bool Add(Waypoint p, double now)
	{
		if (!NavigationMath.Valid(p) || Document.Points.Count >= 128 || Document.Points.Exists((Waypoint q) => q.Id == p.Id))
		{
			return false;
		}
		Before(now);
		Document.Points.Add(p.Copy());
		return true;
	}

	public bool Remove(int index, double now)
	{
		if (index < 0 || index >= Document.Points.Count)
		{
			return false;
		}
		Before(now);
		Document.Points.RemoveAt(index);
		return true;
	}

	public bool Move(int from, int to, double now)
	{
		if (from < 0 || to < 0 || from >= Document.Points.Count || to >= Do