Decompiled source of Speedometer v1.2.2

BepInEx/plugins/Speedometer.dll

Decompiled a month ago
using System;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using Pigeon.Movement;
using Sparroh.UI;
using TMPro;
using UnityEngine;

[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("Sparroh")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.2.2.0")]
[assembly: AssemblyInformationalVersion("1.2.2")]
[assembly: AssemblyProduct("Speedometer")]
[assembly: AssemblyTitle("Speedometer")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.2.2.0")]
[module: UnverifiableCode]
[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;
		}
	}
}
public static class ConfigManager
{
	private const float DebounceSeconds = 0.25f;

	private static ConfigFile config;

	private static ManualLogSource logger;

	private static FileSystemWatcher configWatcher;

	private static volatile bool pendingRefresh;

	private static volatile bool reloadPending;

	private static float lastReloadTime;

	public static ConfigEntry<bool> EnableSpeedometerHUD { get; private set; }

	public static HudAnchors Anchors { get; private set; }

	public static ConfigColor ValueColor { get; private set; }

	public static void Initialize(ConfigFile configFile, ManualLogSource log)
	{
		//IL_005d: Unknown result type (might be due to invalid IL or missing references)
		config = configFile;
		logger = log;
		EnableSpeedometerHUD = config.Bind<bool>("General", "Enable Speedometer", true, "Enables the speedometer HUD display.");
		Anchors = HudAnchors.Bind(config, "Speedometer", 0.06418981f, 0.2298982f, "HUD Positioning");
		ValueColor = ConfigColor.Bind(config, "Colors", "Speed Color", UIColors.Sky, "Rich-text value color for speed (hex RRGGBB or #RRGGBB).");
		EnableSpeedometerHUD.SettingChanged += OnSettingChanged;
		try
		{
			SetupFileWatcher();
		}
		catch (Exception ex)
		{
			logger.LogError((object)("Error setting up config file watcher: " + ex.Message));
		}
	}

	public static void Tick()
	{
		if (!reloadPending || Time.unscaledTime - lastReloadTime < 0.25f)
		{
			return;
		}
		reloadPending = false;
		lastReloadTime = Time.unscaledTime;
		try
		{
			config.Reload();
			pendingRefresh = true;
			logger.LogInfo((object)"Config reloaded from disk.");
		}
		catch (Exception ex)
		{
			logger.LogError((object)("Error reloading config: " + ex.Message));
		}
	}

	public static bool ConsumePendingRefresh()
	{
		if (!pendingRefresh)
		{
			return false;
		}
		pendingRefresh = false;
		return true;
	}

	public static void Dispose()
	{
		if (EnableSpeedometerHUD != null)
		{
			EnableSpeedometerHUD.SettingChanged -= OnSettingChanged;
		}
		if (configWatcher != null)
		{
			configWatcher.EnableRaisingEvents = false;
			configWatcher.Changed -= OnConfigFileChanged;
			configWatcher.Created -= OnConfigFileChanged;
			configWatcher.Renamed -= OnConfigFileChanged;
			configWatcher.Dispose();
			configWatcher = null;
		}
	}

	private static void SetupFileWatcher()
	{
		configWatcher = new FileSystemWatcher(Paths.ConfigPath, "sparroh.speedometer.cfg");
		configWatcher.NotifyFilter = NotifyFilters.FileName | NotifyFilters.Size | NotifyFilters.LastWrite;
		configWatcher.Changed += OnConfigFileChanged;
		configWatcher.Created += OnConfigFileChanged;
		configWatcher.Renamed += OnConfigFileChanged;
		configWatcher.EnableRaisingEvents = true;
	}

	private static void OnConfigFileChanged(object sender, FileSystemEventArgs e)
	{
		reloadPending = true;
	}

	private static void OnSettingChanged(object sender, EventArgs e)
	{
		pendingRefresh = true;
	}
}
public sealed class PlayerSpeedReader
{
	private readonly FieldInfo currentMoveSpeedField;

	private readonly FieldInfo moveVelocityField;

	private readonly FieldInfo rbField;

	private readonly PropertyInfo rbProp;

	private readonly FieldInfo vkField;

	private readonly PropertyInfo vkProp;

