Decompiled source of EnhancedPing v1.0.0

plugins/EnhancedPing.dll

Decompiled 8 hours ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.Numerics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using EnhancedPing.Core;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using Photon.Pun;
using TMPro;
using UnityEngine;
using UnityEngine.InputSystem;
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("EnhancedPing")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0+7191e90729a136227fa75d774a7fa881c5a0faf1")]
[assembly: AssemblyProduct("EnhancedPing")]
[assembly: AssemblyTitle("EnhancedPing")]
[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.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableAttribute : Attribute
	{
		public readonly byte[] NullableFlags;

		public NullableAttribute(byte P_0)
		{
			NullableFlags = new byte[1] { P_0 };
		}

		public NullableAttribute(byte[] P_0)
		{
			NullableFlags = P_0;
		}
	}
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableContextAttribute : Attribute
	{
		public readonly byte Flag;

		public NullableContextAttribute(byte P_0)
		{
			Flag = P_0;
		}
	}
	[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 EnhancedPing
{
	internal sealed class EnhancedPingController
	{
		private readonly Plugin _plugin;

		private readonly ModConfig _config;

		private readonly ManualLogSource _logger;

		private readonly PathPreview _preview = new PathPreview();

		private readonly PingDistanceOverlay _distanceOverlay;

		private readonly GhostReticleOverlay _ghostReticle = new GhostReticleOverlay();

		private static readonly MethodInfo? ReceivePointMethod = AccessTools.Method(typeof(PointPinger), "ReceivePoint_Rpc", (Type[])null, (Type[])null);

		private PatchCapabilities _capabilities;

		private PathDrawingSession? _drawing;

		private PointPinger? _drawingPinger;

		private PointPinger? _drawingCarrier;

		private Coroutine? _sequence;

		private PointPinger? _sequencePinger;

		public EnhancedPingController(Plugin plugin, ModConfig config, ManualLogSource logger)
		{
			_plugin = plugin;
			_config = config;
			_logger = logger;
			_distanceOverlay = new PingDistanceOverlay(config, logger);
		}

		public void SetCapabilities(PatchCapabilities capabilities)
		{
			_capabilities = capabilities;
		}

		public void TickLifecycle()
		{
			if (!_config.Enabled.Value)
			{
				Reset("feature disabled");
				return;
			}
			if (_drawing != null && ((Object)(object)_drawingPinger == (Object)null || (Object)(object)_drawingCarrier == (Object)null || (Object)(object)Character.localCharacter == (Object)null || !InputAllowed()))
			{
				CancelDrawing("input or character lifecycle ended");
			}
			if (_sequence != null && ((Object)(object)_sequencePinger == (Object)null || (Object)(object)Character.localCharacter == (Object)null))
			{
				CancelSequence();
			}
		}

		public bool BeforePointPingerUpdate(PointPinger pinger, ref float timeLastPinged)
		{
			if (!_capabilities.Input || !_config.Enabled.Value || !IsLocalPinger(pinger))
			{
				return true;
			}
			InputAction action_ping = CharacterInput.action_ping;
			if (action_ping == null)
			{
				return true;
			}
			if (_drawing != null)
			{
				return ContinueDrawing(pinger, action_ping, ref timeLastPinged);
			}
			if (!_config.PathEnabled.Value)
			{
				if (!_config.GhostEnabled.Value || (Object)(object)pinger.character?.data == (Object)null || !pinger.character.data.dead)
				{
					return true;
				}
				if (action_ping.WasPressedThisFrame() && CanStartEnhancedPing(pinger, timeLastPinged) && InputAllowed() && TryResolvePingCarrier(pinger, out PointPinger carrier) && TryGetPingSample(out var sample))
				{
					timeLastPinged = Time.time;
					SendVanillaPing(carrier, sample);
				}
				return false;
			}
			if (!action_ping.WasPressedThisFrame())
			{
				return true;
			}
			CancelSequence();
			if (CanStartEnhancedPing(pinger, timeLastPinged) && InputAllowed() && TryResolvePingCarrier(pinger, out PointPinger carrier2))
			{
				BeginDrawing(pinger, carrier2);
			}
			return false;
		}

		public void ShowDistanceLabel(PointPinger pinger, GameObject previousMarker, GameObject currentMarker)
		{
			if (_capabilities.Distance && !((Object)(object)pinger.character == (Object)null) && !((Object)(object)currentMarker == (Object)null) && previousMarker != currentMarker)
			{
				_distanceOverlay.Show(pinger.character, currentMarker);
			}
		}

		public void InitializeDistanceOverlay(GUIManager gui)
		{
			if (_config.Enabled.Value && _config.DistanceEnabled.Value)
			{
				_distanceOverlay.Initialize(gui);
			}
		}

		public void DestroyDistanceOverlay()
		{
			_distanceOverlay.Dispose();
			_ghostReticle.Dispose();
		}

		public void UpdateDeadReticle(GUIManager gui)
		{
			Character localCharacter = Character.localCharacter;
			bool visible = _capabilities.DeadReticle && (Object)(object)localCharacter != (Object)null && (Object)(object)localCharacter.data != (Object)null && localCharacter.data.dead && _config.Enabled.Value && _config.GhostEnabled.Value && _config.ShowReticleWhenDead.Value && Time.timeScale > 0f && !GUIManager.InPauseMenu && !gui.windowBlockingInput && !gui.wheelActive;
			_ghostReticle.Update(gui, visible);
		}

		public void Reset(string reason)
		{
			bool num = _drawing != null || _sequence != null;
			CancelDrawing(reason);
			CancelSequence();
			_distanceOverlay.Dispose();
			_ghostReticle.Dispose();
			if (num)
			{
				_logger.LogDebug((object)("Enhanced ping state reset: " + reason + "."));
			}
		}

		private bool ContinueDrawing(PointPinger pinger, InputAction pingAction, ref float timeLastPinged)
		{
			PointPinger drawingCarrier = _drawingCarrier;
			if ((Object)(object)pinger != (Object)(object)_drawingPinger || (Object)(object)drawingCarrier == (Object)null || !IsLivingCarrier(drawingCarrier) || !_config.PathEnabled.Value || !InputAllowed())
			{
				CancelDrawing("path drawing cancelled");
				return false;
			}
			CaptureDrawingSample();
			if (pingAction.IsPressed() && !pingAction.WasReleasedThisFrame())
			{
				return false;
			}
			PathDrawingResult pathDrawingResult = _drawing.Finish(_config.SafeMaximumPingPoints);
			CancelDrawing("path drawing completed");
			if (pathDrawingResult.Samples.Count == 0)
			{
				return false;
			}
			timeLastPinged = Time.time;
			if (pathDrawingResult.TotalAngleDegrees < _config.SafeMinimumPathAngle || pathDrawingResult.Samples.Count < 2)
			{
				SendVanillaPing(drawingCarrier, pathDrawingResult.Samples[pathDrawingResult.Samples.Count - 1]);
				return false;
			}
			_sequencePinger = drawingCarrier;
			_sequence = ((MonoBehaviour)_plugin).StartCoroutine(SendSequence(drawingCarrier, pathDrawingResult.Samples));
			return false;
		}

		private void BeginDrawing(PointPinger pinger, PointPinger carrier)
		{
			//IL_0042: Unknown result type (might be due to invalid IL or missing references)
			CancelDrawing("new path started");
			_drawing = new PathDrawingSession();
			_drawingPinger = pinger;
			_drawingCarrier = carrier;
			if (_config.ShowPathPreview.Value)
			{
				_preview.Initialize(GetPlayerColor(carrier.character));
			}
			CaptureDrawingSample();
		}

		private void CaptureDrawingSample()
		{
			if (_drawing != null && TryGetPingSample(out var sample))
			{
				_drawing.Capture(sample, _config.SafeMinimumCaptureAngle);
				if (_config.ShowPathPreview.Value)
				{
					_preview.Update(_drawing.PreviewSamples);
				}
			}
		}

		private IEnumerator SendSequence(PointPinger pinger, IReadOnlyList<RuntimePingSample> samples)
		{
			float num = SequenceTiming.EffectivePointDuration(samples.Count, _config.SafePreferredPointDuration, _config.SafeMaximumSequenceDuration);
			WaitForSeconds wait = new WaitForSeconds(num);
			for (int i = 0; i < samples.Count; i++)
			{
				if ((Object)(object)pinger == (Object)null)
				{
					break;
				}
				if (!IsLivingCarrier(pinger))
				{
					break;
				}
				if (!_config.Enabled.Value)
				{
					break;
				}
				SendVanillaPing(pinger, samples[i]);
				if (i < samples.Count - 1)
				{
					yield return wait;
				}
			}
			_sequence = null;
			_sequencePinger = null;
		}

		private void SendVanillaPing(PointPinger pinger, RuntimePingSample sample)
		{
			//IL_0060: 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_002f: 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)
			PhotonView component = ((Component)pinger).GetComponent<PhotonView>();
			if (!((Object)(object)component == (Object)null))
			{
				if (pinger.character == Character.localCharacter)
				{
					component.RPC("ReceivePoint_Rpc", (RpcTarget)0, new object[2] { sample.Point, sample.Normal });
				}
				else
				{
					component.RPC("ReceivePoint_Rpc", (RpcTarget)1, new object[2] { sample.Point, sample.Normal });
					ShowPingLocally(pinger, sample);
				}
			}
		}

		private void ShowPingLocally(PointPinger pinger, RuntimePingSample sample)
		{
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			Character localCharacter = Character.localCharacter;
			try
			{
				Character.localCharacter = pinger.character;
				ReceivePointMethod?.Invoke(pinger, new object[2] { sample.Point, sample.Normal });
			}
			catch (Exception arg)
			{
				_logger.LogWarning((object)$"Could not show an enhanced ping locally: {arg}");
			}
			finally
			{
				Character.localCharacter = localCharacter;
			}
		}

		private bool CanStartEnhancedPing(PointPinger pinger, float timeLastPinged)
		{
			if (Time.time - timeLastPinged < pinger.coolDown || (Object)(object)pinger.character?.data == (Object)null)
			{
				return false;
			}
			if (!pinger.character.data.fullyConscious)
			{
				if (_config.GhostEnabled.Value)
				{
					return pinger.character.data.dead;
				}
				return false;
			}
			return true;
		}

		private static bool TryResolvePingCarrier(PointPinger source, out PointPinger carrier)
		{
			carrier = null;
			if ((Object)(object)source.character?.data == (Object)null)
			{
				return false;
			}
			if (!source.character.data.dead)
			{
				carrier = source;
				return IsLivingCarrier(carrier);
			}
			Character specCharacter = MainCameraMovement.specCharacter;
			if ((Object)(object)specCharacter == (Object)null || specCharacter == source.character || (Object)(object)specCharacter.data == (Object)null || specCharacter.data.dead)
			{
				return false;
			}
			PointPinger component = ((Component)specCharacter).GetComponent<PointPinger>();
			if (!IsLivingCarrier(component))
			{
				return false;
			}
			carrier = component;
			return true;
		}

		private static bool IsLivingCarrier(PointPinger pinger)
		{
			if ((Object)(object)pinger == (Object)null || (Object)(object)pinger.character?.data == (Object)null || pinger.character.data.dead)
			{
				return false;
			}
			PhotonView component = ((Component)pinger).GetComponent<PhotonView>();
			if ((Object)(object)component != (Object)null)
			{
				return component.ViewID > 0;
			}
			return false;
		}

		private static bool IsLocalPinger(PointPinger pinger)
		{
			if ((Object)(object)pinger.character == (Object)null || (Object)(object)pinger.character != (Object)(object)Character.localCharacter)
			{
				return false;
			}
			PhotonView component = ((Component)pinger).GetComponent<PhotonView>();
			if ((Object)(object)component != (Object)null)
			{
				return component.IsMine;
			}
			return false;
		}

		private static bool InputAllowed()
		{
			if (Time.timeScale <= 0f || GUIManager.InPauseMenu)
			{
				return false;
			}
			GUIManager instance = GUIManager.instance;
			if (!((Object)(object)instance == (Object)null))
			{
				if (!instance.windowBlockingInput)
				{
					return !instance.wheelActive;
				}
				return false;
			}
			return true;
		}

		private static bool TryGetPingSample(out RuntimePingSample sample)
		{
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: 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_0047: Unknown result type (might be due to invalid IL or missing references)
			//IL_0055: Unknown result type (might be due to invalid IL or missing references)
			//IL_0063: Unknown result type (might be due to invalid IL or missing references)
			//IL_0074: Unknown result type (might be due to invalid IL or missing references)
			//IL_0079: Unknown result type (might be due to invalid IL or missing references)
			//IL_007d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0084: Unknown result type (might be due to invalid IL or missing references)
			//IL_008b: Unknown result type (might be due to invalid IL or missing references)
			sample = default(RuntimePingSample);
			Camera main = Camera.main;
			if ((Object)(object)main == (Object)null)
			{
				return false;
			}
			Ray val = main.ScreenPointToRay(Input.mousePosition);
			int num = LayerMask.op_Implicit(HelperFunctions.GetMask((LayerType)1));
			RaycastHit val2 = default(RaycastHit);
			if (num == 0 || !Physics.Raycast(val, ref val2, float.PositiveInfinity, num))
			{
				return false;
			}
			if (!IsFinite(((Ray)(ref val)).direction) || !IsFinite(((RaycastHit)(ref val2)).point) || !IsFinite(((RaycastHit)(ref val2)).normal))
			{
				return false;
			}
			Vector3 direction = ((Ray)(ref val)).direction;
			sample = new RuntimePingSample(((Vector3)(ref direction)).normalized, ((RaycastHit)(ref val2)).point, ((RaycastHit)(ref val2)).normal);
			return true;
		}

		private void CancelDrawing(string reason)
		{
			if (_drawing != null)
			{
				_logger.LogDebug((object)("Path drawing ended: " + reason + "."));
			}
			_drawing = null;
			_drawingPinger = null;
			_drawingCarrier = null;
			_preview.Dispose();
		}

		private void CancelSequence()
		{
			if (_sequence != null)
			{
				((MonoBehaviour)_plugin).StopCoroutine(_sequence);
			}
			_sequence = null;
			_sequencePinger = null;
		}

		private static Color GetPlayerColor(Character character)
		{
			//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_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_001c: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				return character.refs.customization.PlayerColor;
			}
			catch
			{
				return Color.white;
			}
		}

		private static bool IsFinite(Vector3 value)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			if (IsFinite(value.x) && IsFinite(value.y))
			{
				return IsFinite(value.z);
			}
			return false;
		}

		private static bool IsFinite(float value)
		{
			if (!float.IsNaN(value))
			{
				return !float.IsInfinity(value);
			}
			return false;
		}
	}
	internal sealed class GhostReticleOverlay
	{
		private Canvas? _canvas;

		private Image? _image;

		private GUIManager? _gui;

		public void Update(GUIManager gui, bool visible)
		{
			if (!visible)
			{
				if ((Object)(object)_canvas != (Object)null && ((Component)_canvas).gameObject.activeSelf)
				{
					((Component)_canvas).gameObject.SetActive(false);
				}
				return;
			}
			if ((Object)(object)_canvas == (Object)null || (Object)(object)_image == (Object)null || (Object)(object)_gui != (Object)(object)gui)
			{
				Initialize(gui);
			}
			if ((Object)(object)_canvas != (Object)null && !((Component)_canvas).gameObject.activeSelf)
			{
				((Component)_canvas).gameObject.SetActive(true);
			}
		}

		public void Dispose()
		{
			if ((Object)(object)_canvas != (Object)null)
			{
				Object.Destroy((Object)(object)((Component)_canvas).gameObject);
			}
			_canvas = null;
			_image = null;
			_gui = null;
		}

		private void Initialize(GUIManager gui)
		{
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0050: Expected O, but got Unknown
			//IL_00af: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f7: Expected O, but got Unknown
			//IL_0126: Unknown result type (might be due to invalid IL or missing references)
			//IL_013b: 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_0152: Unknown result type (might be due to invalid IL or missing references)
			//IL_015e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0163: Unknown result type (might be due to invalid IL or missing references)
			//IL_0167: Unknown result type (might be due to invalid IL or missing references)
			//IL_0172: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b1: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c2: Unknown result type (might be due to invalid IL or missing references)
			Dispose();
			Image reticleDefaultImage = gui.reticleDefaultImage;
			if (!((Object)(object)reticleDefaultImage == (Object)null) && !((Object)(object)reticleDefaultImage.sprite == (Object)null))
			{
				GameObject val = new GameObject("Canvas_EnhancedPingGhostReticle", new Type[2]
				{
					typeof(Canvas),
					typeof(CanvasScaler)
				});
				val.transform.SetParent(((Component)gui).transform, false);
				val.layer = LayerMask.NameToLayer("UI");
				_canvas = val.GetComponent<Canvas>();
				_canvas.renderMode = (RenderMode)0;
				_canvas.sortingOrder = 101;
				CanvasScaler component = val.GetComponent<CanvasScaler>();
				component.uiScaleMode = (ScaleMode)1;
				component.referenceResolution = new Vector2(1920f, 1080f);
				component.screenMatchMode = (ScreenMatchMode)1;
				GameObject val2 = new GameObject("EnhancedPingGhostReticle", new Type[3]
				{
					typeof(RectTransform),
					typeof(CanvasRenderer),
					typeof(Image)
				});
				val2.transform.SetParent(((Component)_canvas).transform, false);
				RectTransform rectTransform = ((Graphic)reticleDefaultImage).rectTransform;
				RectTransform component2 = val2.GetComponent<RectTransform>();
				component2.anchorMin = new Vector2(0.5f, 0.5f);
				component2.anchorMax = new Vector2(0.5f, 0.5f);
				component2.pivot = rectTransform.pivot;
				component2.anchoredPosition = Vector2.zero;
				Rect rect = rectTransform.rect;
				component2.sizeDelta = ((Rect)(ref rect)).size;
				((Transform)component2).localScale = ((Transform)rectTransform).localScale;
				_image = val2.GetComponent<Image>();
				_image.sprite = reticleDefaultImage.sprite;
				((Graphic)_image).material = ((Graphic)reticleDefaultImage).material;
				((Graphic)_image).color = ((Graphic)reticleDefaultImage).color;
				_image.type = reticleDefaultImage.type;
				_image.preserveAspect = reticleDefaultImage.preserveAspect;
				((Graphic)_image).raycastTarget = false;
				_gui = gui;
			}
		}
	}
	internal sealed class ModConfig
	{
		private const int DefaultMaximumPingPoints = 10;

		private const float DefaultMinimumCaptureAngle = 0.5f;

		private const float DefaultMinimumPathAngle = 1.5f;

		private const float DefaultPreferredPointDuration = 0.2f;

		private const float DefaultMaximumSequenceDuration = 2f;

		private const int DefaultFontSize = 24;

		public ConfigEntry<bool> Enabled { get; }

		public ConfigEntry<bool> DistanceEnabled { get; }

		public ConfigEntry<int> DistanceDecimalPlaces { get; }

		public ConfigEntry<int> DistanceFontSize { get; }

		public ConfigEntry<bool> GhostEnabled { get; }

		public ConfigEntry<bool> ShowReticleWhenDead { get; }

		public ConfigEntry<bool> PathEnabled { get; }

		public ConfigEntry<int> MaximumPingPoints { get; }

		public ConfigEntry<float> MinimumCaptureAngleDegrees { get; }

		public ConfigEntry<float> MinimumPathAngleDegrees { get; }

		public ConfigEntry<float> PreferredPointDurationSeconds { get; }

		public ConfigEntry<float> MaximumSequenceDurationSeconds { get; }

		public ConfigEntry<bool> ShowPathPreview { get; }

		public int SafeDistanceDecimals => Mathf.Clamp(DistanceDecimalPlaces.Value, 0, 1);

		public int SafeDistanceFontSize => Mathf.Clamp(DistanceFontSize.Value, 10, 72);

		public int SafeMaximumPingPoints => Mathf.Clamp(MaximumPingPoints.Value, 2, 20);

		public float SafeMinimumCaptureAngle => SafeRange(MinimumCaptureAngleDegrees.Value, 0.05f, 5f, 0.5f);

		public float SafeMinimumPathAngle => SafeRange(MinimumPathAngleDegrees.Value, 0.1f, 30f, 1.5f);

		public float SafePreferredPointDuration => SafeRange(PreferredPointDurationSeconds.Value, 0.05f, 1f, 0.2f);

		public float SafeMaximumSequenceDuration => SafeRange(MaximumSequenceDurationSeconds.Value, 1f, 10f, 2f);

		public ModConfig(ConfigFile config)
		{
			//IL_005c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0066: Expected O, but got Unknown
			//IL_008c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0096: 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_0148: Unknown result type (might be due to invalid IL or missing references)
			//IL_0152: 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
			//IL_01ba: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c4: Expected O, but got Unknown
			//IL_01f3: Unknown result type (might be due to invalid IL or missing references)
			//IL_01fd: Expected O, but got Unknown
			Enabled = config.Bind<bool>("General", "Enabled", true, "Enable EnhancedPing features.");
			DistanceEnabled = config.Bind<bool>("Distance", "Enabled", true, "Show distance on visible ping markers.");
			DistanceDecimalPlaces = config.Bind<int>("Distance", "DecimalPlaces", 0, new ConfigDescription("Number of decimal places used by distance labels.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 1), Array.Empty<object>()));
			DistanceFontSize = config.Bind<int>("Distance", "FontSize", 24, new ConfigDescription("Distance label font size.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(10, 72), Array.Empty<object>()));
			GhostEnabled = config.Bind<bool>("Ghost", "Enabled", true, "Allow ping input while the local scout is dead.");
			ShowReticleWhenDead = config.Bind<bool>("Ghost", "ShowReticleWhenDead", true, "Show PEAK's default center reticle while the local scout is dead.");
			PathEnabled = config.Bind<bool>("Path", "Enabled", true, "Hold the rebound Ping action and move the aim to draw a path.");
			MaximumPingPoints = config.Bind<int>("Path", "MaximumPingPoints", 10, new ConfigDescription("Maximum transmitted points, including the start and end.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(2, 20), Array.Empty<object>()));
			MinimumCaptureAngleDegrees = config.Bind<float>("Path", "MinimumCaptureAngleDegrees", 0.5f, new ConfigDescription("Minimum angular movement between captured aim rays.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.05f, 5f), Array.Empty<object>()));
			MinimumPathAngleDegrees = config.Bind<float>("Path", "MinimumPathAngleDegrees", 1.5f, new ConfigDescription("Minimum cumulative angular movement required to classify a held Ping as a path.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.1f, 30f), Array.Empty<object>()));
			PreferredPointDurationSeconds = config.Bind<float>("Path", "PreferredPointDurationSeconds", 0.2f, new ConfigDescription("Preferred lifetime of each intermediate ping before the next replaces it.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.05f, 1f), Array.Empty<object>()));
			MaximumSequenceDurationSeconds = config.Bind<float>("Path", "MaximumSequenceDurationSeconds", 2f, new ConfigDescription("Maximum time from the first path ping until the endpoint appears.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 10f), Array.Empty<object>()));
			ShowPathPreview = config.Bind<bool>("Path", "ShowPreview", true, "Show a local line while drawing a path.");
		}

		private static float SafeRange(float value, float minimum, float maximum, float fallback)
		{
			if (float.IsNaN(value) || float.IsInfinity(value))
			{
				return fallback;
			}
			return Mathf.Clamp(value, minimum, maximum);
		}
	}
	internal readonly struct PatchCapabilities
	{
		public bool Input { get; }

		public bool Distance { get; }

		public bool DeadReticle { get; }

		public PatchCapabilities(bool input, bool distance, bool deadReticle)
		{
			Input = input;
			Distance = distance;
			DeadReticle = deadReticle;
		}
	}
	internal static class PatchInstaller
	{
		public static PatchCapabilities Install(Harmony harmony, ManualLogSource logger)
		{
			bool input = TryPatch(harmony, AccessTools.Method(typeof(PointPinger), "Update", (Type[])null, (Type[])null), AccessTools.Method(typeof(PatchCallbacks), "PointPingerUpdatePrefix", (Type[])null, (Type[])null), null, "PointPinger.Update", logger);
			bool distance = TryPatch(harmony, AccessTools.Method(typeof(PointPinger), "ReceivePoint_Rpc", (Type[])null, (Type[])null), AccessTools.Method(typeof(PatchCallbacks), "ReceivePointPrefix", (Type[])null, (Type[])null), AccessTools.Method(typeof(PatchCallbacks), "ReceivePointPostfix", (Type[])null, (Type[])null), "PointPinger.ReceivePoint_Rpc", logger);
			TryPatch(harmony, AccessTools.Method(typeof(GUIManager), "Start", (Type[])null, (Type[])null), null, AccessTools.Method(typeof(PatchCallbacks), "GUIManagerStartPostfix", (Type[])null, (Type[])null), "GUIManager.Start", logger);
			TryPatch(harmony, AccessTools.Method(typeof(GUIManager), "OnDestroy", (Type[])null, (Type[])null), AccessTools.Method(typeof(PatchCallbacks), "GUIManagerOnDestroyPrefix", (Type[])null, (Type[])null), null, "GUIManager.OnDestroy", logger);
			bool deadReticle = TryPatch(harmony, AccessTools.Method(typeof(GUIManager), "LateUpdate", (Type[])null, (Type[])null), null, AccessTools.Method(typeof(PatchCallbacks), "GUIManagerLateUpdatePostfix", (Type[])null, (Type[])null), "GUIManager.LateUpdate", logger);
			return new PatchCapabilities(input, distance, deadReticle);
		}

		private static bool TryPatch(Harmony harmony, MethodInfo? original, MethodInfo? prefix = null, MethodInfo? postfix = null, string? description = null, ManualLogSource? logger = null)
		{
			//IL_0046: Unknown result type (might be due to invalid IL or missing references)
			//IL_004b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0063: 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)
			if (original == null || (prefix == null && postfix == null))
			{
				if (logger != null)
				{
					logger.LogError((object)("Required patch target is missing: " + description + "."));
				}
				return false;
			}
			try
			{
				harmony.Patch((MethodBase)original, (prefix == null) ? ((HarmonyMethod)null) : new HarmonyMethod(prefix)
				{
					priority = 800
				}, (postfix == null) ? ((HarmonyMethod)null) : new HarmonyMethod(postfix)
				{
					priority = 0
				}, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
				return true;
			}
			catch (Exception arg)
			{
				if (logger != null)
				{
					logger.LogError((object)$"Failed to patch {description}: {arg}");
				}
				return false;
			}
		}
	}
	internal static class PatchCallbacks
	{
		public static bool PointPingerUpdatePrefix(PointPinger __instance, ref float ____timeLastPinged)
		{
			return (Plugin.Instance?.Controller)?.BeforePointPingerUpdate(__instance, ref ____timeLastPinged) ?? true;
		}

		public static void ReceivePointPrefix(ref GameObject ___pingInstance, out GameObject __state)
		{
			__state = ___pingInstance;
		}

		public static void ReceivePointPostfix(PointPinger __instance, GameObject __state, ref GameObject ___pingInstance)
		{
			Plugin.Instance?.Controller.ShowDistanceLabel(__instance, __state, ___pingInstance);
		}

		public static void GUIManagerStartPostfix(GUIManager __instance)
		{
			Plugin.Instance?.Controller.InitializeDistanceOverlay(__instance);
		}

		public static void GUIManagerOnDestroyPrefix(GUIManager __instance)
		{
			Plugin.Instance?.Controller.DestroyDistanceOverlay();
		}

		public static void GUIManagerLateUpdatePostfix(GUIManager __instance)
		{
			Plugin.Instance?.Controller.UpdateDeadReticle(__instance);
		}
	}
	internal readonly struct PathDrawingResult
	{
		public IReadOnlyList<RuntimePingSample> Samples { get; }

		public float TotalAngleDegrees { get; }

		public PathDrawingResult(IReadOnlyList<RuntimePingSample> samples, float totalAngleDegrees)
		{
			Samples = samples;
			TotalAngleDegrees = totalAngleDegrees;
		}
	}
	internal sealed class PathDrawingSession
	{
		private readonly List<RuntimePingSample> _accepted = new List<RuntimePingSample>();

		private RuntimePingSample _latest;

		private bool _hasLatest;

		public IReadOnlyList<RuntimePingSample> PreviewSamples
		{
			get
			{
				//IL_0037: Unknown result type (might be due to invalid IL or missing references)
				//IL_0042: Unknown result type (might be due to invalid IL or missing references)
				if (!_hasLatest || _accepted.Count == 0)
				{
					return _accepted;
				}
				if (Angle(_accepted[_accepted.Count - 1].Direction, _latest.Direction) <= 0.0001f)
				{
					return _accepted;
				}
				List<RuntimePingSample> list = new List<RuntimePingSample>(_accepted.Count + 1);
				list.AddRange(_accepted);
				list.Add(_latest);
				return list;
			}
		}

		public void Capture(RuntimePingSample sample, float minimumAngleDegrees)
		{
			//IL_0036: 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)
			_latest = sample;
			_hasLatest = true;
			if (_accepted.Count == 0 || Angle(_accepted[_accepted.Count - 1].Direction, sample.Direction) >= minimumAngleDegrees)
			{
				_accepted.Add(sample);
			}
		}

		public PathDrawingResult Finish(int maximumPoints)
		{
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_003b: Unknown result type (might be due to invalid IL or missing references)
			if (_hasLatest && (_accepted.Count == 0 || Angle(_accepted[_accepted.Count - 1].Direction, _latest.Direction) > 0.0001f))
			{
				_accepted.Add(_latest);
			}
			List<SphericalPathSample> list = new List<SphericalPathSample>(_accepted.Count);
			foreach (RuntimePingSample item in _accepted)
			{
				list.Add(item.ToCore());
			}
			float totalAngleDegrees;
			IReadOnlyList<SphericalPathSample> readOnlyList = SphericalPathSelector.Select(list, maximumPoints, out totalAngleDegrees);
			List<RuntimePingSample> list2 = new List<RuntimePingSample>(readOnlyList.Count);
			foreach (SphericalPathSample item2 in readOnlyList)
			{
				list2.Add(RuntimePingSample.FromCore(item2));
			}
			return new PathDrawingResult(list2, totalAngleDegrees);
		}

		private static float Angle(Vector3 left, Vector3 right)
		{
			//IL_0022: 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)
			if (((Vector3)(ref left)).sqrMagnitude <= 1E-08f || ((Vector3)(ref right)).sqrMagnitude <= 1E-08f)
			{
				return float.NaN;
			}
			return Vector3.Angle(left, right);
		}
	}
	internal sealed class PathPreview
	{
		private GameObject? _gameObject;

		private LineRenderer? _line;

		private Material? _material;

		public void Initialize(Color color)
		{
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_002b: Expected O, but got Unknown
			//IL_004b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0055: Expected O, but got Unknown
			//IL_00b8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c4: Unknown result type (might be due to invalid IL or missing references)
			Dispose();
			Shader val = Shader.Find("Sprites/Default");
			if (!((Object)(object)val == (Object)null))
			{
				_gameObject = new GameObject("EnhancedPing.PathPreview");
				((Object)_gameObject).hideFlags = (HideFlags)61;
				_line = _gameObject.AddComponent<LineRenderer>();
				_material = new Material(val);
				((Renderer)_line).material = _material;
				_line.useWorldSpace = true;
				_line.alignment = (LineAlignment)0;
				_line.widthMultiplier = 0.045f;
				_line.numCapVertices = 4;
				_line.numCornerVertices = 2;
				color.a = 0.9f;
				_line.startColor = color;
				_line.endColor = color;
				_line.positionCount = 0;
			}
		}

		public void Update(IReadOnlyList<RuntimePingSample> samples)
		{
			//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_0053: Unknown result type (might be due to invalid IL or missing references)
			//IL_0058: Unknown result type (might be due to invalid IL or missing references)
			//IL_005b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0042: Unknown result type (might be due to invalid IL or missing references)
			//IL_0060: Unknown result type (might be due to invalid IL or missing references)
			//IL_0072: Unknown result type (might be due to invalid IL or missing references)
			//IL_0077: Unknown result type (might be due to invalid IL or missing references)
			//IL_007d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0082: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)_line == (Object)null)
			{
				return;
			}
			_line.positionCount = samples.Count;
			for (int i = 0; i < samples.Count; i++)
			{
				Vector3 normal = samples[i].Normal;
				Vector3 val;
				if (!(((Vector3)(ref normal)).sqrMagnitude > 1E-08f))
				{
					val = Vector3.up;
				}
				else
				{
					normal = samples[i].Normal;
					val = ((Vector3)(ref normal)).normalized;
				}
				Vector3 val2 = val;
				_line.SetPosition(i, samples[i].Point + val2 * 0.035f);
			}
		}

		public void Dispose()
		{
			if ((Object)(object)_gameObject != (Object)null)
			{
				Object.Destroy((Object)(object)_gameObject);
			}
			if ((Object)(object)_material != (Object)null)
			{
				Object.Destroy((Object)(object)_material);
			}
			_gameObject = null;
			_line = null;
			_material = null;
		}
	}
	internal sealed class PingDistanceOverlay
	{
		private readonly ModConfig _config;

		private readonly ManualLogSource _logger;

		private readonly Dictionary<Character, GameObject> _instances = new Dictionary<Character, GameObject>();

		private Canvas? _canvas;

		private GameObject? _template;

		public PingDistanceOverlay(ModConfig config, ManualLogSource logger)
		{
			_config = config;
			_logger = logger;
		}

		public void Initialize(GUIManager gui)
		{
			//IL_00a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a9: Expected O, but got Unknown
			//IL_0108: Unknown result type (might be due to invalid IL or missing references)
			//IL_014b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0155: Expected O, but got Unknown
			if ((Object)(object)_canvas != (Object)null && (Object)(object)_template != (Object)null && (Object)(object)((Component)_canvas).transform.parent == (Object)(object)((Component)gui).transform)
			{
				return;
			}
			Dispose();
			TextMeshProUGUI interactNameText = gui.interactNameText;
			if ((Object)(object)interactNameText == (Object)null || (Object)(object)((TMP_Text)interactNameText).font == (Object)null || (Object)(object)((TMP_Text)interactNameText).fontSharedMaterial == (Object)null)
			{
				_logger.LogError((object)"Could not initialize distance labels from GUIManager.interactNameText.");
				return;
			}
			try
			{
				GameObject val = new GameObject("Canvas_EnhancedPingDistance", new Type[2]
				{
					typeof(Canvas),
					typeof(CanvasScaler)
				});
				val.transform.SetParent(((Component)gui).transform, false);
				val.layer = LayerMask.NameToLayer("UI");
				_canvas = val.GetComponent<Canvas>();
				_canvas.renderMode = (RenderMode)0;
				_canvas.sortingOrder = 100;
				CanvasScaler component = val.GetComponent<CanvasScaler>();
				component.uiScaleMode = (ScaleMode)1;
				component.referenceResolution = new Vector2(1920f, 1080f);
				component.screenMatchMode = (ScreenMatchMode)1;
				_template = new GameObject("EnhancedPingDistanceIndicator", new Type[3]
				{
					typeof(RectTransform),
					typeof(CanvasRenderer),
					typeof(PingDistanceLabel)
				});
				_template.transform.SetParent(((Component)_canvas).transform, false);
				CreateText(_template.transform, ((TMP_Text)interactNameText).font, ((TMP_Text)interactNameText).fontSharedMaterial);
				_template.SetActive(false);
				_logger.LogInfo((object)"Distance label overlay initialized from GUIManager.interactNameText.");
			}
			catch (Exception arg)
			{
				_logger.LogWarning((object)$"Could not initialize the ping distance overlay: {arg}");
				Dispose();
			}
		}

		public void Show(Character character, GameObject marker)
		{
			//IL_00c8: 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_00fb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d5: Unknown result type (might be due to invalid IL or missing references)
			if (!_config.Enabled.Value || !_config.DistanceEnabled.Value || (Object)(object)character == (Object)null || (Object)(object)marker == (Object)null)
			{
				return;
			}
			if ((Object)(object)_canvas == (Object)null || (Object)(object)_template == (Object)null)
			{
				GUIManager instance = GUIManager.instance;
				if ((Object)(object)instance != (Object)null)
				{
					Initialize(instance);
				}
			}
			if ((Object)(object)_canvas == (Object)null || (Object)(object)_template == (Object)null)
			{
				return;
			}
			if (_instances.TryGetValue(character, out GameObject value) && (Object)(object)value != (Object)null)
			{
				Object.Destroy((Object)(object)value);
			}
			try
			{
				PointPing component = marker.GetComponent<PointPing>();
				Vector3 normal = (((Object)(object)component != (Object)null && ((Vector3)(ref component.hitNormal)).sqrMagnitude > 1E-08f) ? ((Vector3)(ref component.hitNormal)).normalized : Vector3.up);
				GameObject val = Object.Instantiate<GameObject>(_template, ((Component)_canvas).transform);
				val.GetComponent<PingDistanceLabel>().Initialize(marker, normal, GetPlayerColor(character), _config);
				val.SetActive(true);
				_instances[character] = val;
			}
			catch (Exception arg)
			{
				_logger.LogWarning((object)$"Could not create a ping distance label: {arg}");
			}
		}

		public void Dispose()
		{
			if ((Object)(object)_canvas != (Object)null)
			{
				Object.Destroy((Object)(object)((Component)_canvas).gameObject);
			}
			_canvas = null;
			_template = null;
			_instances.Clear();
		}

		private static void CreateText(Transform parent, TMP_FontAsset font, Material material)
		{
			//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)
			//IL_0051: 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_0077: 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_00a0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00aa: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bf: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f9: Unknown result type (might be due to invalid IL or missing references)
			//IL_011d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0131: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = new GameObject("DistanceText", new Type[4]
			{
				typeof(RectTransform),
				typeof(CanvasRenderer),
				typeof(TextMeshProUGUI),
				typeof(Shadow)
			});
			val.transform.SetParent(parent, false);
			RectTransform component = val.GetComponent<RectTransform>();
			component.anchorMin = new Vector2(0.5f, 0.5f);
			component.anchorMax = new Vector2(0.5f, 0.5f);
			component.pivot = new Vector2(0.5f, 0.5f);
			component.sizeDelta = new Vector2(160f, 50f);
			TextMeshProUGUI component2 = val.GetComponent<TextMeshProUGUI>();
			((TMP_Text)component2).font = font;
			((TMP_Text)component2).fontMaterial = material;
			((Graphic)component2).color = Color.white;
			((TMP_Text)component2).alignment = (TextAlignmentOptions)514;
			((TMP_Text)component2).enableAutoSizing = false;
			((Graphic)component2).raycastTarget = false;
			((TMP_Text)component2).textWrappingMode = (TextWrappingModes)0;
			((TMP_Text)component2).outlineWidth = 0.1f;
			((TMP_Text)component2).outlineColor = Color32.op_Implicit(Color.black);
			Shadow component3 = val.GetComponent<Shadow>();
			component3.effectColor = new Color(0f, 0f, 0f, 0.95f);
			component3.effectDistance = new Vector2(2f, -2f);
		}

		private static Color GetPlayerColor(Character character)
		{
			//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_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_001c: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				return character.refs.customization.PlayerColor;
			}
			catch
			{
				return Color.white;
			}
		}
	}
	internal sealed class PingDistanceLabel : MonoBehaviour
	{
		private GameObject? _marker;

		private Vector3 _normal;

		private Color _color;

		private ModConfig? _config;

		private TextMeshProUGUI? _text;

		public void Initialize(GameObject marker, Vector3 normal, Color color, ModConfig config)
		{
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_0009: 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_0010: Unknown result type (might be due to invalid IL or missing references)
			_marker = marker;
			_normal = normal;
			_color = color;
			_config = config;
			_text = ((Component)this).GetComponentInChildren<TextMeshProUGUI>(true);
		}

		private void LateUpdate()
		{
			//IL_0076: 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_007d: Unknown result type (might be due to invalid IL or missing references)
			//IL_007f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0084: Unknown result type (might be due to invalid IL or missing references)
			//IL_0089: Unknown result type (might be due to invalid IL or missing references)
			//IL_008e: Unknown result type (might be due to invalid IL or missing references)
			//IL_008f: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a4: 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_00de: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f0: Unknown result type (might be due to invalid IL or missing references)
			//IL_0125: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)_marker == (Object)null)
			{
				Object.Destroy((Object)(object)((Component)this).gameObject);
				return;
			}
			Camera main = Camera.main;
			if (_config == null || !_config.Enabled.Value || !_config.DistanceEnabled.Value || (Object)(object)main == (Object)null || (Object)(object)_text == (Object)null)
			{
				SetTextVisible(visible: false);
				return;
			}
			Vector3 position = _marker.transform.position;
			Vector3 val = main.WorldToScreenPoint(position + _normal);
			if (val.z <= 0f)
			{
				SetTextVisible(visible: false);
				return;
			}
			float num = Vector3.Distance(position, ((Component)main).transform.position);
			float num2 = Mathf.Clamp(20f / Mathf.Max(num, 0.01f), 0.5f, 1.5f);
			((Component)this).transform.position = val;
			((Component)this).transform.localScale = new Vector3(num2, num2, num2);
			int safeDistanceDecimals = _config.SafeDistanceDecimals;
			((TMP_Text)_text).fontSize = _config.SafeDistanceFontSize;
			((Graphic)_text).color = _color;
			((TMP_Text)_text).text = num.ToString((safeDistanceDecimals == 0) ? "0" : "0.0", CultureInfo.InvariantCulture) + "m";
			SetTextVisible(visible: true);
		}

		private void SetTextVisible(bool visible)
		{
			if ((Object)(object)_text != (Object)null && ((Component)_text).gameObject.activeSelf != visible)
			{
				((Component)_text).gameObject.SetActive(visible);
			}
		}
	}
	[BepInPlugin("com.github.lllei.EnhancedPing", "EnhancedPing", "1.0.0")]
	public sealed class Plugin : BaseUnityPlugin
	{
		public const string PluginGuid = "com.github.lllei.EnhancedPing";

		public const string PluginName = "EnhancedPing";

		private Harmony? _harmony;

		internal static Plugin? Instance { get; private set; }

		internal EnhancedPingController Controller { get; private set; }

		private void Awake()
		{
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Expected O, but got Unknown
			Instance = this;
			ModConfig config = new ModConfig(((BaseUnityPlugin)this).Config);
			Controller = new EnhancedPingController(this, config, ((BaseUnityPlugin)this).Logger);
			_harmony = new Harmony("com.github.lllei.EnhancedPing");
			PatchCapabilities capabilities = PatchInstaller.Install(_harmony, ((BaseUnityPlugin)this).Logger);
			Controller.SetCapabilities(capabilities);
			((BaseUnityPlugin)this).Logger.LogInfo((object)("EnhancedPing 1.0.0 loaded for PEAK 2.0.a baseline. " + $"Input: {capabilities.Input}; distance: {capabilities.Distance}; " + $"dead reticle: {capabilities.DeadReticle}."));
		}

		private void Update()
		{
			Controller?.TickLifecycle();
		}

		private void OnDestroy()
		{
			Controller?.Reset("plugin destroyed");
			Harmony? harmony = _harmony;
			if (harmony != null)
			{
				harmony.UnpatchSelf();
			}
			Instance = null;
		}
	}
	internal readonly struct RuntimePingSample
	{
		public Vector3 Direction { get; }

		public Vector3 Point { get; }

		public Vector3 Normal { get; }

		public RuntimePingSample(Vector3 direction, Vector3 point, Vector3 normal)
		{
			//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_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_0009: 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_0010: Unknown result type (might be due to invalid IL or missing references)
			Direction = direction;
			Point = point;
			Normal = normal;
		}

		public SphericalPathSample ToCore()
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			return new SphericalPathSample(ToCore(Direction), ToCore(Point), ToCore(Normal));
		}

		public static RuntimePingSample FromCore(SphericalPathSample sample)
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			return new RuntimePingSample(ToUnity(sample.Direction), ToUnity(sample.Point), ToUnity(sample.Normal));
		}

		private static Vector3 ToCore(Vector3 value)
		{
			//IL_0000: 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_000c: Unknown result type (might be due to invalid IL or missing references)
			return new Vector3(value.x, value.y, value.z);
		}

		private static Vector3 ToUnity(Vector3 value)
		{
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			return new Vector3(value.X, value.Y, value.Z);
		}
	}
	internal static class BuildInfo
	{
		internal const string Version = "1.0.0";
	}
}
namespace EnhancedPing.Core
{
	public static class SequenceTiming
	{
		public static float EffectivePointDuration(int pointCount, float preferredPointDurationSeconds, float maximumSequenceDurationSeconds)
		{
			if (pointCount <= 0)
			{
				throw new ArgumentOutOfRangeException("pointCount");
			}
			if (!IsFinite(preferredPointDurationSeconds) || preferredPointDurationSeconds <= 0f)
			{
				throw new ArgumentOutOfRangeException("preferredPointDurationSeconds");
			}
			if (!IsFinite(maximumSequenceDurationSeconds) || maximumSequenceDurationSeconds <= 0f)
			{
				throw new ArgumentOutOfRangeException("maximumSequenceDurationSeconds");
			}
			return MathF.Min(preferredPointDurationSeconds, maximumSequenceDurationSeconds / (float)pointCount);
		}

		private static bool IsFinite(float value)
		{
			if (!float.IsNaN(value))
			{
				return !float.IsInfinity(value);
			}
			return false;
		}
	}
	public readonly struct SphericalPathSample
	{
		public Vector3 Direction { get; }

		public Vector3 Point { get; }

		public Vector3 Normal { get; }

		public SphericalPathSample(Vector3 direction, Vector3 point, Vector3 normal)
		{
			Direction = direction;
			Point = point;
			Normal = normal;
		}
	}
	public static class SphericalPathSelector
	{
		private const float DirectionEpsilonSquared = 1E-10f;

		private const float DuplicateAngleDegrees = 0.0001f;

		private const float RadToDeg = 180f / MathF.PI;

		public static float AngleDegrees(Vector3 left, Vector3 right)
		{
			if (!TryNormalize(left, out var normalized) || !TryNormalize(right, out var normalized2))
			{
				return float.NaN;
			}
			return MathF.Acos(MathF.Max(-1f, MathF.Min(1f, Vector3.Dot(normalized, normalized2)))) * (180f / MathF.PI);
		}

		public static IReadOnlyList<SphericalPathSample> Select(IReadOnlyList<SphericalPathSample> samples, int maximumPoints)
		{
			float totalAngleDegrees;
			return Select(samples, maximumPoints, out totalAngleDegrees);
		}

		public static IReadOnlyList<SphericalPathSample> Select(IReadOnlyList<SphericalPathSample> samples, int maximumPoints, out float totalAngleDegrees)
		{
			if (samples == null)
			{
				throw new ArgumentNullException("samples");
			}
			if (maximumPoints < 2)
			{
				throw new ArgumentOutOfRangeException("maximumPoints");
			}
			List<SphericalPathSample> list = Sanitize(samples);
			float[] array = BuildCumulativeAngles(list);
			totalAngleDegrees = ((array.Length == 0) ? 0f : array[^1]);
			if (list.Count <= maximumPoints)
			{
				return list;
			}
			if (totalAngleDegrees <= 0.0001f)
			{
				return new SphericalPathSample[1] { list[0] };
			}
			int num = Math.Min(list.Count, maximumPoints);
			List<SphericalPathSample> list2 = new List<SphericalPathSample>(num) { list[0] };
			int num2 = 0;
			for (int i = 1; i < num - 1; i++)
			{
				float num3 = totalAngleDegrees * (float)i / (float)(num - 1);
				int num4 = num2 + 1;
				int num5 = list.Count - (num - i);
				int num6 = num4;
				float num7 = MathF.Abs(array[num6] - num3);
				for (int j = num4 + 1; j <= num5; j++)
				{
					float num8 = MathF.Abs(array[j] - num3);
					if (num8 < num7)
					{
						num7 = num8;
						num6 = j;
					}
				}
				list2.Add(list[num6]);
				num2 = num6;
			}
			list2.Add(list[list.Count - 1]);
			return list2;
		}

		private static float[] BuildCumulativeAngles(IReadOnlyList<SphericalPathSample> samples)
		{
			float[] array = new float[samples.Count];
			for (int i = 1; i < samples.Count; i++)
			{
				float num = AngleDegrees(samples[i - 1].Direction, samples[i].Direction);
				array[i] = array[i - 1] + (IsFinite(num) ? num : 0f);
			}
			return array;
		}

		private static List<SphericalPathSample> Sanitize(IReadOnlyList<SphericalPathSample> samples)
		{
			List<SphericalPathSample> list = new List<SphericalPathSample>(samples.Count);
			foreach (SphericalPathSample sample in samples)
			{
				if (TryNormalize(sample.Direction, out var normalized) && IsFinite(sample.Point) && IsFinite(sample.Normal))
				{
					Vector3 normalized2;
					Vector3 normal = (TryNormalize(sample.Normal, out normalized2) ? normalized2 : Vector3.UnitY);
					SphericalPathSample item = new SphericalPathSample(normalized, sample.Point, normal);
					if (list.Count <= 0 || !(AngleDegrees(list[list.Count - 1].Direction, normalized) <= 0.0001f))
					{
						list.Add(item);
					}
				}
			}
			return list;
		}

		private static bool TryNormalize(Vector3 value, out Vector3 normalized)
		{
			float num = value.LengthSquared();
			if (!IsFinite(num) || num <= 1E-10f)
			{
				normalized = Vector3.Zero;
				return false;
			}
			normalized = value / MathF.Sqrt(num);
			return IsFinite(normalized);
		}

		private static bool IsFinite(Vector3 value)
		{
			if (IsFinite(value.X) && IsFinite(value.Y))
			{
				return IsFinite(value.Z);
			}
			return false;
		}

		private static bool IsFinite(float value)
		{
			if (!float.IsNaN(value))
			{
				return !float.IsInfinity(value);
			}
			return false;
		}
	}
}