Decompiled source of REPOSimpleTimer v1.0.1

REPOSimpleTimer.dll

Decompiled 2 days ago
using System;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using Microsoft.CodeAnalysis;
using TMPro;
using UnityEngine;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("REPOSimpleTimer")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyDescription("Shows the elapsed time since the level started on the R.E.P.O. HUD.")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("REPO Simple Timer")]
[assembly: AssemblyTitle("REPOSimpleTimer")]
[assembly: AssemblyVersion("1.0.0.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace REPOSimpleTimer
{
	internal class LevelTimer : MonoBehaviour
	{
		private static readonly Vector2 LabelSize = new Vector2(400f, 48f);

		private int currentDirectorId;

		private float elapsed;

		private bool levelStarted;

		private bool hiddenByUser;

		private TextMeshProUGUI label;

		private bool layoutDirty = true;

		private string lastText;

		private void OnEnable()
		{
			((BaseUnityPlugin)Plugin.Instance).Config.SettingChanged += OnSettingChanged;
		}

		private void OnDisable()
		{
			((BaseUnityPlugin)Plugin.Instance).Config.SettingChanged -= OnSettingChanged;
		}

		private void OnSettingChanged(object sender, EventArgs e)
		{
			layoutDirty = true;
		}

		private void Update()
		{
			TimerSettings settings = Plugin.Settings;
			Tick();
			HandleToggleKey(settings);
			if (!ShouldShow(settings))
			{
				if ((Object)(object)label != (Object)null)
				{
					((Behaviour)label).enabled = false;
				}
			}
			else if (EnsureLabel())
			{
				if (layoutDirty)
				{
					ApplyLayout(settings);
					layoutDirty = false;
				}
				((Behaviour)label).enabled = true;
				string text = settings.Prefix.Value + FormatElapsed(elapsed, settings.Format.Value);
				if (text != lastText)
				{
					((TMP_Text)label).text = text;
					lastText = text;
				}
			}
		}

		private void Tick()
		{
			//IL_0053: Unknown result type (might be due to invalid IL or missing references)
			//IL_0059: Invalid comparison between Unknown and I4
			GameDirector instance = GameDirector.instance;
			if ((Object)(object)instance == (Object)null)
			{
				currentDirectorId = 0;
				levelStarted = false;
				elapsed = 0f;
				return;
			}
			int instanceID = ((Object)instance).GetInstanceID();
			if (instanceID != currentDirectorId)
			{
				currentDirectorId = instanceID;
				levelStarted = false;
				elapsed = 0f;
			}
			if ((int)instance.currentState == 2)
			{
				levelStarted = true;
				elapsed += Time.deltaTime;
			}
		}

		private void HandleToggleKey(TimerSettings settings)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			KeyboardShortcut value = settings.ToggleKey.Value;
			if (((KeyboardShortcut)(ref value)).IsDown() && !((Object)(object)RunManager.instance == (Object)null) && !SemiFunc.MenuLevel() && SemiFunc.NoTextInputsActive())
			{
				hiddenByUser = !hiddenByUser;
			}
		}

		private bool ShouldShow(TimerSettings settings)
		{
			if (!settings.Enabled.Value || hiddenByUser || !levelStarted)
			{
				return false;
			}
			if ((Object)(object)RunManager.instance == (Object)null || (Object)(object)RunManager.instance.levelCurrent == (Object)null || SemiFunc.MenuLevel())
			{
				return false;
			}
			if ((Object)(object)HUD.instance != (Object)null && HUD.instance.hidden)
			{
				return false;
			}
			if (!settings.ShowOutsideLevels.Value && !SemiFunc.RunIsLevel() && !SemiFunc.RunIsArena())
			{
				return false;
			}
			return true;
		}

		private bool EnsureLabel()
		{
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			//IL_0047: Expected O, but got Unknown
			if ((Object)(object)label != (Object)null)
			{
				return true;
			}
			HUDCanvas instance = HUDCanvas.instance;
			if ((Object)(object)instance == (Object)null)
			{
				return false;
			}
			TextMeshProUGUI componentInChildren = ((Component)instance).GetComponentInChildren<TextMeshProUGUI>(true);
			GameObject val = new GameObject("REPOSimpleTimer Label", new Type[1] { typeof(RectTransform) });
			val.transform.SetParent(((Component)instance).transform, false);
			label = val.AddComponent<TextMeshProUGUI>();
			if ((Object)(object)componentInChildren != (Object)null)
			{
				((TMP_Text)label).font = ((TMP_Text)componentInChildren).font;
				((TMP_Text)label).fontSharedMaterial = ((TMP_Text)componentInChildren).fontSharedMaterial;
			}
			((TMP_Text)label).enableWordWrapping = false;
			((TMP_Text)label).overflowMode = (TextOverflowModes)0;
			((Graphic)label).raycastTarget = false;
			((TMP_Text)label).richText = true;
			layoutDirty = true;
			lastText = null;
			return true;
		}

		private void ApplyLayout(TimerSettings settings)
		{
			//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_001d: 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_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: 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_0084: Unknown result type (might be due to invalid IL or missing references)
			//IL_009f: Unknown result type (might be due to invalid IL or missing references)
			Vector2 val = AnchorToVector(settings.Anchor.Value);
			RectTransform rectTransform = ((TMP_Text)label).rectTransform;
			rectTransform.anchorMin = val;
			rectTransform.anchorMax = val;
			rectTransform.pivot = val;
			rectTransform.sizeDelta = LabelSize;
			((Transform)rectTransform).localScale = Vector3.one;
			rectTransform.anchoredPosition = new Vector2(settings.OffsetX.Value, settings.OffsetY.Value);
			((TMP_Text)label).fontSize = settings.FontSize.Value;
			((Graphic)label).color = settings.ResolveColor();
			((TMP_Text)label).alignment = AnchorToAlignment(settings.Anchor.Value);
		}

		private static Vector2 AnchorToVector(ScreenAnchor anchor)
		{
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_0045: Unknown result type (might be due to invalid IL or missing references)
			//IL_0055: Unknown result type (might be due to invalid IL or missing references)
			//IL_0065: Unknown result type (might be due to invalid IL or missing references)
			//IL_0075: Unknown result type (might be due to invalid IL or missing references)
			//IL_0085: 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_00a5: 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)
			return (Vector2)(anchor switch
			{
				ScreenAnchor.TopLeft => new Vector2(0f, 1f), 
				ScreenAnchor.TopCenter => new Vector2(0.5f, 1f), 
				ScreenAnchor.TopRight => new Vector2(1f, 1f), 
				ScreenAnchor.MiddleLeft => new Vector2(0f, 0.5f), 
				ScreenAnchor.MiddleRight => new Vector2(1f, 0.5f), 
				ScreenAnchor.BottomLeft => new Vector2(0f, 0f), 
				ScreenAnchor.BottomCenter => new Vector2(0.5f, 0f), 
				ScreenAnchor.BottomRight => new Vector2(1f, 0f), 
				_ => new Vector2(0.5f, 1f), 
			});
		}

		private static TextAlignmentOptions AnchorToAlignment(ScreenAnchor anchor)
		{
			switch (anchor)
			{
			case ScreenAnchor.TopLeft:
			case ScreenAnchor.MiddleLeft:
			case ScreenAnchor.BottomLeft:
				return (TextAlignmentOptions)513;
			case ScreenAnchor.TopRight:
			case ScreenAnchor.MiddleRight:
			case ScreenAnchor.BottomRight:
				return (TextAlignmentOptions)516;
			default:
				return (TextAlignmentOptions)514;
			}
		}

		private static string FormatElapsed(float seconds, TimeFormat format)
		{
			if (seconds < 0f)
			{
				seconds = 0f;
			}
			int num = (int)seconds;
			int num2 = num / 3600;
			int num3 = num / 60;
			int num4 = num % 60;
			switch (format)
			{
			case TimeFormat.MinutesSecondsCentis:
			{
				int num5 = (int)((seconds - (float)num) * 100f);
				return $"{num3:00}:{num4:00}.{num5:00}";
			}
			case TimeFormat.HoursMinutesSeconds:
				return $"{num2:00}:{num3 % 60:00}:{num4:00}";
			default:
				return $"{num3:00}:{num4:00}";
			}
		}
	}
	[BepInPlugin("harukazelab.REPOSimpleTimer", "REPO Simple Timer", "1.0.0")]
	public class Plugin : BaseUnityPlugin
	{
		internal static Plugin Instance { get; private set; }

		internal static ManualLogSource Log { get; private set; }

		internal static TimerSettings Settings { get; private set; }

		private void Awake()
		{
			Instance = this;
			Log = ((BaseUnityPlugin)this).Logger;
			Settings = new TimerSettings(((BaseUnityPlugin)this).Config);
			((Component)this).gameObject.AddComponent<LevelTimer>();
			Log.LogInfo((object)"REPO Simple Timer 1.0.0 loaded.");
		}
	}
	internal static class PluginInfo
	{
		public const string Guid = "harukazelab.REPOSimpleTimer";

		public const string Name = "REPO Simple Timer";

		public const string Version = "1.0.0";
	}
	internal enum TimeFormat
	{
		MinutesSeconds,
		MinutesSecondsCentis,
		HoursMinutesSeconds
	}
	internal enum ScreenAnchor
	{
		TopLeft,
		TopCenter,
		TopRight,
		MiddleLeft,
		MiddleRight,
		BottomLeft,
		BottomCenter,
		BottomRight
	}
	internal class TimerSettings
	{
		public readonly ConfigEntry<bool> Enabled;

		public readonly ConfigEntry<bool> ShowOutsideLevels;

		public readonly ConfigEntry<KeyboardShortcut> ToggleKey;

		public readonly ConfigEntry<TimeFormat> Format;

		public readonly ConfigEntry<string> Prefix;

		public readonly ConfigEntry<ScreenAnchor> Anchor;

		public readonly ConfigEntry<float> OffsetX;

		public readonly ConfigEntry<float> OffsetY;

		public readonly ConfigEntry<float> FontSize;

		public readonly ConfigEntry<string> ColorHex;

		public TimerSettings(ConfigFile config)
		{
			//IL_0054: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ea: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f4: Expected O, but got Unknown
			//IL_0123: Unknown result type (might be due to invalid IL or missing references)
			//IL_012d: Expected O, but got Unknown
			//IL_015c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0166: Expected O, but got Unknown
			Enabled = config.Bind<bool>("1. General", "Enabled", true, "Show the level timer on the HUD.");
			ShowOutsideLevels = config.Bind<bool>("1. General", "ShowOutsideLevels", false, "Also show the timer in the truck, the shop and the tutorial. When false the timer only appears in run levels and the arena.");
			ToggleKey = config.Bind<KeyboardShortcut>("1. General", "ToggleKey", new KeyboardShortcut((KeyCode)289, Array.Empty<KeyCode>()), "Key that toggles the timer on and off while playing. The timer keeps counting while hidden.");
			Format = config.Bind<TimeFormat>("2. Text", "Format", TimeFormat.MinutesSeconds, "How the elapsed time is written out.");
			Prefix = config.Bind<string>("2. Text", "Prefix", "", "Text placed in front of the time, e.g. \"TIME \".");
			Anchor = config.Bind<ScreenAnchor>("3. Layout", "Anchor", ScreenAnchor.TopCenter, "Corner or edge of the screen the timer is pinned to.");
			OffsetX = config.Bind<float>("3. Layout", "OffsetX", 0f, new ConfigDescription("Horizontal offset from the anchor, in canvas units. Positive moves right.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(-960f, 960f), Array.Empty<object>()));
			OffsetY = config.Bind<float>("3. Layout", "OffsetY", -30f, new ConfigDescription("Vertical offset from the anchor, in canvas units. Positive moves up.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(-540f, 540f), Array.Empty<object>()));
			FontSize = config.Bind<float>("3. Layout", "FontSize", 24f, new ConfigDescription("Font size of the timer text.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(8f, 96f), Array.Empty<object>()));
			ColorHex = config.Bind<string>("3. Layout", "Color", "#FFFFFF", "Timer color as an HTML hex string, e.g. #FFFFFF or #7FFF7FCC.");
		}

		public Color ResolveColor()
		{
			//IL_0016: 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)
			Color result = default(Color);
			if (ColorUtility.TryParseHtmlString(ColorHex.Value, ref result))
			{
				return result;
			}
			return Color.white;
		}
	}
}