Decompiled source of YetAnotherClock v0.5.0

YetAnotherClock.dll

Decompiled 8 hours ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using BepInEx.Logging;
using JG224.ModCore.API;
using JG224.YetAnotherClock.Core;
using JG224.YetAnotherClock.UI;
using Microsoft.CodeAnalysis;
using UnityEngine;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[assembly: AssemblyCompany("YetAnotherClock")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("0.5.0.0")]
[assembly: AssemblyInformationalVersion("0.5.0")]
[assembly: AssemblyProduct("YetAnotherClock")]
[assembly: AssemblyTitle("YetAnotherClock")]
[assembly: AssemblyVersion("0.5.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 JG224.YetAnotherClock
{
	[BepInPlugin("jg224.YetAnotherClock", "YetAnotherClock", "0.5.0")]
	[BepInProcess("valheim.exe")]
	[BepInDependency("com.jg224.modcore", "0.5.0")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	public sealed class Plugin : BaseUnityPlugin
	{
		public const string PluginGuid = "jg224.YetAnotherClock";

		public const string PluginName = "YetAnotherClock";

		public const string PluginVersion = "0.5.0";

		public const string ModCoreGuid = "com.jg224.modcore";

		public const string GeneralTweaksGuid = "JG224.GeneralTweaks";

		public const int ProtocolVersion = 1;

		public static readonly ModuleId ModuleId = new ModuleId("yetanotherclock");

		private readonly List<IDisposable> _registrations = new List<IDisposable>();

		private bool _active;

		private bool _shutDown;

		internal static ManualLogSource Log { get; private set; }

		internal static YetAnotherClockConfig Settings { get; private set; }

		internal static ICoreServices Core { get; private set; }

		private void Awake()
		{
			//IL_00ab: Unknown result type (might be due to invalid IL or missing references)
			//IL_011a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0073: Unknown result type (might be due to invalid IL or missing references)
			Log = ((BaseUnityPlugin)this).Logger;
			Settings = YetAnotherClockConfig.Load((BaseUnityPlugin)(object)this, Paths.ConfigPath, ((BaseUnityPlugin)this).Logger);
			try
			{
				if (!ModCoreApi.IsAvailable)
				{
					throw new InvalidOperationException("ModCore did not initialize before YetAnotherClock.");
				}
				Core = ModCoreApi.Services;
				RegisterWithCore();
				if (TryGetLegacyOwner(out var version))
				{
					string text = "GeneralTweaks " + version?.ToString() + " still contains the clock; YetAnotherClock is paused to prevent duplicate overlays.";
					Core.Modules.SetState(ModuleId, (ModuleRuntimeState)3, text);
					((BaseUnityPlugin)this).Logger.LogWarning((object)(text + " Update GeneralTweaks to 3.0.0 or newer."));
				}
				else
				{
					_active = true;
					Core.Modules.SetState(ModuleId, (ModuleRuntimeState)2, "Client-local clock overlay ready.");
					Game.isModded = true;
					((BaseUnityPlugin)this).Logger.LogInfo((object)("YetAnotherClock 0.5.0 loaded; protocol " + 1 + "."));
				}
			}
			catch (Exception ex)
			{
				((BaseUnityPlugin)this).Logger.LogError((object)("YetAnotherClock failed to initialize safely: " + ex));
				if (Core != null)
				{
					Core.Modules.SetState(ModuleId, (ModuleRuntimeState)5, ex.Message);
				}
				Shutdown();
				throw;
			}
		}

		private void Update()
		{
			if (_active)
			{
				OverlayController.Tick();
			}
		}

		private void OnDestroy()
		{
			Shutdown();
		}

		private void RegisterWithCore()
		{
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			//IL_0040: Unknown result type (might be due to invalid IL or missing references)
			//IL_004a: Expected O, but got Unknown
			//IL_0059: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00db: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e5: Expected O, but got Unknown
			//IL_00fa: 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)
			SemanticVersion val = default(SemanticVersion);
			if (!SemanticVersion.TryParse("0.5.0", ref val))
			{
				throw new InvalidOperationException("YetAnotherClock has invalid release version metadata.");
			}
			_registrations.Add(Core.Modules.Register(new ModuleDescriptor(ModuleId, "jg224.YetAnotherClock", "YetAnotherClock", val, 1, (ModuleSide)1, (ModuleRequirement)1, 0uL, 1, 1)));
			foreach (IDisposable item in Settings.RegisterMetadata(Core, ModuleId))
			{
				_registrations.Add(item);
			}
			_registrations.Add(Core.Namespaces.Register(ModuleId, (NamespaceKind)8, "jg224.yetanotherclock.", 1, Array.Empty<string>()));
			_registrations.Add(Core.Ui.Reserve(new UiReservation(ModuleId, (UiSurface)6, "top-right.clock", 20, false)));
			_registrations.Add(Core.Lifecycle.Subscribe(ModuleId, (LifecycleEventKind)9, (Action<LifecycleEvent>)delegate
			{
				OverlayController.Destroy();
			}, 0));
			_registrations.Add(Core.Lifecycle.Subscribe(ModuleId, (LifecycleEventKind)3, (Action<LifecycleEvent>)delegate
			{
				OverlayController.Destroy();
			}, 0));
		}

		private static bool TryGetLegacyOwner(out Version version)
		{
			version = null;
			if (!Chainloader.PluginInfos.TryGetValue("JG224.GeneralTweaks", out var value))
			{
				return false;
			}
			version = value.Metadata.Version;
			if (version != null)
			{
				return version.CompareTo(new Version(3, 0, 0)) < 0;
			}
			return false;
		}

		private void Shutdown()
		{
			//IL_0088: Unknown result type (might be due to invalid IL or missing references)
			if (_shutDown)
			{
				return;
			}
			_shutDown = true;
			_active = false;
			OverlayController.Destroy();
			for (int num = _registrations.Count - 1; num >= 0; num--)
			{
				try
				{
					_registrations[num].Dispose();
				}
				catch (Exception ex)
				{
					ManualLogSource logger = ((BaseUnityPlugin)this).Logger;
					if (logger != null)
					{
						logger.LogWarning((object)("Registration cleanup failed: " + ex.Message));
					}
				}
			}
			_registrations.Clear();
			if (Core != null)
			{
				Core.Metrics.RemoveOwner(ModuleId);
			}
			Core = null;
			Settings = null;
			Log = null;
		}
	}
	internal sealed class YetAnotherClockConfig
	{
		private readonly ConfigFile _file;

		private readonly List<Tuple<ConfigEntryBase, ConfigScope>> _entries = new List<Tuple<ConfigEntryBase, ConfigScope>>();

		internal ConfigEntry<bool> Enabled { get; }

		internal ConfigEntry<bool> ShowDay { get; }

		internal ConfigEntry<bool> TwelveHour { get; }

		internal ConfigEntry<bool> ShowWhenHudHidden { get; }

		internal ConfigEntry<bool> RequireMinimap { get; }

		internal ConfigEntry<float> Scale { get; }

		internal ConfigEntry<bool> AnchorToMinimap { get; }

		internal ConfigEntry<float> OffsetX { get; }

		internal ConfigEntry<float> OffsetY { get; }

		internal ConfigEntry<string> Color { get; }

		internal ConfigEntry<float> Opacity { get; }

		internal ConfigEntry<bool> DebugLogging { get; }

		private YetAnotherClockConfig(ConfigFile file)
		{
			_file = file;
			Enabled = Local("Clock", "Enabled", value: true, "Show the in-game 24-hour clock above the minimap.");
			ShowDay = Local("Clock", "ShowDay", value: true, "Include the current day before the time.");
			TwelveHour = Local("Clock", "TwelveHour", value: false, "Use 12-hour time with AM/PM instead of 24-hour time.");
			ShowWhenHudHidden = Local("Clock", "ShowWhenHudHidden", value: false, "Keep the clock visible when the HUD is hidden.");
			RequireMinimap = Local("Clock", "RequireMinimap", value: false, "Show the clock only while the small minimap is visible.");
			Scale = LocalRange("Clock", "Scale", 1f, 0.5f, 2f, "Clock display scale.");
			AnchorToMinimap = Local("Clock", "AnchorToMinimap", value: true, "Center the clock above the small minimap at any resolution, ignoring and disabling manual offsets. Disable to restore your saved position from the screen's top-right edge.");
			OffsetX = ManualOffset("OffsetX", "Horizontal offset in screen pixels from the screen's top-right edge. Positive moves right. Ignored and greyed out while AnchorToMinimap is enabled; the saved value is kept.");
			OffsetY = ManualOffset("OffsetY", "Vertical offset in screen pixels from the screen's top-right edge. Positive moves up. Ignored and greyed out while AnchorToMinimap is enabled; the saved value is kept.");
			Color = Local("Clock", "Color", "#F2E6C9", "Clock HTML color, for example #F2E6C9.");
			Opacity = LocalRange("Clock", "Opacity", 0.95f, 0f, 1f, "Clock opacity.");
			DebugLogging = Developer("Diagnostics", "DebugLogging", value: false, "Enable verbose clock diagnostics.");
		}

		internal static YetAnotherClockConfig Load(BaseUnityPlugin plugin, string configDirectory, ManualLogSource log)
		{
			//IL_00c2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cc: Expected O, but got Unknown
			//IL_0075: Unknown result type (might be due to invalid IL or missing references)
			//IL_007a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0081: Unknown result type (might be due to invalid IL or missing references)
			if (!Directory.Exists(configDirectory))
			{
				Directory.CreateDirectory(configDirectory);
			}
			string text = LegacyClockConfigRules.FindImportSource(Directory.GetFiles(configDirectory, "*.cfg", SearchOption.TopDirectoryOnly));
			string text2 = Path.Combine(configDirectory, "jg224.YetAnotherClock.cfg");
			bool num = File.Exists(text2);
			if (num)
			{
				text = null;
			}
			string[] lines = (num ? File.ReadAllLines(text2) : Array.Empty<string>());
			bool flag = num && !LegacyClockConfigRules.HasSetting(lines, "Clock", "AnchorToMinimap");
			float num2 = -32f;
			float num3 = -28f;
			if (flag)
			{
				ConfigFile val = new ConfigFile(text2, false)
				{
					SaveOnConfigSet = false
				};
				num2 = val.Bind<float>("Clock", "OffsetX", num2, (ConfigDescription)null).Value;
				num3 = val.Bind<float>("Clock", "OffsetY", num3, (ConfigDescription)null).Value;
			}
			ConfigFile val2 = PluginConfigFiles.Attach(plugin, new ConfigFile(text2, false, plugin.Info.Metadata));
			bool saveOnConfigSet = val2.SaveOnConfigSet;
			val2.SaveOnConfigSet = false;
			YetAnotherClockConfig yetAnotherClockConfig;
			try
			{
				yetAnotherClockConfig = new YetAnotherClockConfig(val2);
				if (text != null && yetAnotherClockConfig.ImportLegacyGeneralTweaks(text, log))
				{
					yetAnotherClockConfig.MigrateLegacyPosition(yetAnotherClockConfig.OffsetX.Value, yetAnotherClockConfig.OffsetY.Value, log);
				}
				else if (flag)
				{
					yetAnotherClockConfig.MigrateLegacyPosition(num2, num3, log);
				}
			}
			finally
			{
				val2.SaveOnConfigSet = saveOnConfigSet;
			}
			val2.Save();
			return yetAnotherClockConfig;
		}

		internal IEnumerable<IDisposable> RegisterMetadata(ICoreServices services, ModuleId owner)
		{
			//IL_0016: 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)
			foreach (Tuple<ConfigEntryBase, ConfigScope> entry2 in _entries)
			{
				ConfigEntryBase entry = entry2.Item1;
				yield return services.Configuration.Register(new ConfigSettingDescriptor(owner, entry.Definition.Section, entry.Definition.Key, entry2.Item2, (Func<string>)(() => Convert.ToString(entry.BoxedValue, CultureInfo.InvariantCulture)), 1));
			}
		}

		internal static Color ParseColor(string value, float opacity)
		{
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			Color result = default(Color);
			if (!ColorUtility.TryParseHtmlString(value ?? string.Empty, ref result))
			{
				((Color)(ref result))..ctor(0.95f, 0.9f, 0.79f);
			}
			result.a = Mathf.Clamp01(opacity);
			return result;
		}

		private bool ImportLegacyGeneralTweaks(string path, ManualLogSource log)
		{
			//IL_0002: 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_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_0052: 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_0090: 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)
			try
			{
				ConfigFile val = new ConfigFile(path, false)
				{
					SaveOnConfigSet = false
				};
				bool value = val.Bind<bool>("Clock", "Enabled", Enabled.Value, (ConfigDescription)null).Value;
				bool value2 = val.Bind<bool>("Clock", "ShowDay", ShowDay.Value, (ConfigDescription)null).Value;
				float value3 = val.Bind<float>("Clock", "Scale", Scale.Value, (ConfigDescription)null).Value;
				float value4 = val.Bind<float>("Clock", "OffsetX", -32f, (ConfigDescription)null).Value;
				float value5 = val.Bind<float>("Clock", "OffsetY", -28f, (ConfigDescription)null).Value;
				string value6 = val.Bind<string>("Clock", "Color", Color.Value, (ConfigDescription)null).Value;
				float value7 = val.Bind<float>("Clock", "Opacity", Opacity.Value, (ConfigDescription)null).Value;
				Enabled.Value = value;
				ShowDay.Value = value2;
				Scale.Value = value3;
				OffsetX.Value = value4;
				OffsetY.Value = value5;
				Color.Value = value6;
				Opacity.Value = value7;
				if (log != null)
				{
					log.LogInfo((object)("Imported clock settings from " + Path.GetFileName(path) + " into jg224.YetAnotherClock.cfg."));
				}
				return true;
			}
			catch (Exception ex)
			{
				if (log != null)
				{
					log.LogWarning((object)("Could not import clock settings from " + Path.GetFileName(path) + "; the source file was left unchanged. Review jg224.YetAnotherClock.cfg before adjusting your clock. " + ex.Message));
				}
				return false;
			}
		}

		private void MigrateLegacyPosition(float offsetX, float offsetY, ManualLogSource log)
		{
			bool flag = ClockLayoutRules.HasLegacyDefaultOffsets(offsetX, offsetY);
			AnchorToMinimap.Value = flag;
			OffsetX.Value = (flag ? 0f : offsetX);
			OffsetY.Value = (flag ? 0f : offsetY);
			if (log != null)
			{
				log.LogInfo((object)(flag ? "Updated the default clock position to center above the minimap. Disable Clock.AnchorToMinimap to use manual offsets." : "Preserved your custom clock position with Clock.AnchorToMinimap=false. Enable it to center above the minimap without changing your saved offsets."));
			}
		}

		private ConfigEntry<float> ManualOffset(string key, string description)
		{
			//IL_0052: Unknown result type (might be due to invalid IL or missing references)
			//IL_005c: Expected O, but got Unknown
			return Add<float>(_file.Bind<float>("Clock", key, 0f, new ConfigDescription(description, (AcceptableValueBase)(object)new AcceptableValueRange<float>(-1000f, 1000f), new object[1]
			{
				new ConfigurationManagerAttributes
				{
					CustomDrawer = new OffsetSettingDrawer(() => AnchorToMinimap.Value).Draw
				}
			})), (ConfigScope)1);
		}

		private ConfigEntry<T> Local<T>(string section, string key, T value, string description)
		{
			return Add<T>(_file.Bind<T>(section, key, value, description), (ConfigScope)1);
		}

		private ConfigEntry<float> LocalRange(string section, string key, float value, float min, float max, string description)
		{
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: Expected O, but got Unknown
			return Add<float>(_file.Bind<float>(section, key, value, new ConfigDescription(description, (AcceptableValueBase)(object)new AcceptableValueRange<float>(min, max), Array.Empty<object>())), (ConfigScope)1);
		}

		private ConfigEntry<T> Developer<T>(string section, string key, T value, string description)
		{
			return Add<T>(_file.Bind<T>(section, key, value, description), (ConfigScope)5);
		}

		private ConfigEntry<T> Add<T>(ConfigEntry<T> entry, ConfigScope scope)
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			_entries.Add(Tuple.Create<ConfigEntryBase, ConfigScope>((ConfigEntryBase)(object)entry, scope));
			return entry;
		}
	}
}
namespace JG224.YetAnotherClock.UI
{
	internal sealed class ConfigurationManagerAttributes
	{
		public Action<ConfigEntryBase> CustomDrawer;

		public bool HideDefaultButton = true;
	}
	internal sealed class OffsetSettingDrawer
	{
		private readonly Func<bool> _anchorToMinimap;

		private string _text;

		private float _displayedValue = float.NaN;

		internal OffsetSettingDrawer(Func<bool> anchorToMinimap)
		{
			_anchorToMinimap = anchorToMinimap;
		}

		internal void Draw(ConfigEntryBase setting)
		{
			ConfigEntry<float> val = (ConfigEntry<float>)(object)setting;
			AcceptableValueRange<float> val2 = (AcceptableValueRange<float>)(object)((ConfigEntryBase)val).Description.AcceptableValues;
			if (_text == null || _displayedValue != val.Value)
			{
				RefreshText(val.Value);
			}
			bool enabled = GUI.enabled;
			bool flag = enabled && !_anchorToMinimap();
			try
			{
				GUI.enabled = flag;
				float num = GUILayout.HorizontalSlider(val.Value, val2.MinValue, val2.MaxValue, Array.Empty<GUILayoutOption>());
				string text = GUILayout.TextField(_text, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(85f) });
				bool flag2 = GUILayout.Button("Reset", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(55f) });
				if (!flag)
				{
					return;
				}
				if (flag2)
				{
					val.Value = (float)((ConfigEntryBase)val).DefaultValue;
					RefreshText(val.Value);
				}
				else if (num != val.Value)
				{
					val.Value = num;
					RefreshText(val.Value);
				}
				else
				{
					if (!(text != _text))
					{
						return;
					}
					_text = text;
					if (float.TryParse(text, NumberStyles.Float, CultureInfo.InvariantCulture, out var result) && !float.IsNaN(result) && !float.IsInfinity(result))
					{
						val.Value = result;
						_displayedValue = val.Value;
						if (val.Value != result)
						{
							RefreshText(val.Value);
						}
					}
				}
			}
			finally
			{
				GUI.enabled = enabled;
			}
		}

		private void RefreshText(float value)
		{
			_displayedValue = value;
			_text = value.ToString(CultureInfo.InvariantCulture);
		}
	}
	internal static class OverlayController
	{
		[CompilerGenerated]
		private static class <>O
		{
			public static WillRenderCanvases <0>__UpdateLayout;
		}

		private static GameObject _root;

		private static RectTransform _canvasRect;

		private static Text _clock;

		private static Font _font;

		private static RectTransform _minimapRect;

		private static Canvas _minimapCanvas;

		private static int _minutes = -1;

		private static int _day = -1;

		private static bool _showDay;

		private static bool _twelveHour;

		private static string _color;

		private static float _opacity = -1f;

		internal static void Tick()
		{
			if (Application.isBatchMode || !Object.op_Implicit((Object)(object)Player.m_localPlayer) || !Object.op_Implicit((Object)(object)ZNet.instance))
			{
				if (Object.op_Implicit((Object)(object)_root))
				{
					_root.SetActive(false);
				}
				return;
			}
			EnsureCreated();
			if (Object.op_Implicit((Object)(object)_root))
			{
				_root.SetActive(true);
				UpdateClock();
			}
		}

		internal static void Destroy()
		{
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Expected O, but got Unknown
			object obj = <>O.<0>__UpdateLayout;
			if (obj == null)
			{
				WillRenderCanvases val = UpdateLayout;
				<>O.<0>__UpdateLayout = val;
				obj = (object)val;
			}
			Canvas.preWillRenderCanvases -= (WillRenderCanvases)obj;
			if (Object.op_Implicit((Object)(object)_root))
			{
				Object.Destroy((Object)(object)_root);
			}
			_root = null;
			_canvasRect = null;
			_clock = null;
			_font = null;
			_minimapRect = null;
			_minimapCanvas = null;
			_minutes = (_day = -1);
			_color = null;
			_opacity = -1f;
		}

		private static void EnsureCreated()
		{
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: Expected O, but got Unknown
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			//IL_0040: Expected O, but got Unknown
			//IL_00bd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c2: Unknown result type (might be due to invalid IL or missing references)
			//IL_0159: Unknown result type (might be due to invalid IL or missing references)
			//IL_015f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0179: Unknown result type (might be due to invalid IL or missing references)
			//IL_0197: 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_01b6: Unknown result type (might be due to invalid IL or missing references)
			//IL_01bc: Expected O, but got Unknown
			//IL_01d1: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d6: Unknown result type (might be due to invalid IL or missing references)
			//IL_01dc: Expected O, but got Unknown
			if (Object.op_Implicit((Object)(object)_root))
			{
				return;
			}
			_root = new GameObject("JG224.YetAnotherClock.Overlay");
			Object.DontDestroyOnLoad((Object)(object)_root);
			Canvas obj = _root.AddComponent<Canvas>();
			_canvasRect = (RectTransform)((Component)obj).transform;
			obj.renderMode = (RenderMode)0;
			obj.sortingOrder = 200;
			obj.pixelPerfect = false;
			_root.AddComponent<CanvasScaler>().uiScaleMode = (ScaleMode)0;
			((Behaviour)_root.AddComponent<GraphicRaycaster>()).enabled = false;
			_font = Resources.GetBuiltinResource<Font>("Arial.ttf");
			if (!Object.op_Implicit((Object)(object)_font))
			{
				Font[] array = Resources.FindObjectsOfTypeAll<Font>();
				if (array.Length != 0)
				{
					_font = array[0];
				}
			}
			GameObject val = new GameObject("Clock", new Type[1] { typeof(RectTransform) });
			val.transform.SetParent(_root.transform, false);
			_clock = val.AddComponent<Text>();
			_clock.font = _font;
			_clock.fontSize = 18;
			_clock.fontStyle = (FontStyle)1;
			_clock.alignment = (TextAnchor)2;
			_clock.horizontalOverflow = (HorizontalWrapMode)1;
			_clock.verticalOverflow = (VerticalWrapMode)1;
			((Graphic)_clock).raycastTarget = false;
			RectTransform rectTransform = ((Graphic)_clock).rectTransform;
			RectTransform rectTransform2 = ((Graphic)_clock).rectTransform;
			Vector2 val2 = default(Vector2);
			((Vector2)(ref val2))..ctor(1f, 1f);
			rectTransform2.anchorMax = val2;
			rectTransform.anchorMin = val2;
			((Graphic)_clock).rectTransform.pivot = new Vector2(1f, 1f);
			((Graphic)_clock).rectTransform.sizeDelta = new Vector2(320f, 32f);
			object obj2 = <>O.<0>__UpdateLayout;
			if (obj2 == null)
			{
				WillRenderCanvases val3 = UpdateLayout;
				<>O.<0>__UpdateLayout = val3;
				obj2 = (object)val3;
			}
			Canvas.preWillRenderCanvases -= (WillRenderCanvases)obj2;
			object obj3 = <>O.<0>__UpdateLayout;
			if (obj3 == null)
			{
				WillRenderCanvases val4 = UpdateLayout;
				<>O.<0>__UpdateLayout = val4;
				obj3 = (object)val4;
			}
			Canvas.preWillRenderCanvases += (WillRenderCanvases)obj3;
		}

		private static void UpdateClock()
		{
			//IL_01c8: Unknown result type (might be due to invalid IL or missing references)
			YetAnotherClockConfig settings = Plugin.Settings;
			bool hudVisible = Object.op_Implicit((Object)(object)Hud.instance) && !Hud.IsUserHidden() && Object.op_Implicit((Object)(object)Hud.instance.m_rootObject) && Hud.instance.m_rootObject.activeInHierarchy;
			bool minimapVisible = Object.op_Implicit((Object)(object)Minimap.instance) && Object.op_Implicit((Object)(object)Minimap.instance.m_smallRoot) && Minimap.instance.m_smallRoot.activeInHierarchy;
			bool flag = settings != null && Object.op_Implicit((Object)(object)EnvMan.instance) && ClockRules.IsVisible(settings.Enabled.Value, hudVisible, minimapVisible, settings.ShowWhenHudHidden.Value, settings.RequireMinimap.Value);
			((Component)_clock).gameObject.SetActive(flag);
			if (flag)
			{
				int num = ClockRules.DayMinutes(EnvMan.instance.GetDayFraction());
				int day = EnvMan.instance.GetDay();
				if (_minutes != num || _day != day || _showDay != settings.ShowDay.Value || _twelveHour != settings.TwelveHour.Value)
				{
					string text = ClockRules.FormatTime(num, settings.TwelveHour.Value);
					_clock.text = (settings.ShowDay.Value ? ("Day " + day + " — " + text) : text);
					_minutes = num;
					_day = day;
					_showDay = settings.ShowDay.Value;
					_twelveHour = settings.TwelveHour.Value;
				}
				if (_color != settings.Color.Value || _opacity != settings.Opacity.Value)
				{
					((Graphic)_clock).color = YetAnotherClockConfig.ParseColor(settings.Color.Value, settings.Opacity.Value);
					_color = settings.Color.Value;
					_opacity = settings.Opacity.Value;
				}
			}
		}

		private static void UpdateLayout()
		{
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			//IL_0049: Unknown result type (might be due to invalid IL or missing references)
			//IL_004e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0050: 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_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_006f: 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_0076: 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_005e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ac: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ba: 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_0125: Unknown result type (might be due to invalid IL or missing references)
			//IL_012a: Unknown result type (might be due to invalid IL or missing references)
			//IL_010a: Unknown result type (might be due to invalid IL or missing references)
			//IL_010f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0122: Unknown result type (might be due to invalid IL or missing references)
			//IL_013a: Unknown result type (might be due to invalid IL or missing references)
			//IL_013f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0133: Unknown result type (might be due to invalid IL or missing references)
			//IL_014f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0154: Unknown result type (might be due to invalid IL or missing references)
			//IL_0148: Unknown result type (might be due to invalid IL or missing references)
			//IL_016a: Unknown result type (might be due to invalid IL or missing references)
			//IL_016f: 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_0180: Unknown result type (might be due to invalid IL or missing references)
			//IL_0185: Unknown result type (might be due to invalid IL or missing references)
			//IL_0178: Unknown result type (might be due to invalid IL or missing references)
			//IL_018f: Unknown result type (might be due to invalid IL or missing references)
			YetAnotherClockConfig settings = Plugin.Settings;
			if (Object.op_Implicit((Object)(object)_clock) && Object.op_Implicit((Object)(object)_canvasRect) && ((Behaviour)_clock).isActiveAndEnabled && settings != null)
			{
				RectTransform rectTransform = ((Graphic)_clock).rectTransform;
				Vector3 val = Vector3.one * settings.Scale.Value;
				if (((Transform)rectTransform).localScale != val)
				{
					((Transform)rectTransform).localScale = val;
				}
				Vector2 val2 = Vector2.one;
				Vector2 one = Vector2.one;
				TextAnchor val3 = (TextAnchor)2;
				Vector2 left = default(Vector2);
				Vector2 right = default(Vector2);
				bool flag = settings.AnchorToMinimap.Value && TryGetMinimapTop(out left, out right);
				ClockPosition clockPosition = ClockLayoutRules.ResolvePosition(settings.AnchorToMinimap.Value, flag, left.x, right.x, (left.y + right.y) * 0.5f, settings.OffsetX.Value, settings.OffsetY.Value);
				Vector2 val4 = default(Vector2);
				((Vector2)(ref val4))..ctor(clockPosition.X, clockPosition.Y);
				if (flag)
				{
					val2 = _canvasRect.pivot;
					((Vector2)(ref one))..ctor(0.5f, 0f);
					val3 = (TextAnchor)7;
				}
				if (rectTransform.anchorMin != val2)
				{
					rectTransform.anchorMin = val2;
				}
				if (rectTransform.anchorMax != val2)
				{
					rectTransform.anchorMax = val2;
				}
				if (rectTransform.pivot != one)
				{
					rectTransform.pivot = one;
				}
				if (_clock.alignment != val3)
				{
					_clock.alignment = val3;
				}
				if (rectTransform.anchoredPosition != val4)
				{
					rectTransform.anchoredPosition = val4;
				}
			}
		}

		private static bool TryGetMinimapTop(out Vector2 left, out Vector2 right)
		{
			//IL_0004: Unknown result type (might be due to invalid IL or missing references)
			//IL_000a: 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_000d: 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_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: 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_0091: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00be: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ee: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f8: 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_0112: Unknown result type (might be due to invalid IL or missing references)
			//IL_0117: Unknown result type (might be due to invalid IL or missing references)
			//IL_011c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0121: Unknown result type (might be due to invalid IL or missing references)
			//IL_0127: Unknown result type (might be due to invalid IL or missing references)
			//IL_0136: Unknown result type (might be due to invalid IL or missing references)
			left = (right = default(Vector2));
			RectTransform val = ((Object.op_Implicit((Object)(object)Minimap.instance) && Object.op_Implicit((Object)(object)Minimap.instance.m_mapImageSmall)) ? ((Graphic)Minimap.instance.m_mapImageSmall).rectTransform : null);
			if (!Object.op_Implicit((Object)(object)val))
			{
				return false;
			}
			if ((Object)(object)_minimapRect != (Object)(object)val || !Object.op_Implicit((Object)(object)_minimapCanvas))
			{
				_minimapRect = val;
				_minimapCanvas = ((Component)val).GetComponentInParent<Canvas>();
			}
			if (Object.op_Implicit((Object)(object)_minimapCanvas))
			{
				Rect rect = val.rect;
				if (!(((Rect)(ref rect)).width <= 0f))
				{
					rect = val.rect;
					if (!(((Rect)(ref rect)).height <= 0f))
					{
						Camera obj = (((int)_minimapCanvas.renderMode == 0) ? null : _minimapCanvas.worldCamera);
						Rect rect2 = val.rect;
						Vector2 val2 = RectTransformUtility.WorldToScreenPoint(obj, ((Transform)val).TransformPoint(new Vector3(((Rect)(ref rect2)).xMin, ((Rect)(ref rect2)).yMax, 0f)));
						Vector2 val3 = RectTransformUtility.WorldToScreenPoint(obj, ((Transform)val).TransformPoint(new Vector3(((Rect)(ref rect2)).xMax, ((Rect)(ref rect2)).yMax, 0f)));
						if (RectTransformUtility.ScreenPointToLocalPointInRectangle(_canvasRect, val2, (Camera)null, ref left))
						{
							return RectTransformUtility.ScreenPointToLocalPointInRectangle(_canvasRect, val3, (Camera)null, ref right);
						}
						return false;
					}
				}
			}
			return false;
		}
	}
}
namespace JG224.YetAnotherClock.Core
{
	internal readonly struct ClockPosition
	{
		internal float X { get; }

		internal float Y { get; }

		internal ClockPosition(float x, float y)
		{
			X = x;
			Y = y;
		}
	}
	internal static class ClockLayoutRules
	{
		internal const float LegacyOffsetX = -32f;

