Decompiled source of PinGPS Ymiron v1.0.0

PinGPS.dll

Decompiled 13 hours ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using TMPro;
using UnityEngine;
using UnityEngine.SceneManagement;
using UnityEngine.UI;

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

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace PinGPS
{
	internal class GpsHud : MonoBehaviour
	{
		private const float ReferenceHeight = 1080f;

		private Canvas _canvas;

		private RectTransform _marker;

		private Image _icon;

		private RectTransform _arrow;

		private Image _arrowImage;

		private TextMeshProUGUI _label;

		private PinData _smoothedPin;

		private float _smoothedY;

		private int _lastRefreshFrame = -1;

		internal static GpsHud Instance { get; private set; }

		private void Awake()
		{
			Instance = this;
			BuildUi();
		}

		private void OnDestroy()
		{
			if ((Object)(object)Instance == (Object)(object)this)
			{
				Instance = null;
			}
		}

		private void Update()
		{
			if (_lastRefreshFrame < Time.frameCount - 1)
			{
				Show(visible: false);
			}
		}

		private void BuildUi()
		{
			//IL_0051: Unknown result type (might be due to invalid IL or missing references)
			//IL_0056: Unknown result type (might be due to invalid IL or missing references)
			//IL_0057: Unknown result type (might be due to invalid IL or missing references)
			//IL_005d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0073: Unknown result type (might be due to invalid IL or missing references)
			//IL_011b: Unknown result type (might be due to invalid IL or missing references)
			_canvas = ((Component)this).gameObject.AddComponent<Canvas>();
			_canvas.renderMode = (RenderMode)0;
			_canvas.sortingOrder = -100;
			_marker = NewRect("Marker", ((Component)_canvas).transform);
			RectTransform marker = _marker;
			Vector2 anchorMin = (_marker.anchorMax = Vector2.zero);
			marker.anchorMin = anchorMin;
			_marker.pivot = new Vector2(0.5f, 0.5f);
			RectTransform val = NewRect("Icon", (Transform)(object)_marker);
			_icon = ((Component)val).gameObject.AddComponent<Image>();
			_icon.preserveAspect = true;
			((Graphic)_icon).raycastTarget = false;
			_arrow = NewRect("Arrow", (Transform)(object)_marker);
			_arrowImage = ((Component)_arrow).gameObject.AddComponent<Image>();
			_arrowImage.sprite = CreateArrowSprite();
			((Graphic)_arrowImage).raycastTarget = false;
			RectTransform val2 = NewRect("Label", (Transform)(object)_marker);
			val2.pivot = new Vector2(0.5f, 1f);
			_label = ((Component)val2).gameObject.AddComponent<TextMeshProUGUI>();
			((TMP_Text)_label).alignment = (TextAlignmentOptions)258;
			((TMP_Text)_label).overflowMode = (TextOverflowModes)0;
			((Graphic)_label).raycastTarget = false;
			Show(visible: false);
		}

		private static RectTransform NewRect(string name, Transform parent)
		{
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: Expected O, but got Unknown
			GameObject val = new GameObject(name, new Type[1] { typeof(RectTransform) });
			val.transform.SetParent(parent, false);
			return (RectTransform)val.transform;
		}

		private static Sprite CreateArrowSprite()
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0013: Expected O, but got Unknown
			//IL_00f8: Unknown result type (might be due to invalid IL or missing references)
			//IL_0107: 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_00b9: Unknown result type (might be due to invalid IL or missing references)
			Texture2D val = new Texture2D(64, 64, (TextureFormat)4, false)
			{
				wrapMode = (TextureWrapMode)1
			};
			Color32[] array = (Color32[])(object)new Color32[4096];
			for (int i = 0; i < 64; i++)
			{
				for (int j = 0; j < 64; j++)
				{
					float num = ((float)i + 0.5f) / 64f;
					float num2 = (1f - num) * 0.5f;
					float num3 = Mathf.Abs(((float)j + 0.5f) / 64f - 0.5f);
					float num4 = Mathf.Clamp01((num2 - num3) * 64f * 0.75f) * Mathf.Clamp01((num - 0.08f) * 64f * 0.5f);
					array[i * 64 + j] = new Color32(byte.MaxValue, byte.MaxValue, byte.MaxValue, (byte)(num4 * 255f));
				}
			}
			val.SetPixels32(array);
			val.Apply();
			return Sprite.Create(val, new Rect(0f, 0f, 64f, 64f), new Vector2(0.5f, 0.5f));
		}

		private void Show(bool visible)
		{
			if ((Object)(object)_marker != (Object)null && ((Component)_marker).gameObject.activeSelf != visible)
			{
				((Component)_marker).gameObject.SetActive(visible);
			}
		}

		private static bool HudAllowsMarker()
		{
			if ((Object)(object)Hud.instance != (Object)null && Hud.instance.IsVisible() && !Minimap.IsOpen() && !InventoryGui.IsVisible() && !Menu.IsVisible() && !StoreGui.IsVisible() && !TextInput.IsVisible())
			{
				return !Console.IsVisible();
			}
			return false;
		}

		internal void Refresh(Camera camera)
		{
			//IL_0094: Unknown result type (might be due to invalid IL or missing references)
			_lastRefreshFrame = Time.frameCount;
			PinData pin = GpsTarget.Pin;
			Player localPlayer = Player.m_localPlayer;
			if (pin == null || (Object)(object)localPlayer == (Object)null || ((Character)localPlayer).IsDead() || (Object)(object)camera == (Object)null || !HudAllowsMarker())
			{
				Show(visible: false);
				return;
			}
			float num = GpsTarget.HorizontalDistance(localPlayer);
			if (num < ModConfig.ArrivalDistance.Value)
			{
				Show(visible: false);
				return;
			}
			Show(visible: true);
			ApplyStyle(pin);
			Vector3 world = default(Vector3);
			((Vector3)(ref world))..ctor(pin.m_pos.x, TargetHeight(pin, camera), pin.m_pos.z);
			PlaceOnScreen(camera, world);
			((TMP_Text)_label).text = LabelText(pin, num);
		}

		private float TargetHeight(PinData pin, Camera camera)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			float num2 = default(float);
			float num = (Heightmap.GetHeight(pin.m_pos, ref num2) ? (Mathf.Max(num2, ((Object)(object)ZoneSystem.instance != (Object)null) ? ZoneSystem.instance.m_waterLevel : 30f) + ModConfig.HeightAboveGround.Value) : ((Component)camera).transform.position.y);
			if (_smoothedPin != pin)
			{
				_smoothedPin = pin;
				_smoothedY = num;
			}
			else
			{
				_smoothedY = Mathf.Lerp(_smoothedY, num, 1f - Mathf.Exp(-4f * Time.unscaledDeltaTime));
			}
			return _smoothedY;
		}

		private void ApplyStyle(PinData pin)
		{
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			//IL_0056: Unknown result type (might be due to invalid IL or missing references)
			//IL_0060: Unknown result type (might be due to invalid IL or missing references)
			//IL_0065: Unknown result type (might be due to invalid IL or missing references)
			//IL_006c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0078: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a8: 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)
			float num = (float)Screen.height / 1080f;
			float num2 = ModConfig.IconSize.Value * num;
			_icon.sprite = pin.m_icon;
			((Graphic)_icon).rectTransform.sizeDelta = new Vector2(num2, num2);
			_arrow.sizeDelta = new Vector2(num2 * 0.45f, num2 * 0.45f);
			Color color = ModConfig.ParseTextColor();
			((Graphic)_arrowImage).color = color;
			((Graphic)_label).color = color;
			((TMP_Text)_label).fontSize = 20f * num;
			((TMP_Text)_label).rectTransform.anchoredPosition = new Vector2(0f, (0f - num2) * 0.55f);
			((TMP_Text)_label).rectTransform.sizeDelta = new Vector2(400f * num, 60f * num);
			if ((Object)(object)Hud.instance != (Object)null && (Object)(object)Hud.instance.m_healthText != (Object)null && (Object)(object)((TMP_Text)_label).font != (Object)(object)Hud.instance.m_healthText.font)
			{
				((TMP_Text)_label).font = Hud.instance.m_healthText.font;
				((TMP_Text)_label).fontSharedMaterial = Hud.instance.m_healthText.fontSharedMaterial;
			}
		}

		private void PlaceOnScreen(Camera camera, Vector3 world)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//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)
			//IL_0045: 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_0047: Unknown result type (might be due to invalid IL or missing references)
			//IL_004c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0037: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0051: Unknown result type (might be due to invalid IL or missing references)
			//IL_006f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0083: Unknown result type (might be due to invalid IL or missing references)
			//IL_0094: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_0134: Unknown result type (might be due to invalid IL or missing references)
			//IL_0135: Unknown result type (might be due to invalid IL or missing references)
			//IL_0136: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e7: 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_017d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0182: Unknown result type (might be due to invalid IL or missing references)
			//IL_018f: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a1: 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_01c5: Unknown result type (might be due to invalid IL or missing references)
			//IL_01cc: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e4: Unknown result type (might be due to invalid IL or missing references)
			//IL_0110: Unknown result type (might be due to invalid IL or missing references)
			//IL_011e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0128: Unknown result type (might be due to invalid IL or missing references)
			//IL_012d: Unknown result type (might be due to invalid IL or missing references)
			Vector3 val = camera.WorldToScreenPoint(world);
			bool num = val.z < 0f;
			Vector2 val2 = default(Vector2);
			((Vector2)(ref val2))..ctor((float)Screen.width * 0.5f, (float)Screen.height * 0.5f);
			Vector2 val3 = (num ? (val2 - Vector2.op_Implicit(val)) : (Vector2.op_Implicit(val) - val2));
			float num2 = ModConfig.EdgeMargin.Value * ((float)Screen.height / 1080f);
			float num3 = Mathf.Max(1f, val2.x - num2);
			float num4 = Mathf.Max(1f, val2.y - num2);
			int num5;
			if (!num && !(Mathf.Abs(val3.x) > num3))
			{
				num5 = ((Mathf.Abs(val3.y) > num4) ? 1 : 0);
				if (num5 == 0)
				{
					goto IL_012e;
				}
			}
			else
			{
				num5 = 1;
			}
			if (((Vector2)(ref val3)).sqrMagnitude < 0.01f)
			{
				val3 = Vector2.down;
			}
			float num6 = ((Mathf.Abs(val3.x) > 0.0001f) ? (num3 / Mathf.Abs(val3.x)) : float.MaxValue);
			float num7 = ((Mathf.Abs(val3.y) > 0.0001f) ? (num4 / Mathf.Abs(val3.y)) : float.MaxValue);
			val3 *= Mathf.Min(num6, num7);
			goto IL_012e;
			IL_012e:
			_marker.anchoredPosition = val2 + val3;
			bool flag = num5 != 0 && ModConfig.ShowEdgeArrow.Value;
			if (((Component)_arrow).gameObject.activeSelf != flag)
			{
				((Component)_arrow).gameObject.SetActive(flag);
			}
			if (flag)
			{
				Vector2 normalized = ((Vector2)(ref val3)).normalized;
				float x = ((Graphic)_icon).rectTransform.sizeDelta.x;
				_arrow.anchoredPosition = normalized * (x * 0.75f);
				((Transform)_arrow).localRotation = Quaternion.Euler(0f, 0f, Mathf.Atan2(normalized.y, normalized.x) * 57.29578f - 90f);
			}
		}

		private static string LabelText(PinData pin, float distance)
		{
			string text = (ModConfig.ShowName.Value ? GpsTarget.DisplayName(pin) : "");
			string text2 = (ModConfig.ShowDistance.Value ? FormatDistance(distance) : "");
			if (text.Length > 0 && text2.Length > 0)
			{
				return text + "\n" + text2;
			}
			return text + text2;
		}

		private static string FormatDistance(float meters)
		{
			if (!(meters < 1000f))
			{
				return (meters / 1000f).ToString("0.0", CultureInfo.InvariantCulture) + " km";
			}
			return $"{Mathf.RoundToInt(meters)} m";
		}
	}
	[HarmonyPatch(typeof(GameCamera), "LateUpdate")]
	internal static class GameCamera_LateUpdate_Patch
	{
		private static readonly FieldRef<GameCamera, Camera> CameraRef = AccessTools.FieldRefAccess<GameCamera, Camera>("m_camera");

		private static void Postfix(GameCamera __instance)
		{
			GpsHud.Instance?.Refresh(CameraRef.Invoke(__instance));
		}
	}
	internal static class GpsTarget
	{
		private delegate Vector3 ScreenToWorldPointFn(Minimap minimap, Vector3 screenPos);

		private const string SaveKeyPrefix = "ymiron.pingps.";

		private static readonly FieldRef<Minimap, List<PinData>> PinsRef = AccessTools.FieldRefAccess<Minimap, List<PinData>>("m_pins");

		private static readonly FieldRef<Minimap, bool> PinUpdateRequiredRef = AccessTools.FieldRefAccess<Minimap, bool>("m_pinUpdateRequired");

		private static readonly ScreenToWorldPointFn ScreenToWorldPoint = AccessTools.MethodDelegate<ScreenToWorldPointFn>(AccessTools.Method(typeof(Minimap), "ScreenToWorldPoint", (Type[])null, (Type[])null), (object)null, true);

		private static bool _armed;

		private static bool _pinWasAnimated;

		private static bool _restoreDone;

		private static float _playerAliveTime;

		internal static PinData Pin { get; private set; }

		internal static PinData FindPinUnderCursor(Minimap minimap)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_0076: Unknown result type (might be due to invalid IL or missing references)
			//IL_0079: Unknown result type (might be due to invalid IL or missing references)
			Vector3 val = ScreenToWorldPoint(minimap, ZInput.pointerPosition);
			float num = minimap.m_removeRadius * (minimap.LargeZoom * 2f);
			PinData result = null;
			float num2 = float.MaxValue;
			foreach (PinData item in PinsRef.Invoke(minimap))
			{
				if (item.m_save && !((Object)(object)item.m_uiElement == (Object)null) && ((Component)item.m_uiElement).gameObject.activeInHierarchy)
				{
					float num3 = Utils.DistanceXZ(val, item.m_pos);
					if (num3 < num && num3 < num2)
					{
						result = item;
						num2 = num3;
					}
				}
			}
			return result;
		}

		internal static void Toggle(PinData pin)
		{
			if (pin == Pin)
			{
				TurnOff();
				return;
			}
			Set(pin);
			Sounds.Play(ModConfig.SetSound.Value);
			Player localPlayer = Player.m_localPlayer;
			if (localPlayer != null)
			{
				((Character)localPlayer).Message((MessageType)1, ModConfig.MsgSet.Value + ": " + DisplayName(pin), 0, pin.m_icon, false);
			}
		}

		internal static void TurnOff()
		{
			if (Pin != null)
			{
				Clear(forget: true);
				Sounds.Play(ModConfig.SetSound.Value);
				Player localPlayer = Player.m_localPlayer;
				if (localPlayer != null)
				{
					((Character)localPlayer).Message((MessageType)1, ModConfig.MsgOff.Value, 0, (Sprite)null, false);
				}
			}
		}

		internal static string DisplayName(PinData pin)
		{
			if (string.IsNullOrEmpty(pin.m_name))
			{
				return "";
			}
			if (Localization.instance == null)
			{
				return pin.m_name;
			}
			return Localization.instance.Localize(pin.m_name);
		}

		internal static void Tick()
		{
			Minimap instance = Minimap.instance;
			if ((Object)(object)instance == (Object)null)
			{
				Pin = null;
				_restoreDone = false;
				_playerAliveTime = 0f;
				return;
			}
			Player localPlayer = Player.m_localPlayer;
			if ((Object)(object)localPlayer == (Object)null)
			{
				_playerAliveTime = 0f;
				return;
			}
			_playerAliveTime += Time.deltaTime;
			if (!_restoreDone && _playerAliveTime > 1f)
			{
				_restoreDone = true;
				if (Pin == null)
				{
					Restore(instance, localPlayer);
				}
			}
			if (Pin == null)
			{
				return;
			}
			if (!PinsRef.Invoke(instance).Contains(Pin))
			{
				Clear(forget: true);
				return;
			}
			if (ModConfig.PulseOnMap.Value)
			{
				Pin.m_animate = true;
				PinUpdateRequiredRef.Invoke(instance) = true;
			}
			else if (Pin.m_animate && !_pinWasAnimated)
			{
				StopAnimation(instance, Pin);
			}
			if (!(HorizontalDistance(localPlayer) < ModConfig.ArrivalDistance.Value))
			{
				_armed = true;
			}
			else if (_armed && !((Character)localPlayer).IsDead() && ModConfig.TurnOffOnArrival.Value)
			{
				Clear(forget: true);
				Sounds.Play(ModConfig.ArrivalSound.Value);
				((Character)localPlayer).Message((MessageType)2, ModConfig.MsgArrived.Value, 0, (Sprite)null, false);
			}
		}

		internal static float HorizontalDistance(Player player)
		{
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			if (Pin != null)
			{
				return Utils.DistanceXZ(((Component)player).transform.position, Pin.m_pos);
			}
			return 0f;
		}

		private static void Set(PinData pin)
		{
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			Clear(forget: false);
			Pin = pin;
			_pinWasAnimated = pin.m_animate;
			_armed = false;
			Save(pin.m_pos);
		}

		private static void Clear(bool forget)
		{
			if (Pin != null && (Object)(object)Minimap.instance != (Object)null && !_pinWasAnimated)
			{
				StopAnimation(Minimap.instance, Pin);
			}
			Pin = null;
			if (forget)
			{
				Save(null);
			}
		}

		private static void StopAnimation(Minimap minimap, PinData pin)
		{
			pin.m_animate = false;
			if ((Object)(object)pin.m_uiElement != (Object)null)
			{
				Object.Destroy((Object)(object)((Component)pin.m_uiElement).gameObject);
				pin.m_uiElement = null;
			}
			PinUpdateRequiredRef.Invoke(minimap) = true;
		}

		private static string SaveKey()
		{
			if (!((Object)(object)ZNet.instance != (Object)null))
			{
				return null;
			}
			return "ymiron.pingps." + ZNet.instance.GetWorldUID().ToString(CultureInfo.InvariantCulture);
		}

		private static void Save(Vector3? position)
		{
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_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)
			Player localPlayer = Player.m_localPlayer;
			string text = SaveKey();
			if (!((Object)(object)localPlayer == (Object)null) && text != null)
			{
				if (position.HasValue)
				{
					localPlayer.m_customData[text] = position.Value.x.ToString("R", CultureInfo.InvariantCulture) + ";" + position.Value.z.ToString("R", CultureInfo.InvariantCulture);
				}
				else
				{
					localPlayer.m_customData.Remove(text);
				}
			}
		}

		private static void Restore(Minimap minimap, Player player)
		{
			//IL_008d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0091: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ba: Unknown result type (might be due to invalid IL or missing references)
			string text = SaveKey();
			if (text == null || !player.m_customData.TryGetValue(text, out var value))
			{
				return;
			}
			string[] array = value.Split(';');
			if (array.Length != 2 || !float.TryParse(array[0], NumberStyles.Float, CultureInfo.InvariantCulture, out var result) || !float.TryParse(array[1], NumberStyles.Float, CultureInfo.InvariantCulture, out var result2))
			{
				return;
			}
			Vector3 val = default(Vector3);
			((Vector3)(ref val))..ctor(result, 0f, result2);
			foreach (PinData item in PinsRef.Invoke(minimap))
			{
				if (item.m_save && Utils.DistanceXZ(val, item.m_pos) < 0.5f)
				{
					Set(item);
					PinGPSPlugin.Log.LogInfo((object)$"GPS destination restored: {DisplayName(item)} at {val}.");
					return;
				}
			}
			player.m_customData.Remove(text);
		}
	}
	internal static class ModConfig
	{
		internal static ConfigEntry<KeyCode> SelectModifier;

		internal static ConfigEntry<KeyboardShortcut> ClearKey;

		internal static ConfigEntry<float> IconSize;

		internal static ConfigEntry<bool> ShowName;

		internal static ConfigEntry<bool> ShowDistance;

		internal static ConfigEntry<string> TextColor;

		internal static ConfigEntry<bool> ShowEdgeArrow;

		internal static ConfigEntry<float> EdgeMargin;

		internal static ConfigEntry<float> HeightAboveGround;

		internal static ConfigEntry<bool> PulseOnMap;

		internal static ConfigEntry<float> ArrivalDistance;

		internal static ConfigEntry<bool> TurnOffOnArrival;

		internal static ConfigEntry<string> SetSound;

		internal static ConfigEntry<string> ArrivalSound;

		internal static ConfigEntry<string> MsgSet;

		internal static ConfigEntry<string> MsgOff;

		internal static ConfigEntry<string> MsgArrived;

		internal static void Bind(ConfigFile cfg)
		{
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0067: Unknown result type (might be due to invalid IL or missing references)
			//IL_0071: Expected O, but got Unknown
			//IL_010f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0119: Expected O, but got Unknown
			//IL_0181: Unknown result type (might be due to invalid IL or missing references)
			//IL_018b: Expected O, but got Unknown
			SelectModifier = cfg.Bind<KeyCode>("1 - Controls", "SelectModifier", (KeyCode)306, "Hold this key and left-click a pin on the large map to make it the GPS destination. Do it again on the same pin to turn the GPS off.");
			ClearKey = cfg.Bind<KeyboardShortcut>("1 - Controls", "TurnOffKey", KeyboardShortcut.Empty, "Optional key that turns the GPS off without opening the map (e.g. \"G\" or \"LeftAlt + G\"). Empty = none.");
			IconSize = cfg.Bind<float>("2 - Display", "IconSize", 40f, new ConfigDescription("Size of the on-screen icon, in pixels at 1080p (scaled with the resolution).", (AcceptableValueBase)(object)new AcceptableValueRange<float>(16f, 128f), Array.Empty<object>()));
			ShowName = cfg.Bind<bool>("2 - Display", "ShowName", true, "Show the name of the pin under the icon (when the pin has one).");
			ShowDistance = cfg.Bind<bool>("2 - Display", "ShowDistance", true, "Show the distance to the destination under the icon.");
			TextColor = cfg.Bind<string>("2 - Display", "TextColor", "#FFD966", "Color of the name/distance text: a hex code (#RRGGBB) or a Unity color name (yellow, orange, white...).");
			ShowEdgeArrow = cfg.Bind<bool>("2 - Display", "ShowEdgeArrow", true, "When the destination is out of view, the icon sticks to the edge of the screen; this adds an arrow pointing towards it.");
			EdgeMargin = cfg.Bind<float>("2 - Display", "EdgeMargin", 70f, new ConfigDescription("Distance (pixels at 1080p) kept from the screen edges when the icon is stuck to the edge.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 300f), Array.Empty<object>()));
			HeightAboveGround = cfg.Bind<float>("2 - Display", "HeightAboveGround", 4f, "When the destination is close enough for the terrain to be loaded, the icon floats this many meters above the ground. Farther away it sits on the horizon.");
			PulseOnMap = cfg.Bind<bool>("2 - Display", "PulseOnMap", true, "Make the active pin pulse on the map and minimap.");
			ArrivalDistance = cfg.Bind<float>("3 - Arrival", "ArrivalDistance", 10f, new ConfigDescription("You have arrived when you are this close (meters, horizontal distance).", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 200f), Array.Empty<object>()));
			TurnOffOnArrival = cfg.Bind<bool>("3 - Arrival", "TurnOffOnArrival", true, "Turn the GPS off automatically on arrival. If false, the marker is just hidden while you are within ArrivalDistance.");
			SetSound = cfg.Bind<string>("3 - Arrival", "SetSound", "sfx_gui_select", "Vanilla sound played when a destination is set or turned off. Empty = silent.");
			ArrivalSound = cfg.Bind<string>("3 - Arrival", "ArrivalSound", "sfx_gui_biomefound", "Vanilla sound played on arrival. Empty = silent.");
			MsgSet = cfg.Bind<string>("4 - Messages", "DestinationSet", "GPS destination set", "Message shown when a pin becomes the GPS destination.");
			MsgOff = cfg.Bind<string>("4 - Messages", "GpsOff", "GPS turned off", "Message shown when the GPS is turned off.");
			MsgArrived = cfg.Bind<string>("4 - Messages", "Arrived", "You have reached your destination", "Message shown on arrival.");
		}

		internal static Color ParseTextColor()
		{
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			Color result = default(Color);
			if (!ColorUtility.TryParseHtmlString(TextColor.Value, ref result))
			{
				return new Color(1f, 0.85f, 0.4f);
			}
			return result;
		}
	}
	internal static class MapInput
	{
		internal static bool ModifierHeld()
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			return ZInput.GetKey(ModConfig.SelectModifier.Value, true);
		}
	}
	[HarmonyPatch(typeof(Minimap), "OnMapLeftClick")]
	internal static class Minimap_OnMapLeftClick_Patch
	{
		private static bool Prefix(Minimap __instance)
		{
			if (!MapInput.ModifierHeld())
			{
				return true;
			}
			PinData val = GpsTarget.FindPinUnderCursor(__instance);
			if (val == null)
			{
				return true;
			}
			GpsTarget.Toggle(val);
			return false;
		}
	}
	[HarmonyPatch(typeof(Minimap), "OnMapDblClick")]
	internal static class Minimap_OnMapDblClick_Patch
	{
		private static bool Prefix()
		{
			return !MapInput.ModifierHeld();
		}
	}
	[BepInPlugin("ymiron.valheim.pingps", "PinGPS-Ymiron", "1.0.0")]
	[BepInProcess("valheim.exe")]
	public class PinGPSPlugin : BaseUnityPlugin
	{
		public const string PluginGuid = "ymiron.valheim.pingps";

		public const string PluginName = "PinGPS-Ymiron";

		public const string PluginVersion = "1.0.0";

		private Harmony _harmony;

		private FileSystemWatcher _watcher;

		private volatile bool _configChanged;

		private GpsHud _hud;

		internal static ManualLogSource Log { get; private set; }

		private void Awake()
		{
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: Expected O, but got Unknown
			//IL_0045: Unknown result type (might be due to invalid IL or missing references)
			//IL_004b: Expected O, but got Unknown
			Log = ((BaseUnityPlugin)this).Logger;
			ModConfig.Bind(((BaseUnityPlugin)this).Config);
			_harmony = new Harmony("ymiron.valheim.pingps");
			_harmony.PatchAll(typeof(PinGPSPlugin).Assembly);
			GameObject val = new GameObject("PinGPS_Hud");
			Object.DontDestroyOnLoad((Object)(object)val);
			_hud = val.AddComponent<GpsHud>();
			WatchConfigFile();
			Log.LogInfo((object)"PinGPS-Ymiron 1.0.0 loaded.");
		}

		private void WatchConfigFile()
		{
			_watcher = new FileSystemWatcher(Path.GetDirectoryName(((BaseUnityPlugin)this).Config.ConfigFilePath), Path.GetFileName(((BaseUnityPlugin)this).Config.ConfigFilePath))
			{
				NotifyFilter = (NotifyFilters.FileName | NotifyFilters.Size | NotifyFilters.LastWrite),
				IncludeSubdirectories = false
			};
			_watcher.Changed += delegate
			{
				_configChanged = true;
			};
			_watcher.Created += delegate
			{
				_configChanged = true;
			};
			_watcher.Renamed += delegate
			{
				_configChanged = true;
			};
			_watcher.EnableRaisingEvents = true;
		}

		private void Update()
		{
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			GpsTarget.Tick();
			if (GpsTarget.Pin != null)
			{
				KeyboardShortcut value = ModConfig.ClearKey.Value;
				if (((KeyboardShortcut)(ref value)).IsDown() && !IsTyping())
				{
					GpsTarget.TurnOff();
				}
			}
			if (!_configChanged)
			{
				return;
			}
			_configChanged = false;
			try
			{
				((BaseUnityPlugin)this).Config.Reload();
				Log.LogInfo((object)"Config reloaded.");
			}
			catch (IOException)
			{
				_configChanged = true;
			}
		}

		private static bool IsTyping()
		{
			if (!Console.IsVisible() && !TextInput.IsVisible() && !Minimap.InTextInput())
			{
				if ((Object)(object)Chat.instance != (Object)null)
				{
					return Chat.instance.HasFocus();
				}
				return false;
			}
			return true;
		}

		private void OnDestroy()
		{
			_watcher?.Dispose();
			Harmony harmony = _harmony;
			if (harmony != null)
			{
				harmony.UnpatchSelf();
			}
			if ((Object)(object)_hud != (Object)null)
			{
				Object.Destroy((Object)(object)((Component)_hud).gameObject);
			}
		}
	}
	internal static class Sounds
	{
		private static readonly Dictionary<string, GameObject> Cache = new Dictionary<string, GameObject>();

		private static readonly HashSet<string> Missing = new HashSet<string>();

		internal static void Play(string name)
		{
			//IL_0065: Unknown result type (might be due to invalid IL or missing references)
			//IL_006a: Unknown result type (might be due to invalid IL or missing references)
			Player localPlayer = Player.m_localPlayer;
			if (string.IsNullOrWhiteSpace(name) || (Object)(object)localPlayer == (Object)null)
			{
				return;
			}
			name = name.Trim();
			GameObject val = Find(name);
			if ((Object)(object)val == (Object)null)
			{
				if (Missing.Add(name))
				{
					PinGPSPlugin.Log.LogWarning((object)("Sound '" + name + "' not found."));
				}
				return;
			}
			ZNetView.m_forceDisableInit = true;
			try
			{
				Object.Instantiate<GameObject>(val, ((Component)localPlayer).transform.position, Quaternion.identity);
			}
			finally
			{
				ZNetView.m_forceDisableInit = false;
			}
		}

		private static GameObject Find(string name)
		{
			//IL_0078: Unknown result type (might be due to invalid IL or missing references)
			//IL_007d: Unknown result type (might be due to invalid IL or missing references)
			if (Cache.TryGetValue(name, out var value) && (Object)(object)value != (Object)null)
			{
				return value;
			}
			GameObject val = (((Object)(object)ZNetScene.instance != (Object)null) ? ZNetScene.instance.GetPrefab(name) : null);
			if ((Object)(object)val == (Object)null)
			{
				ZSFX[] array = Resources.FindObjectsOfTypeAll<ZSFX>();
				foreach (ZSFX val2 in array)
				{
					if (((Object)val2).name == name && (Object)(object)((Component)val2).transform.parent == (Object)null)
					{
						Scene scene = ((Component)val2).gameObject.scene;
						if (!((Scene)(ref scene)).IsValid())
						{
							val = ((Component)val2).gameObject;
							break;
						}
					}
				}
			}
			if ((Object)(object)val != (Object)null)
			{
				Cache[name] = val;
			}
			return val;
		}
	}
}