	public PlayerSpeedReader()
	{
		try
		{
			currentMoveSpeedField = typeof(Player).GetField("currentMoveSpeed", BindingFlags.Instance | BindingFlags.NonPublic);
			vkField = typeof(Player).GetField("velocity", BindingFlags.Instance | BindingFlags.NonPublic) ?? typeof(Player).GetField("velocity", BindingFlags.Instance | BindingFlags.Public);
			if (vkField == null)
			{
				vkProp = typeof(Player).GetProperty("velocity", BindingFlags.Instance | BindingFlags.Public);
			}
			if (vkField == null && vkProp == null)
			{
				rbField = typeof(Player).GetField("rb", BindingFlags.Instance | BindingFlags.NonPublic) ?? typeof(Player).GetField("rb", BindingFlags.Instance | BindingFlags.Public);
			}
			if (rbField == null && vkField == null && vkProp == null)
			{
				rbProp = typeof(Player).GetProperty("rb", BindingFlags.Instance | BindingFlags.Public);
			}
			if (rbField == null && rbProp == null && vkField == null && vkProp == null)
			{
				moveVelocityField = typeof(Player).GetField("moveVelocity", BindingFlags.Instance | BindingFlags.NonPublic) ?? typeof(Player).GetField("moveVelocity", BindingFlags.Instance | BindingFlags.Public);
			}
		}
		catch (Exception ex)
		{
			ManualLogSource logger = SpeedometerPlugin.Logger;
			if (logger != null)
			{
				logger.LogError((object)("Failed to initialize PlayerSpeedReader reflection: " + ex.Message));
			}
		}
	}

	public float Read(Player player)
	{
		//IL_0058: 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_0095: Unknown result type (might be due to invalid IL or missing references)
		//IL_009a: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ec: 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_0124: Unknown result type (might be due to invalid IL or missing references)
		//IL_0129: Unknown result type (might be due to invalid IL or missing references)
		//IL_019b: Unknown result type (might be due to invalid IL or missing references)
		//IL_01a0: Unknown result type (might be due to invalid IL or missing references)
		if ((Object)(object)player == (Object)null)
		{
			return 0f;
		}
		float num = 0f;
		if (vkField != null || vkProp != null)
		{
			if (vkField != null)
			{
				if (vkField.GetValue(player) is Vector3 val)
				{
					num = ((Vector3)(ref val)).magnitude;
				}
			}
			else if (vkProp != null && vkProp.GetValue(player) is Vector3 val2)
			{
				num = ((Vector3)(ref val2)).magnitude;
			}
		}
		else if (rbField != null || rbProp != null)
		{
			Vector3 velocity;
			if (rbField != null)
			{
				object? value = rbField.GetValue(player);
				Rigidbody val3 = (Rigidbody)((value is Rigidbody) ? value : null);
				if (val3 != null)
				{
					velocity = val3.velocity;
					num = ((Vector3)(ref velocity)).magnitude;
				}
			}
			else if (rbProp != null)
			{
				object? value2 = rbProp.GetValue(player);
				Rigidbody val4 = (Rigidbody)((value2 is Rigidbody) ? value2 : null);
				if (val4 != null)
				{
					velocity = val4.velocity;
					num = ((Vector3)(ref velocity)).magnitude;
				}
			}
		}
		if (num == 0f && currentMoveSpeedField != null && currentMoveSpeedField.GetValue(player) is float num2)
		{
			num = num2;
		}
		if (num == 0f && moveVelocityField != null && moveVelocityField.GetValue(player) is Vector3 val5)
		{
			num = ((Vector3)(ref val5)).magnitude;
		}
		return num;
	}
}
[BepInPlugin("sparroh.speedometer", "Speedometer", "1.2.2")]
[BepInDependency(/*Could not decode attribute arguments.*/)]
[MycoMod(/*Could not decode attribute arguments.*/)]
public class SpeedometerPlugin : BaseUnityPlugin
{
	public const string PluginGUID = "sparroh.speedometer";

	public const string PluginName = "Speedometer";

	public const string PluginVersion = "1.2.2";

	internal static ManualLogSource Logger;

	private Harmony harmony;

	private SpeedometerMod speedometer;

	private void Awake()
	{
		//IL_0044: Unknown result type (might be due to invalid IL or missing references)
		//IL_004e: Expected O, but got Unknown
		Logger = ((BaseUnityPlugin)this).Logger;
		try
		{
			ConfigManager.Initialize(((BaseUnityPlugin)this).Config, Logger);
		}
		catch (Exception ex)
		{
			Logger.LogError((object)("Failed to initialize config: " + ex.Message));
			return;
		}
		try
		{
			harmony = new Harmony("sparroh.speedometer");
		}
		catch (Exception ex2)
		{
			Logger.LogError((object)("Failed to create Harmony instance: " + ex2.Message));
			return;
		}
		try
		{
			speedometer = new SpeedometerMod();
		}
		catch (Exception ex3)
		{
			Logger.LogError((object)("Failed to initialize Speedometer: " + ex3.Message));
		}
		try
		{
			harmony.PatchAll();
		}
		catch (Exception ex4)
		{
			Logger.LogError((object)("Failed to apply Harmony patches: " + ex4.Message));
		}
		Logger.LogInfo((object)"Speedometer loaded successfully.");
	}

