Decompiled source of WhereIsMyAmulet v1.0.0

WhereIsMyAmulet.dll

Decompiled 6 hours ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using Microsoft.CodeAnalysis;
using TMPro;
using UnityEngine;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyTitle("WhereIsMyAmulet")]
[assembly: AssemblyDescription("Shows the distance to dropped amulet fragments in PEAK.")]
[assembly: AssemblyProduct("WhereIsMyAmulet")]
[assembly: ComVisible(false)]
[assembly: Guid("ce0f5e2c-08a1-4f5f-8da4-a91c5c43a5a7")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[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 WhereIsMyAmulet
{
	[BepInPlugin("com.wuyachiyu.WhereIsMyAmulet", "WhereIsMyAmulet", "1.0.0")]
	public sealed class WhereIsMyAmuletPlugin : BaseUnityPlugin
	{
		public const string PluginGuid = "com.wuyachiyu.WhereIsMyAmulet";

		public const string PluginName = "WhereIsMyAmulet";

		public const string PluginVersion = "1.0.0";

		private readonly Dictionary<int, AmuletLabel> _labels = new Dictionary<int, AmuletLabel>();

		private ManualLogSource _log;

		private Canvas _canvas;

		private TMP_FontAsset _font;

		private bool _loggedDiscovery;

		private ConfigEntry<bool> _enabled;

		private ConfigEntry<KeyCode> _scanKey;

		private ConfigEntry<float> _maxDistance;

		private ConfigEntry<float> _fontSize;

		private ConfigEntry<bool> _showOffscreen;

		private void Awake()
		{
			//IL_00d1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d6: Unknown result type (might be due to invalid IL or missing references)
			_log = ((BaseUnityPlugin)this).Logger;
			_enabled = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "Enabled", true, "Show labels for dropped amulet fragments.");
			_scanKey = ((BaseUnityPlugin)this).Config.Bind<KeyCode>("General", "ScanKey", (KeyCode)99, "Press this key to scan for dropped amulet fragments.");
			_maxDistance = ((BaseUnityPlugin)this).Config.Bind<float>("Display", "MaxDistance", 500f, "Maximum distance in metres for a label. Set to 0 for unlimited.");
			_fontSize = ((BaseUnityPlugin)this).Config.Bind<float>("Display", "FontSize", 22f, "Distance label font size.");
			_showOffscreen = ((BaseUnityPlugin)this).Config.Bind<bool>("Display", "ShowOffscreenDirection", true, "Show a direction marker on the screen edge for offscreen fragments.");
			CreateCanvas();
			_log.LogInfo((object)("WhereIsMyAmulet v1.0.0 loaded. Press " + ((object)_scanKey.Value/*cast due to .constrained prefix*/).ToString() + " to scan for dropped fragments."));
		}

		private void Update()
		{
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			if (!_enabled.Value)
			{
				ClearLabels();
				return;
			}
			if (Input.GetKeyDown(_scanKey.Value))
			{
				ScanItems();
			}
			foreach (AmuletLabel item in _labels.Values.ToList())
			{
				if (item.IsValid)
				{
					item.Update(Camera.main, _maxDistance.Value, _showOffscreen.Value);
				}
				else
				{
					RemoveLabel(item.InstanceId);
				}
			}
		}

		private void OnDestroy()
		{
			ClearLabels();
			if ((Object)(object)_canvas != (Object)null)
			{
				Object.Destroy((Object)(object)((Component)_canvas).gameObject);
			}
		}

		private void CreateCanvas()
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Expected O, but got Unknown
			//IL_0057: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = new GameObject("WhereIsMyAmuletCanvas");
			Object.DontDestroyOnLoad((Object)(object)val);
			val.layer = 5;
			_canvas = val.AddComponent<Canvas>();
			_canvas.renderMode = (RenderMode)0;
			_canvas.sortingOrder = 32700;
			CanvasScaler obj = val.AddComponent<CanvasScaler>();
			obj.uiScaleMode = (ScaleMode)1;
			obj.referenceResolution = new Vector2(1920f, 1080f);
			val.AddComponent<GraphicRaycaster>();
			_font = FindFont();
		}

		private void ScanItems()
		{
			//IL_006f: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)_font == (Object)null)
			{
				_font = FindFont();
			}
			Item[] array = Object.FindObjectsByType<Item>((FindObjectsSortMode)0);
			HashSet<int> hashSet = new HashSet<int>();
			Item[] array2 = array;
			Backpack backpack = default(Backpack);
			foreach (Item item in array2)
			{
				if ((Object)(object)item == (Object)null || !((Component)item).gameObject.activeInHierarchy || (int)item.itemState != 0)
				{
					continue;
				}
				if (Matches(item))
				{
					int instanceID = ((Object)((Component)item).gameObject).GetInstanceID();
					hashSet.Add(instanceID);
					AddLabel(instanceID, ((Component)item).transform, "Amulet", () => (Object)(object)item != (Object)null && ((Component)item).gameObject.activeInHierarchy && (int)item.itemState == 0);
				}
				ref Backpack reference = ref backpack;
				Item obj = item;
				reference = (Backpack)(object)((obj is Backpack) ? obj : null);
				if ((Object)(object)backpack != (Object)null && HasAmulet(((Item)backpack).data))
				{
					int instanceID2 = ((Object)((Component)backpack).gameObject).GetInstanceID();
					hashSet.Add(instanceID2);
					AddLabel(instanceID2, ((Component)backpack).transform, "Backpack\nAmulet", () => (Object)(object)backpack != (Object)null && ((Component)backpack).gameObject.activeInHierarchy && (int)((Item)backpack).itemState == 0 && HasAmulet(((Item)backpack).data));
				}
			}
			foreach (int item2 in _labels.Keys.ToList())
			{
				if (!hashSet.Contains(item2))
				{
					RemoveLabel(item2);
				}
			}
		}

		private static bool Matches(Item item)
		{
			return ((Object)((Component)item).gameObject).name.IndexOf("amulet", StringComparison.OrdinalIgnoreCase) >= 0;
		}

		private void AddLabel(int id, Transform target, string title, Func<bool> isValid)
		{
			if (!_labels.ContainsKey(id))
			{
				_labels.Add(id, new AmuletLabel(((Component)_canvas).transform, target, title, isValid, _font, _fontSize));
				if (!_loggedDiscovery)
				{
					_log.LogInfo((object)("Found amulet target: " + title));
					_loggedDiscovery = true;
				}
			}
		}

		private static bool HasAmulet(ItemInstanceData instanceData)
		{
			BackpackData val = default(BackpackData);
			if (instanceData == null || !instanceData.TryGetDataEntry<BackpackData>((DataEntryKey)7, ref val) || val == null || val.itemSlots == null)
			{
				return false;
			}
			ItemSlot[] itemSlots = val.itemSlots;
			foreach (ItemSlot val2 in itemSlots)
			{
				if (val2 != null && !val2.IsEmpty() && (Object)(object)val2.prefab != (Object)null && Matches(val2.prefab))
				{
					return true;
				}
			}
			return false;
		}

		private void RemoveLabel(int id)
		{
			if (_labels.TryGetValue(id, out var value))
			{
				value.Dispose();
				_labels.Remove(id);
			}
		}

		private void ClearLabels()
		{
			foreach (AmuletLabel value in _labels.Values)
			{
				value.Dispose();
			}
			_labels.Clear();
		}

		private static TMP_FontAsset FindFont()
		{
			try
			{
				if ((Object)(object)GUIManager.instance != (Object)null)
				{
					AscentUI componentInChildren = ((Component)GUIManager.instance).GetComponentInChildren<AscentUI>(true);
					if ((Object)(object)componentInChildren != (Object)null && (Object)(object)componentInChildren.text != (Object)null && (Object)(object)((TMP_Text)componentInChildren.text).font != (Object)null)
					{
						return ((TMP_Text)componentInChildren.text).font;
					}
					if ((Object)(object)GUIManager.instance.heroDayText != (Object)null && (Object)(object)((TMP_Text)GUIManager.instance.heroDayText).font != (Object)null)
					{
						return ((TMP_Text)GUIManager.instance.heroDayText).font;
					}
				}
				TextMeshProUGUI val = Object.FindAnyObjectByType<TextMeshProUGUI>();
				if ((Object)(object)val != (Object)null && (Object)(object)((TMP_Text)val).font != (Object)null)
				{
					return ((TMP_Text)val).font;
				}
				if ((Object)(object)TMP_Settings.defaultFontAsset != (Object)null)
				{
					return TMP_Settings.defaultFontAsset;
				}
			}
			catch (Exception ex)
			{
				Debug.LogWarning((object)("WhereIsMyAmulet: failed to find a game font: " + ex.Message));
			}
			return null;
		}
	}
	internal sealed class AmuletLabel
	{
		private readonly int _instanceId;

		private readonly Transform _target;

		private readonly Func<bool> _isValid;

		private readonly string _title;

		private readonly GameObject _root;

		private readonly CanvasGroup _group;

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

		private readonly TextMeshProUGUI _mainText;

		private readonly TextMeshProUGUI _arrow;

		private static readonly Vector2[] ShadowOffsets = (Vector2[])(object)new Vector2[8]
		{
			new Vector2(0f, 1f),
			new Vector2(0f, -1f),
			new Vector2(-1f, 0f),
			new Vector2(1f, 0f),
			new Vector2(-1f, 1f),
			new Vector2(1f, 1f),
			new Vector2(-1f, -1f),
			new Vector2(1f, -1f)
		};

		public int InstanceId => _instanceId;

		public bool IsValid
		{
			get
			{
				if ((Object)(object)_target != (Object)null && _isValid != null)
				{
					return _isValid();
				}
				return false;
			}
		}

		public AmuletLabel(Transform canvas, Transform target, string title, Func<bool> isValid, TMP_FontAsset font, ConfigEntry<float> fontSize)
		{
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0054: Expected O, but got Unknown
			//IL_00d5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00eb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f5: Unknown result type (might be due to invalid IL or missing references)
			//IL_0147: Unknown result type (might be due to invalid IL or missing references)
			//IL_0156: Unknown result type (might be due to invalid IL or missing references)
			//IL_015c: Expected O, but got Unknown
			//IL_01dd: Unknown result type (might be due to invalid IL or missing references)
			//IL_0208: Unknown result type (might be due to invalid IL or missing references)
			//IL_0227: Unknown result type (might be due to invalid IL or missing references)
			_instanceId = ((!((Object)(object)target == (Object)null)) ? ((Object)((Component)target).gameObject).GetInstanceID() : 0);
			_target = target;
			_title = title;
			_isValid = isValid;
			_root = new GameObject("AmuletDistanceLabel");
			_root.transform.SetParent(canvas, false);
			_root.layer = 5;
			_group = _root.AddComponent<CanvasGroup>();
			_group.blocksRaycasts = false;
			_group.interactable = false;
			for (int i = 0; i < 8; i++)
			{
				TextMeshProUGUI val = CreateText("Shadow_" + i, font, fontSize.Value);
				((Graphic)val).color = new Color(0f, 0f, 0f, 0.9f);
				((TMP_Text)val).rectTransform.anchoredPosition = ShadowOffsets[i] * 1.5f;
				_shadowTexts.Add(val);
			}
			_mainText = CreateText("MainText", font, fontSize.Value);
			((Graphic)_mainText).color = new Color(0.875f, 0.855f, 0.761f, 1f);
			GameObject val2 = new GameObject("OffscreenDirection");
			val2.transform.SetParent(_root.transform, false);
			_arrow = val2.AddComponent<TextMeshProUGUI>();
			val2.layer = 5;
			((TMP_Text)_arrow).font = font;
			((TMP_Text)_arrow).text = "^";
			((TMP_Text)_arrow).alignment = (TextAlignmentOptions)514;
			((TMP_Text)_arrow).fontSize = 22f;
			((Graphic)_arrow).color = new Color(1f, 0.85f, 0.2f, 1f);
			((Graphic)_arrow).raycastTarget = false;
			((TMP_Text)_arrow).rectTransform.sizeDelta = new Vector2(18f, 18f);
			((TMP_Text)_arrow).rectTransform.anchoredPosition = new Vector2(0f, -28f);
			((Behaviour)_arrow).enabled = false;
		}

		private TextMeshProUGUI CreateText(string name, TMP_FontAsset font, float size)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_001d: 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_0086: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = new GameObject(name);
			val.transform.SetParent(_root.transform, false);
			val.layer = 5;
			TextMeshProUGUI obj = val.AddComponent<TextMeshProUGUI>();
			((TMP_Text)obj).alignment = (TextAlignmentOptions)514;
			((Graphic)obj).raycastTarget = false;
			((TMP_Text)obj).overflowMode = (TextOverflowModes)0;
			((TMP_Text)obj).richText = true;
			((TMP_Text)obj).font = font;
			((TMP_Text)obj).fontSize = Mathf.Clamp(size, 10f, 64f);
			((TMP_Text)obj).rectTransform.sizeDelta = new Vector2(260f, 90f);
			((TMP_Text)obj).rectTransform.anchoredPosition = Vector2.zero;
			return obj;
		}

		public void Update(Camera camera, float maxDistance, bool showOffscreen)
		{
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: 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_0030: 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_0033: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			//IL_003f: Unknown result type (might be due to invalid IL or missing references)
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: Unknown result type (might be due to invalid IL or missing references)
			//IL_007b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0088: 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)
			//IL_00c6: 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_00a2: 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_011c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0131: Unknown result type (might be due to invalid IL or missing references)
			//IL_0133: Unknown result type (might be due to invalid IL or missing references)
			//IL_0138: Unknown result type (might be due to invalid IL or missing references)
			//IL_0198: Unknown result type (might be due to invalid IL or missing references)
			//IL_019a: Unknown result type (might be due to invalid IL or missing references)
			//IL_019e: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a3: 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_01e9: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f0: Unknown result type (might be due to invalid IL or missing references)
			//IL_0208: Unknown result type (might be due to invalid IL or missing references)
			//IL_0148: Unknown result type (might be due to invalid IL or missing references)
			//IL_014d: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)camera == (Object)null)
			{
				SetVisible(visible: false);
				return;
			}
			Vector3 val = _target.position + Vector3.up * 0.8f;
			Vector3 val2 = camera.WorldToViewportPoint(val);
			float num = Vector3.Distance(((Component)camera).transform.position, _target.position);
			bool flag = maxDistance <= 0f || num <= maxDistance;
			bool flag2 = val2.z > 0f;
			if (flag2 && val2.x >= 0f && val2.x <= 1f && val2.y >= 0f && val2.y <= 1f && flag)
			{
				_root.transform.position = camera.WorldToScreenPoint(val);
				SetText($"<b>{_title}</b>\n<size=18>{num:F0}m</size>");
				((Behaviour)_arrow).enabled = false;
				SetVisible(visible: true);
				return;
			}
			if (!showOffscreen || !flag)
			{
				SetVisible(visible: false);
				return;
			}
			Vector2 val3 = default(Vector2);
			((Vector2)(ref val3))..ctor(val2.x - 0.5f, val2.y - 0.5f);
			if (!flag2)
			{
				val3 = -val3;
			}
			if (((Vector2)(ref val3)).sqrMagnitude < 0.001f)
			{
				val3 = Vector2.up;
			}
			((Vector2)(ref val3)).Normalize();
			Vector2 val4 = default(Vector2);
			((Vector2)(ref val4))..ctor((float)Screen.width * 0.5f, (float)Screen.height * 0.5f);
			float num2 = (float)Mathf.Min(Screen.width, Screen.height) * 0.42f;
			_root.transform.position = Vector2.op_Implicit(val4 + val3 * num2);
			SetText($"{num:F0}m");
			((Behaviour)_arrow).enabled = true;
			((Transform)((TMP_Text)_arrow).rectTransform).localRotation = Quaternion.Euler(0f, 0f, Mathf.Atan2(val3.y, val3.x) * 57.29578f - 90f);
			SetVisible(visible: true);
		}

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

		private void SetVisible(bool visible)
		{
			_group.alpha = (visible ? 1f : 0f);
		}

		private void SetText(string value)
		{
			((TMP_Text)_mainText).text = value;
			foreach (TextMeshProUGUI shadowText in _shadowTexts)
			{
				((TMP_Text)shadowText).text = value;
			}
		}
	}
}