		internal const float LegacyOffsetY = -28f;

		internal const float MinimapGap = 8f;

		internal static bool HasLegacyDefaultOffsets(float x, float y)
		{
			if (x == -32f)
			{
				return y == -28f;
			}
			return false;
		}

		internal static ClockPosition AboveMinimap(float left, float right, float top)
		{
			return new ClockPosition(left + (right - left) * 0.5f, top + 8f);
		}

		internal static ClockPosition ResolvePosition(bool anchorToMinimap, bool minimapAvailable, float left, float right, float top, float offsetX, float offsetY)
		{
			if (!anchorToMinimap)
			{
				return new ClockPosition(offsetX, offsetY);
			}
			if (!minimapAvailable)
			{
				return new ClockPosition(-32f, -28f);
			}
			return AboveMinimap(left, right, top);
		}
	}
	internal static class ClockRules
	{
		internal static int DayMinutes(float dayFraction)
		{
			if (float.IsNaN(dayFraction) || float.IsInfinity(dayFraction))
			{
				return 0;
			}
			return (int)Math.Floor((dayFraction - (float)Math.Floor(dayFraction)) * 1440f) % 1440;
		}

		internal static string FormatTime(int minutes)
		{
			return FormatTime(minutes, twelveHour: false);
		}

		internal static string FormatTime(int minutes, bool twelveHour)
		{
			minutes = (minutes % 1440 + 1440) % 1440;
			if (twelveHour)
			{
				return ((minutes / 60 + 11) % 12 + 1).ToString(CultureInfo.InvariantCulture) + ":" + (minutes % 60).ToString("00", CultureInfo.InvariantCulture) + ((minutes < 720) ? " AM" : " PM");
			}
			return (minutes / 60).ToString("00", CultureInfo.InvariantCulture) + ":" + (minutes % 60).ToString("00", CultureInfo.InvariantCulture);
		}