	private void Update()
	{
		try
		{
			ConfigManager.Tick();
			if (ConfigManager.ConsumePendingRefresh() && speedometer != null)
			{
				speedometer.OnConfigChanged();
			}
			if (speedometer != null)
			{
				speedometer.Update();
			}
		}
		catch (Exception ex)
		{
			Logger.LogError((object)("Error in Speedometer.Update(): " + ex.Message));
		}
	}

	private void OnDestroy()
	{
		try
		{
			if (speedometer != null)
			{
				speedometer.OnDestroy();
			}
		}
		catch (Exception ex)
		{
			Logger.LogError((object)("Error in Speedometer.OnDestroy(): " + ex.Message));
		}
		try
		{
			ConfigManager.Dispose();
		}
		catch (Exception ex2)
		{
			Logger.LogError((object)("Error disposing config: " + ex2.Message));
		}
		try
		{
			if (harmony != null)
			{
				harmony.UnpatchSelf();
			}
		}
		catch (Exception ex3)
		{
			Logger.LogError((object)("Error unpatching Harmony: " + ex3.Message));
		}
	}
}
public class SpeedometerMod
{
	private readonly PlayerSpeedReader speedReader = new PlayerSpeedReader();

	private HudHandle hud;

	public static SpeedometerMod Instance { get; private set; }

	public bool IsActive
	{
		get
		{
			if (HudHandle.IsValid(hud))
			{
				return hud.IsActive;
			}
			return false;
		}
	}

	public Vector2 GetSize
	{
		get
		{
			//IL_0019: 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)
			if (!HudHandle.IsValid(hud))
			{
				return Vector2.zero;
			}
			return hud.Size;
		}
	}

	public SpeedometerMod()
	{
		Instance = this;
	}

	public void OnConfigChanged()
	{
		if (!ConfigManager.EnableSpeedometerHUD.Value && HudHandle.IsValid(hud))
		{
			DestroyHud();
		}
		UpdateHudVisibility();
	}

	public void UpdateHudVisibility()
	{
		if (HudHandle.IsValid(hud))
		{
			hud.SetActive(ConfigManager.EnableSpeedometerHUD.Value);
		}
	}

	private void CreateSpeedometerHUD()
	{
		//IL_005e: Unknown result type (might be due to invalid IL or missing references)
		if (hud != null && !hud.IsAlive)
		{
			hud = null;
		}
		if (!HudHandle.IsValid(hud))
		{
			hud = HudBuilder.Create("SpeedometerHUD").ParentToReticle(true).Anchor(ConfigManager.Anchors.XValue, ConfigManager.Anchors.YValue)
				.Pivot(new Vector2(0f, 0.5f))
				.Size(300f, 25f, true)
				.AddText("SpeedText", -1f, (TextAlignmentOptions)513)
				.Build();
			if (HudHandle.IsValid(hud))
			{
				hud.EnableReposition("sparroh.speedometer", "Speedometer", ConfigManager.Anchors);
				UpdateHudVisibility();
			}
		}
	}

	private void DestroyHud()
	{
		if (hud != null)
		{
			if (hud.IsAlive)
			{
				hud.Destroy();
			}
			hud = null;
		}
	}

	public void Update()
	{
		//IL_008d: Unknown result type (might be due to invalid IL or missing references)
		if (!ConfigManager.EnableSpeedometerHUD.Value)
		{
			return;
		}
		if (!HudHandle.IsValid(hud))
		{
			CreateSpeedometerHUD();
			return;
		}
		if (hud.Primary == null || (Object)(object)Player.LocalPlayer == (Object)null)
		{
			if (hud.Primary != null)
			{
				hud.Primary.Text = "No Player";
			}
			return;
		}
		float num = speedReader.Read(Player.LocalPlayer);
		if (num > 0f)
		{
			hud.Primary.SetRich("Speed", num, ConfigManager.ValueColor.Value, "m/s", "F1");
		}
		else
		{
			hud.Primary.Text = "No Speed Detected";
		}
	}

	public void OnDestroy()
	{
		DestroyHud();
	}
}
namespace Speedometer
{
	public static class MyPluginInfo
	{
		public const string PLUGIN_GUID = "Speedometer";

		public const string PLUGIN_NAME = "Speedometer";

		public const string PLUGIN_VERSION = "1.2.2";
	}
}
namespace System.Runtime.CompilerServices
{
	[AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)]
	internal sealed class IgnoresAccessChecksToAttribute : Attribute
	{
		public IgnoresAccessChecksToAttribute(string assemblyName)
		{
		}
	}
}