Decompiled source of Speedometer v1.1.2

plugins/Speedometer.dll

Decompiled 2 weeks ago
using System;
using System.Collections.Generic;
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 UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("Speedometer")]
[assembly: AssemblyConfiguration("Debug")]
[assembly: AssemblyDescription("Adds a speedometer to the HUD while driving")]
[assembly: AssemblyFileVersion("1.1.2.0")]
[assembly: AssemblyInformationalVersion("1.1.2+e5e5718e0d4ae6ee6fcf6d42d06b740971850bf3")]
[assembly: AssemblyProduct("Speedometer")]
[assembly: AssemblyTitle("Speedometer")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.1.2.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.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 Speedometer
{
	[BepInPlugin("Speedometer", "Speedometer", "1.1.2")]
	public class Plugin : BaseUnityPlugin
	{
		internal enum Align
		{
			Start,
			Center,
			End
		}

		internal enum SpeedoType
		{
			Analog,
			Digital
		}

		internal struct DigitalConfig
		{
			public ConfigEntry<string> format;

			public ConfigEntry<Align> textAlign;
		}

		internal struct AnalogConfig
		{
			public ConfigEntry<string> background;

			public ConfigEntry<float> maxSpeed;

			public ConfigEntry<float> maxPointX;

			public ConfigEntry<float> maxPointY;

			public ConfigEntry<float> zeroPointX;

			public ConfigEntry<float> zeroPointY;

			public ConfigEntry<float> needleX;

			public ConfigEntry<float> needleY;

			public ConfigEntry<float> needleWidth;

			public ConfigEntry<float> lengthFactor;

			public ConfigEntry<float> backLength;
		}

		internal struct SpeedoConfig
		{
			public ConfigEntry<int> x;

			public ConfigEntry<int> y;

			public ConfigEntry<Align> alignX;

			public ConfigEntry<Align> alignY;

			public ConfigEntry<float> factor;

			public ConfigEntry<SpeedoType> type;

			public DigitalConfig digital;

			public AnalogConfig analog;
		}

		internal class SpeedoGauge
		{
			private Texture2D atlas;

			private Texture2D needleOverlay;

			private Texture2D clearTexture;

			private Vector2Int dimensions;

			private Vector2 center;

			private Vector2 needleStart;

			private Vector2 needleEnd;

			private float needleWidth = 1.3f;

			private float length;

			private float back;

			public Vector2Int Dimensions => dimensions;

			private static void SetPixel(Texture2D t, int x, int y, Color c)
			{
				//IL_000a: Unknown result type (might be due to invalid IL or missing references)
				t.SetPixel(x, ((Texture)t).height - y, c);
			}

			private static Color GetPixel(Texture2D t, int x, int y)
			{
				//IL_000a: Unknown result type (might be due to invalid IL or missing references)
				return t.GetPixel(x, ((Texture)t).height - y);
			}

			public SpeedoGauge(string atlasImage, Vector2 needleStart, Vector2 needleEnd, Vector2 center, float width, float length, float back)
			{
				//IL_0036: 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)
				//IL_0057: Unknown result type (might be due to invalid IL or missing references)
				//IL_0061: Expected O, but got Unknown
				//IL_00aa: 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_00ad: Unknown result type (might be due to invalid IL or missing references)
				//IL_00b2: Unknown result type (might be due to invalid IL or missing references)
				//IL_00b4: Unknown result type (might be due to invalid IL or missing references)
				//IL_00b5: Unknown result type (might be due to invalid IL or missing references)
				//IL_00b7: Unknown result type (might be due to invalid IL or missing references)
				//IL_00bc: Unknown result type (might be due to invalid IL or missing references)
				//IL_00bf: Unknown result type (might be due to invalid IL or missing references)
				//IL_00c0: 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_00c7: Unknown result type (might be due to invalid IL or missing references)
				//IL_00cd: Unknown result type (might be due to invalid IL or missing references)
				//IL_00cf: Unknown result type (might be due to invalid IL or missing references)
				//IL_0103: Unknown result type (might be due to invalid IL or missing references)
				//IL_010d: Expected O, but got Unknown
				//IL_0072: Unknown result type (might be due to invalid IL or missing references)
				atlas = LoadImage(atlasImage);
				dimensions = new Vector2Int(((Texture)atlas).width, ((Texture)atlas).height);
				clearTexture = new Texture2D(((Vector2Int)(ref dimensions)).x, ((Vector2Int)(ref dimensions)).y);
				for (int i = 0; i < ((Vector2Int)(ref dimensions)).x; i++)
				{
					for (int j = 0; j < ((Vector2Int)(ref dimensions)).y; j++)
					{
						SetPixel(clearTexture, i, j, Color.clear);
					}
				}
				needleStart -= center;
				needleEnd -= center;
				this.needleEnd = needleEnd;
				this.needleStart = needleStart;
				this.center = center;
				needleWidth = width;
				this.length = length;
				this.back = back;
				needleOverlay = new Texture2D(((Vector2Int)(ref dimensions)).x, ((Vector2Int)(ref dimensions)).y);
			}

			public void Draw(MiniRenderer R, Vector2Int position, float speedFactor)
			{
				//IL_005a: 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_0066: Unknown result type (might be due to invalid IL or missing references)
				//IL_006b: Unknown result type (might be due to invalid IL or missing references)
				//IL_006d: Unknown result type (might be due to invalid IL or missing references)
				//IL_0072: 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_007e: Unknown result type (might be due to invalid IL or missing references)
				//IL_0083: Unknown result type (might be due to invalid IL or missing references)
				//IL_00a0: Unknown result type (might be due to invalid IL or missing references)
				//IL_00a7: Unknown result type (might be due to invalid IL or missing references)
				//IL_00b2: Unknown result type (might be due to invalid IL or missing references)
				//IL_00b7: Unknown result type (might be due to invalid IL or missing references)
				//IL_00bc: Unknown result type (might be due to invalid IL or missing references)
				//IL_00c1: Unknown result type (might be due to invalid IL or missing references)
				//IL_00e5: Unknown result type (might be due to invalid IL or missing references)
				R.spr((Texture)(object)atlas, 0f, 0f, (float)((Vector2Int)(ref position)).x, (float)((Vector2Int)(ref position)).y, (float)((Vector2Int)(ref dimensions)).x, (float)((Vector2Int)(ref dimensions)).y, false, (float)((Vector2Int)(ref dimensions)).x, (float)((Vector2Int)(ref dimensions)).y);
				Vector2 val = ClockwiseLerp(needleStart, needleEnd, speedFactor);
				Vector2 w = center + val * length;
				needleOverlay.CopyPixels((Texture)(object)clearTexture);
				for (int i = 0; i < ((Vector2Int)(ref dimensions)).x; i++)
				{
					for (int j = 0; j < ((Vector2Int)(ref dimensions)).y; j++)
					{
						float num = minimum_distance(center - ((Vector2)(ref val)).normalized * back, w, new Vector2((float)i, (float)j));
						if (num < needleWidth)
						{
							SetPixel(needleOverlay, i, j, Color.white);
						}
					}
				}
				needleOverlay.Apply();
				R.spr((Texture)(object)needleOverlay, 0f, 0f, (float)((Vector2Int)(ref position)).x, (float)((Vector2Int)(ref position)).y, (float)((Vector2Int)(ref dimensions)).x, (float)((Vector2Int)(ref dimensions)).y, false, (float)((Vector2Int)(ref dimensions)).x, (float)((Vector2Int)(ref dimensions)).y);
			}

			private static float minimum_distance(Vector2 v, Vector2 w, Vector2 p)
			{
				//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_0003: 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_0039: Unknown result type (might be due to invalid IL or missing references)
				//IL_003a: Unknown result type (might be due to invalid IL or missing references)
				//IL_003b: Unknown result type (might be due to invalid IL or missing references)
				//IL_0040: Unknown result type (might be due to invalid IL or missing references)
				//IL_0041: 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_0059: 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_005c: 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_0062: 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_006c: Unknown result type (might be due to invalid IL or missing references)
				//IL_006d: Unknown result type (might be due to invalid IL or missing references)
				//IL_006e: Unknown result type (might be due to invalid IL or missing references)
				//IL_0024: 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)
				Vector2 val = w - v;
				float sqrMagnitude = ((Vector2)(ref val)).sqrMagnitude;
				if ((double)sqrMagnitude == 0.0)
				{
					return Vector2.Distance(p, v);
				}
				float num = Mathf.Max(0f, Mathf.Min(1f, Vector2.Dot(p - v, w - v) / sqrMagnitude));
				Vector2 val2 = v + num * (w - v);
				return Vector2.Distance(p, val2);
			}

			private static Vector2 ClockwiseLerp(Vector2 start, Vector2 end, float t)
			{
				//IL_0001: 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_0013: 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_004b: Unknown result type (might be due to invalid IL or missing references)
				//IL_0064: Unknown result type (might be due to invalid IL or missing references)
				//IL_0069: 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)
				//IL_006b: 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)
				float num = Mathf.Atan2(start.y, start.x);
				float num2 = Mathf.Atan2(end.y, end.x);
				if (num > num2)
				{
					num -= MathF.PI * 2f;
				}
				float num3 = num + (num2 - num) * t;
				return new Vector2(Mathf.Cos(num3), Mathf.Sin(num3)) * Mathf.Lerp(((Vector2)(ref start)).magnitude, ((Vector2)(ref end)).magnitude, t);
			}
		}

		internal static ManualLogSource Logger;

		private static SpeedoGauge gauge;

		private static ConfigEntry<bool> useWheelSpeed;

		private static ConfigEntry<string> speedoConfigName;

		private static ConfigFile config;

		private static string configPath = Utility.CombinePaths(new string[2]
		{
			Paths.ConfigPath,
			"Speedometer"
		});

		private static SpeedoConfig sConfig;

		private static List<string> configs = new List<string>();

		private static void LoadConfig(string name)
		{
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: Expected O, but got Unknown
			//IL_0355: Unknown result type (might be due to invalid IL or missing references)
			//IL_037a: Unknown result type (might be due to invalid IL or missing references)
			//IL_039f: Unknown result type (might be due to invalid IL or missing references)
			ConfigFile val = new ConfigFile(Utility.CombinePaths(new string[2]
			{
				configPath,
				name + ".spdo.cfg"
			}), false);
			Logger.LogInfo((object)("Loading config " + val.ConfigFilePath));
			SpeedoConfig speedoConfig = default(SpeedoConfig);
			speedoConfig.x = val.Bind<int>("general", "x", 16, "X position of the speedometer");
			speedoConfig.y = val.Bind<int>("general", "y", -54, "Y position of the speedometer");
			speedoConfig.alignX = val.Bind<Align>("general", "alignX", Align.Center, "X alignment, Start = from left side, Center = from center, End = from right side");
			speedoConfig.alignY = val.Bind<Align>("general", "alignY", Align.End, "Y alignment, Start = from top, Center = from center, End = from bottom");
			speedoConfig.factor = val.Bind<float>("general", "factor", 3.6f, "Multiplication factor for the displayed speed, 1 = meters per second");
			speedoConfig.type = val.Bind<SpeedoType>("general", "type", SpeedoType.Digital, "Speedometer type");
			switch (speedoConfig.type.Value)
			{
			case SpeedoType.Digital:
				speedoConfig.digital = default(DigitalConfig);
				speedoConfig.digital.format = val.Bind<string>("digital", "format", "{0:f0} km/h", "Format string for the display, check C# String.Format docs for options");
				speedoConfig.digital.textAlign = val.Bind<Align>("digital", "textAlign", Align.End, "Text alignment, Start = Text starts at position, Center = Center of text is at position, End = End of text is at position");
				break;
			case SpeedoType.Analog:
				speedoConfig.analog = default(AnalogConfig);
				speedoConfig.analog.background = val.Bind<string>("analog", "background", "", "Image to use for the speedometer");
				speedoConfig.analog.maxSpeed = val.Bind<float>("analog", "maxSpeed", 36f, "Speed where the needle should be at the maxPoint");
				speedoConfig.analog.maxPointX = val.Bind<float>("analog", "maxPointX", 0f, "X coordinate where the needle ends up at max speed");
				speedoConfig.analog.maxPointY = val.Bind<float>("analog", "maxPointY", 0f, "Y coordinate where the needle ends up at max speed");
				speedoConfig.analog.zeroPointX = val.Bind<float>("analog", "zeroPointX", 0f, "X coordinate where the needle is at 0 speed");
				speedoConfig.analog.zeroPointY = val.Bind<float>("analog", "zeroPointY", 0f, "Y coordinate where the needle is at 0 speed");
				speedoConfig.analog.needleX = val.Bind<float>("analog", "needleX", 0f, "X coordinate of the needle start");
				speedoConfig.analog.needleY = val.Bind<float>("analog", "needleY", 0f, "Y coordinate of the needle start");
				speedoConfig.analog.needleWidth = val.Bind<float>("analog", "needleWidth", 1.3f, "Width of the needle in hud pixels");
				speedoConfig.analog.lengthFactor = val.Bind<float>("analog", "lengthFactor", 0.8f, "Scales the needle length by this amount, 1 reaches exactly from base to start/end position");
				speedoConfig.analog.backLength = val.Bind<float>("analog", "backLength", 4f, "How many pixels the needle should poke out the back");
				gauge = new SpeedoGauge(speedoConfig.analog.background.Value, new Vector2(speedoConfig.analog.zeroPointX.Value, speedoConfig.analog.zeroPointY.Value), new Vector2(speedoConfig.analog.maxPointX.Value, speedoConfig.analog.maxPointY.Value), new Vector2(speedoConfig.analog.needleX.Value, speedoConfig.analog.needleY.Value), speedoConfig.analog.needleWidth.Value, speedoConfig.analog.lengthFactor.Value, speedoConfig.analog.backLength.Value);
				break;
			}
			sConfig = speedoConfig;
		}

		private void Awake()
		{
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			//IL_0043: Expected O, but got Unknown
			Logger = ((BaseUnityPlugin)this).Logger;
			Harmony.CreateAndPatchAll(typeof(Plugin), (string)null);
			config = new ConfigFile(Utility.CombinePaths(new string[2]
			{
				Paths.ConfigPath,
				"Speedometer.cfg"
			}), true);
			config.SaveOnConfigSet = true;
			useWheelSpeed = config.Bind<bool>("indicator", "wheelSpeed", true, "Use front wheel rotation speed for calculating speed. Otherwise use car's linear velocity");
			speedoConfigName = config.Bind<string>("indicator", "configName", "digital-center", "Name of speedometer config to use. Configs are located in BepInEx/config/Speedometer/");
			config.SettingChanged += delegate(object _, SettingChangedEventArgs args)
			{
				if (args.ChangedSetting.Definition.Key == "configName")
				{
					LoadConfig(speedoConfigName.Value);
				}
			};
			LoadConfig(speedoConfigName.Value);
			ScanConfigs();
		}

		private static void ScanConfigs()
		{
			configs.Clear();
			foreach (string item in Directory.EnumerateFiles(configPath))
			{
				if (item.EndsWith(".spdo.cfg"))
				{
					ReadOnlySpan<char> readOnlySpan = Path.GetFileName(item).AsSpan().TrimEnd(".spdo.cfg".AsSpan());
					configs.Add(readOnlySpan.ToString());
					Logger.LogInfo((object)("Found config " + readOnlySpan));
				}
			}
		}

		private static void Reload()
		{
			ScanConfigs();
			config.Reload();
			LoadConfig(speedoConfigName.Value);
		}

		private static Texture2D LoadImage(string name)
		{
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: Expected O, but got Unknown
			byte[] array = File.ReadAllBytes(Utility.CombinePaths(new string[2] { configPath, name }));
			Texture2D val = new Texture2D(2, 2);
			ImageConversion.LoadImage(val, array);
			((Texture)val).wrapMode = (TextureWrapMode)1;
			((Texture)val).filterMode = (FilterMode)0;
			return val;
		}

		private void Update()
		{
			if (Input.GetKeyDown((KeyCode)46))
			{
				int index = (configs.IndexOf(speedoConfigName.Value) + 1) % configs.Count;
				speedoConfigName.Value = configs[index];
			}
			if (Input.GetKeyDown((KeyCode)44))
			{
				Reload();
			}
		}

		[HarmonyPatch(typeof(sHUD), "RadioDisplay")]
		[HarmonyPostfix]
		private static void ShowSpeed(sHUD __instance)
		{
			//IL_0086: Unknown result type (might be due to invalid IL or missing references)
			//IL_008b: Unknown result type (might be due to invalid IL or missing references)
			//IL_028d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0292: Unknown result type (might be due to invalid IL or missing references)
			//IL_02fa: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ff: Unknown result type (might be due to invalid IL or missing references)
			//IL_02b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_02b8: Unknown result type (might be due to invalid IL or missing references)
			//IL_033d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0320: Unknown result type (might be due to invalid IL or missing references)
			//IL_0325: Unknown result type (might be due to invalid IL or missing references)
			object? value = AccessTools.Field(typeof(sHUD), "R").GetValue(__instance);
			MiniRenderer val = (MiniRenderer)((value is MiniRenderer) ? value : null);
			sCarController val2 = Object.FindFirstObjectByType<sCarController>();
			if (val2.GuyActive)
			{
				return;
			}
			bool value2 = useWheelSpeed.Value;
			if (1 == 0)
			{
			}
			float num;
			if (value2)
			{
				num = Math.Max(Math.Abs(val2.wheels[0].viewRotationVelocity * 1.092f / 3.6f) - 1f, 0f);
			}
			else
			{
				Vector3 linearVelocity = val2.rb.linearVelocity;
				num = ((Vector3)(ref linearVelocity)).magnitude;
			}
			if (1 == 0)
			{
			}
			float num2 = num;
			num2 *= sConfig.factor.Value;
			Vector2Int position = default(Vector2Int);
			((Vector2Int)(ref position))..ctor(sConfig.x.Value, sConfig.y.Value);
			switch (sConfig.alignX.Value)
			{
			case Align.Center:
				((Vector2Int)(ref position)).x = ((Vector2Int)(ref position)).x + val.width / 2;
				break;
			case Align.End:
				((Vector2Int)(ref position)).x = ((Vector2Int)(ref position)).x + val.width;
				break;
			}
			switch (sConfig.alignY.Value)
			{
			case Align.Center:
				((Vector2Int)(ref position)).y = ((Vector2Int)(ref position)).y + val.height / 2;
				break;
			case Align.End:
				((Vector2Int)(ref position)).y = ((Vector2Int)(ref position)).y + val.height;
				break;
			}
			switch (sConfig.type.Value)
			{
			case SpeedoType.Digital:
			{
				string text;
				try
				{
					text = string.Format(sConfig.digital.format.Value, num2);
				}
				catch (FormatException ex)
				{
					text = "Invalid format specifier";
					Logger.LogError((object)ex);
				}
				int num3 = text.Length * 8;
				switch (sConfig.digital.textAlign.Value)
				{
				case Align.End:
					((Vector2Int)(ref position)).x = ((Vector2Int)(ref position)).x - num3;
					break;
				case Align.Center:
					((Vector2Int)(ref position)).x = ((Vector2Int)(ref position)).x - num3 / 2;
					break;
				}
				val.put(text, (float)((Vector2Int)(ref position)).x, (float)((Vector2Int)(ref position)).y);
				break;
			}
			case SpeedoType.Analog:
			{
				Vector2Int dimensions;
				switch (sConfig.alignX.Value)
				{
				case Align.Center:
				{
					int x2 = ((Vector2Int)(ref position)).x;
					dimensions = gauge.Dimensions;
					((Vector2Int)(ref position)).x = x2 - ((Vector2Int)(ref dimensions)).x / 2;
					break;
				}
				case Align.End:
				{
					int x = ((Vector2Int)(ref position)).x;
					dimensions = gauge.Dimensions;
					((Vector2Int)(ref position)).x = x - ((Vector2Int)(ref dimensions)).x;
					break;
				}
				}
				switch (sConfig.alignY.Value)
				{
				case Align.Center:
				{
					int y2 = ((Vector2Int)(ref position)).y;
					dimensions = gauge.Dimensions;
					((Vector2Int)(ref position)).y = y2 - ((Vector2Int)(ref dimensions)).y / 2;
					break;
				}
				case Align.End:
				{
					int y = ((Vector2Int)(ref position)).y;
					dimensions = gauge.Dimensions;
					((Vector2Int)(ref position)).y = y - ((Vector2Int)(ref dimensions)).y;
					break;
				}
				}
				gauge.Draw(val, position, num2 / sConfig.analog.maxSpeed.Value);
				break;
			}
			}
		}
	}
	public static class MyPluginInfo
	{
		public const string PLUGIN_GUID = "Speedometer";

		public const string PLUGIN_NAME = "Speedometer";

		public const string PLUGIN_VERSION = "1.1.2";
	}
}