		internal static bool IsVisible(bool enabled, bool hudVisible, bool minimapVisible, bool showWhenHudHidden, bool requireMinimap)
		{
			if (enabled && (hudVisible || showWhenHudHidden))
			{
				return !requireMinimap || minimapVisible;
			}
			return false;
		}
	}
	internal static class LegacyClockConfigRules
	{
		internal const string CurrentFileName = "jg224.YetAnotherClock.cfg";

		internal const string GeneralTweaksFileName = "jg224.GeneralTweaks.cfg";

		internal const string LegacyGeneralTweaksFileName = "JG224.GeneralTweaks.cfg";

		internal static string FindImportSource(IEnumerable<string> candidatePaths)
		{
			string[] paths = ((candidatePaths == null) ? Array.Empty<string>() : candidatePaths.ToArray());
			if (FindExact(paths, "jg224.YetAnotherClock.cfg") != null)
			{
				return null;
			}
			return FindExact(paths, "jg224.GeneralTweaks.cfg") ?? FindExact(paths, "JG224.GeneralTweaks.cfg");
		}

		internal static bool HasSetting(IEnumerable<string> lines, string section, string key)
		{
			if (lines == null)
			{
				return false;
			}
			string a = string.Empty;
			foreach (string line in lines)
			{
				string text = (line ?? string.Empty).Trim();
				if (text.StartsWith("#", StringComparison.Ordinal))
				{
					continue;
				}
				if (text.StartsWith("[", StringComparison.Ordinal) && text.EndsWith("]", StringComparison.Ordinal))
				{
					a = text.Substring(1, text.Length - 2);
					continue;
				}
				int num = text.IndexOf('=');
				if (num >= 0 && string.Equals(a, section, StringComparison.Ordinal) && string.Equals(text.Substring(0, num).Trim(), key, StringComparison.Ordinal))
				{
					return true;
				}
			}
			return false;
		}

		private static string FindExact(IEnumerable<string> paths, string fileName)
		{
			return paths.FirstOrDefault((string path) => string.Equals(Path.GetFileName(path), fileName, StringComparison.Ordinal));
		}
	}
}