Please disclose if any significant portion of your mod was created using AI tools by adding the 'AI Generated' category. Failing to do so may result in the mod being removed from Thunderstore.
Decompiled source of RunicClock v1.0.1
RunicClock.dll
Decompiled 3 days agousing System; using System.Diagnostics; using System.Globalization; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using BepInEx; using BepInEx.Configuration; using Microsoft.CodeAnalysis; 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("Chazman")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyDescription("Client-only in-game time, day count, and optional local clock.")] [assembly: AssemblyFileVersion("1.0.1.0")] [assembly: AssemblyInformationalVersion("1.0.1+14960c6664ff621e4c84275abdf3cad7253008dc")] [assembly: AssemblyProduct("RunicClock")] [assembly: AssemblyTitle("RunicClock")] [assembly: AssemblyVersion("1.0.1.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 RunicClock { internal sealed class ClockConfig { internal readonly ConfigEntry<bool> Enabled; internal readonly ConfigEntry<bool> Visible; internal readonly ConfigEntry<bool> Use24Hour; internal readonly ConfigEntry<bool> ShowDay; internal readonly ConfigEntry<bool> ShowIndicator; internal readonly ConfigEntry<bool> ShowRealTime; internal readonly ConfigEntry<bool> RealTime24Hour; internal readonly ConfigEntry<bool> HideInMenus; internal readonly ConfigEntry<float> Scale; internal readonly ConfigEntry<float> OffsetX; internal readonly ConfigEntry<float> OffsetY; internal readonly ConfigEntry<float> BackgroundOpacity; internal readonly ConfigEntry<ClockAnchor> Anchor; internal readonly ConfigEntry<KeyboardShortcut> ToggleKey; internal ClockConfig(ConfigFile config) { //IL_005a: Unknown result type (might be due to invalid IL or missing references) //IL_0140: Unknown result type (might be due to invalid IL or missing references) //IL_014a: Expected O, but got Unknown //IL_0179: Unknown result type (might be due to invalid IL or missing references) //IL_0183: Expected O, but got Unknown //IL_01b2: Unknown result type (might be due to invalid IL or missing references) //IL_01bc: Expected O, but got Unknown //IL_01eb: Unknown result type (might be due to invalid IL or missing references) //IL_01f5: Expected O, but got Unknown Enabled = config.Bind<bool>("General", "Enabled", true, "Enable the client-only clock. No world or server settings are changed."); Visible = config.Bind<bool>("General", "Visible", true, "Show the clock. The toggle shortcut also changes this setting."); ToggleKey = config.Bind<KeyboardShortcut>("General", "ToggleShortcut", new KeyboardShortcut((KeyCode)99, (KeyCode[])(object)new KeyCode[1] { (KeyCode)308 }), "Toggle clock visibility during gameplay. Default: Left Alt+C. Ignored while typing or in menus. Set to None to disable."); Use24Hour = config.Bind<bool>("Clock", "Use24Hour", true, "Display game time as 18:30 instead of 6:30 PM."); ShowDay = config.Bind<bool>("Clock", "ShowDay", true, "Show Valheim's current world day number."); ShowIndicator = config.Bind<bool>("Clock", "ShowSunMoon", true, "Show a sun by day and a crescent moon by night."); ShowRealTime = config.Bind<bool>("Clock", "ShowRealWorldTime", false, "Add your computer's local time, labeled Local. This is not the server's time zone."); RealTime24Hour = config.Bind<bool>("Clock", "RealWorldUse24Hour", true, "Use 24-hour format for the optional local clock."); Anchor = config.Bind<ClockAnchor>("Display", "Anchor", ClockAnchor.TopCenter, "Choose the screen anchor for the clock."); OffsetX = config.Bind<float>("Display", "OffsetX", 0f, new ConfigDescription("Horizontal offset in screen pixels; positive moves right. Kept within the screen safe area.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(-4096f, 4096f), Array.Empty<object>())); OffsetY = config.Bind<float>("Display", "OffsetY", 64f, new ConfigDescription("Vertical offset in screen pixels; positive moves down. Kept within the screen safe area.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(-4096f, 4096f), Array.Empty<object>())); Scale = config.Bind<float>("Display", "Scale", 1f, new ConfigDescription("Clock size multiplier. Also scales with screen height relative to 1080p.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.6f, 2f), Array.Empty<object>())); BackgroundOpacity = config.Bind<float>("Display", "BackgroundOpacity", 0.65f, new ConfigDescription("Dark panel opacity. Zero hides the panel and its border.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1f), Array.Empty<object>())); HideInMenus = config.Bind<bool>("Display", "HideInMenus", true, "Hide while menus, inventory, map, chat input, or text input are open. Always hides with the HUD and during loading."); } } public enum ClockAnchor { TopLeft, TopCenter, TopRight, MiddleLeft, Center, MiddleRight, BottomLeft, BottomCenter, BottomRight } internal static class ClockModel { internal static bool TryGameTime(double dayFraction, bool use24Hour, out string text) { text = string.Empty; if (double.IsNaN(dayFraction) || double.IsInfinity(dayFraction) || dayFraction < 0.0 || dayFraction > 1.0) { return false; } int num = ((dayFraction != 1.0) ? Math.Min(1439, (int)Math.Floor(dayFraction * 1440.0)) : 0); text = FormatTime(num / 60, num % 60, use24Hour); return true; } internal static string FormatTime(int hour, int minute, bool use24Hour) { if (hour < 0 || hour > 23 || minute < 0 || minute > 59) { throw new ArgumentOutOfRangeException(); } if (use24Hour) { return hour.ToString("00", CultureInfo.InvariantCulture) + ":" + minute.ToString("00", CultureInfo.InvariantCulture); } int num = hour % 12; return ((num == 0) ? 12 : num).ToString(CultureInfo.InvariantCulture) + ":" + minute.ToString("00", CultureInfo.InvariantCulture) + ((hour < 12) ? " AM" : " PM"); } internal static double Clamp(double value, double min, double max, double fallback) { if (!double.IsNaN(value) && !double.IsInfinity(value)) { return Math.Max(min, Math.Min(max, value)); } return fallback; } internal static (double X, double Y) Position(ClockAnchor anchor, double safeX, double safeY, double safeWidth, double safeHeight, double width, double height, double offsetX, double offsetY) { int num = (int)anchor; if (num < 0 || num > 8) { num = 1; } double num2 = Math.Max(0.0, safeWidth - width); double num3 = Math.Max(0.0, safeHeight - height); double val = safeX + num2 * (double)(num % 3) / 2.0 + Clamp(offsetX, -4096.0, 4096.0, 0.0); double val2 = safeY + num3 * (double)(num / 3) / 2.0 + Clamp(offsetY, -4096.0, 4096.0, 0.0); return (X: Math.Max(safeX, Math.Min(safeX + num2, val)), Y: Math.Max(safeY, Math.Min(safeY + num3, val2))); } } internal sealed class ClockView : IDisposable { private readonly ClockConfig _settings; private readonly GUIContent _time = new GUIContent(); private readonly GUIContent _day = new GUIContent(); private readonly GUIContent _local = new GUIContent(); private GUIStyle _large; private GUIStyle _small; private int _fontSize; private bool _isDay; private Texture2D _sun; private Texture2D _moon; private static readonly Color Gold = new Color(1f, 0.8f, 0.35f); internal ClockView(ClockConfig settings) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Expected O, but got Unknown //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Expected O, but got Unknown //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Expected O, but got Unknown _settings = settings; } internal void SetText(string time, string day, string local, bool isDay) { _time.text = time; _day.text = day; _local.text = local; _isDay = isDay; } internal void Draw() { //IL_0465: Unknown result type (might be due to invalid IL or missing references) //IL_009c: Unknown result type (might be due to invalid IL or missing references) //IL_00a1: 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_0187: Unknown result type (might be due to invalid IL or missing references) //IL_01aa: Unknown result type (might be due to invalid IL or missing references) //IL_0287: Unknown result type (might be due to invalid IL or missing references) //IL_028c: Unknown result type (might be due to invalid IL or missing references) //IL_02cb: Unknown result type (might be due to invalid IL or missing references) //IL_02de: Unknown result type (might be due to invalid IL or missing references) //IL_0308: Unknown result type (might be due to invalid IL or missing references) //IL_032d: Unknown result type (might be due to invalid IL or missing references) //IL_03cb: Unknown result type (might be due to invalid IL or missing references) //IL_03e5: Unknown result type (might be due to invalid IL or missing references) //IL_03f1: Unknown result type (might be due to invalid IL or missing references) //IL_041f: Unknown result type (might be due to invalid IL or missing references) //IL_037e: Unknown result type (might be due to invalid IL or missing references) //IL_0377: Unknown result type (might be due to invalid IL or missing references) //IL_044d: Unknown result type (might be due to invalid IL or missing references) //IL_039c: Unknown result type (might be due to invalid IL or missing references) float num = (float)ClockModel.Clamp(_settings.Scale.Value, 0.6, 2.0, 1.0) * Mathf.Clamp((float)Screen.height / 1080f, 0.5f, 3f); EnsureStyles(Mathf.Max(12, Mathf.RoundToInt(24f * num))); if ((Object)(object)_sun == (Object)null) { _sun = CreateSymbol(moon: false); } if ((Object)(object)_moon == (Object)null) { _moon = CreateSymbol(moon: true); } Rect safeArea = Screen.safeArea; if (((Rect)(ref safeArea)).width <= 0f || ((Rect)(ref safeArea)).height <= 0f) { ((Rect)(ref safeArea))..ctor(0f, 0f, (float)Screen.width, (float)Screen.height); } float num2 = (float)Screen.height - ((Rect)(ref safeArea)).yMax; float num3 = 10f * num; float num4 = 31f * num; float num5 = 21f * num; float num6 = 24f * num; bool value = _settings.ShowIndicator.Value; bool value2 = _settings.ShowDay.Value; bool value3 = _settings.ShowRealTime.Value; float num7 = _large.CalcSize(_time).x + (value ? (num6 + 8f * num) : 0f); float num8 = num7; if (value2) { num8 = Mathf.Max(num8, _small.CalcSize(_day).x); } if (value3) { num8 = Mathf.Max(num8, _small.CalcSize(_local).x); } float num9 = Mathf.Min(((Rect)(ref safeArea)).width, Mathf.Max(180f * num, num8 + num3 * 2f)); float num10 = Mathf.Min(((Rect)(ref safeArea)).height, num3 * 2f + num4 + (value2 ? num5 : 0f) + (value3 ? num5 : 0f)); (double, double) tuple = ClockModel.Position(_settings.Anchor.Value, ((Rect)(ref safeArea)).x, num2, ((Rect)(ref safeArea)).width, ((Rect)(ref safeArea)).height, num9, num10, _settings.OffsetX.Value, _settings.OffsetY.Value); Rect area = default(Rect); ((Rect)(ref area))..ctor((float)tuple.Item1, (float)tuple.Item2, num9, num10); Color color = GUI.color; try { float num11 = (float)ClockModel.Clamp(_settings.BackgroundOpacity.Value, 0.0, 1.0, 0.65); if (num11 > 0f) { Paint(area, new Color(0.025f, 0.035f, 0.06f, num11)); Paint(new Rect(((Rect)(ref area)).x, ((Rect)(ref area)).y, ((Rect)(ref area)).width, Mathf.Max(1f, num)), new Color(Gold.r, Gold.g, Gold.b, num11)); } float num12 = ((Rect)(ref area)).x + (((Rect)(ref area)).width - num7) / 2f; float num13 = ((Rect)(ref area)).y + num3; if (value) { GUI.color = (Color)(_isDay ? Gold : new Color(0.77f, 0.86f, 1f)); GUI.DrawTexture(new Rect(num12, num13 + (num4 - num6) / 2f, num6, num6), (Texture)(object)(_isDay ? _sun : _moon)); num12 += num6 + 8f * num; } GUI.color = Color.white; GUI.Label(new Rect(num12, num13, _large.CalcSize(_time).x, num4), _time, _large); num13 += num4; if (value2) { GUI.Label(new Rect(((Rect)(ref area)).x, num13, num9, num5), _day, _small); num13 += num5; } if (value3) { GUI.Label(new Rect(((Rect)(ref area)).x, num13, num9, num5), _local, _small); } } finally { GUI.color = color; } } private static void Paint(Rect area, Color color) { //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) GUI.color = color; GUI.DrawTexture(area, (Texture)(object)Texture2D.whiteTexture); } private void EnsureStyles(int fontSize) { //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_0029: 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_0037: 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) //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_004c: 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_005b: Expected O, but got Unknown //IL_0060: Expected O, but got Unknown //IL_006b: Unknown result type (might be due to invalid IL or missing references) //IL_007c: 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) //IL_009b: Unknown result type (might be due to invalid IL or missing references) //IL_00a7: Expected O, but got Unknown //IL_00c1: Unknown result type (might be due to invalid IL or missing references) if (_large == null || _fontSize != fontSize) { _fontSize = fontSize; _large = new GUIStyle(GUI.skin.label) { fontSize = fontSize, fontStyle = (FontStyle)1, alignment = (TextAnchor)4, richText = false, wordWrap = false, padding = new RectOffset(0, 0, 0, 0) }; _large.normal.textColor = Gold; _small = new GUIStyle(_large) { fontSize = Mathf.Max(10, Mathf.RoundToInt((float)fontSize * 0.62f)), fontStyle = (FontStyle)0 }; _small.normal.textColor = new Color(0.91f, 0.92f, 0.95f); } } private static Texture2D CreateSymbol(bool moon) { //IL_01ae: Unknown result type (might be due to invalid IL or missing references) //IL_01b3: Unknown result type (might be due to invalid IL or missing references) //IL_01c8: Unknown result type (might be due to invalid IL or missing references) //IL_01d0: Unknown result type (might be due to invalid IL or missing references) //IL_01d7: Unknown result type (might be due to invalid IL or missing references) //IL_01de: Unknown result type (might be due to invalid IL or missing references) //IL_01e5: Unknown result type (might be due to invalid IL or missing references) //IL_01ee: Expected O, but got Unknown //IL_0186: Unknown result type (might be due to invalid IL or missing references) //IL_018b: Unknown result type (might be due to invalid IL or missing references) Color[] array = (Color[])(object)new Color[4096]; for (int i = 0; i < 64; i++) { for (int j = 0; j < 64; j++) { float num = 0f; for (int k = 0; k < 2; k++) { for (int l = 0; l < 2; l++) { double num2 = ((double)j + ((double)l + 0.5) / 2.0 - 32.0) / 32.0; double num3 = ((double)i + ((double)k + 0.5) / 2.0 - 32.0) / 32.0; double num4 = Math.Sqrt(num2 * num2 + num3 * num3); bool num5; if (!moon) { if (num4 < 0.48) { goto IL_014b; } if (!(num4 > 0.62) || !(num4 < 0.9)) { continue; } num5 = Math.Abs(Math.Sin(Math.Atan2(num3, num2) * 4.0)) < 0.18; } else { if (!(num4 < 0.85)) { continue; } num5 = (num2 - 0.4) * (num2 - 0.4) + (num3 - 0.2) * (num3 - 0.2) > 0.5184; } if (!num5) { continue; } goto IL_014b; IL_014b: num += 0.25f; } } array[i * 64 + j] = new Color(1f, 1f, 1f, num); } } Texture2D val = new Texture2D(64, 64, (TextureFormat)4, false) { name = (moon ? "RunicClock Moon" : "RunicClock Sun"), hideFlags = (HideFlags)61, filterMode = (FilterMode)1, wrapMode = (TextureWrapMode)1 }; val.SetPixels(array); val.Apply(false, true); return val; } public void Dispose() { if ((Object)(object)_sun != (Object)null) { Object.Destroy((Object)(object)_sun); } if ((Object)(object)_moon != (Object)null) { Object.Destroy((Object)(object)_moon); } _sun = (_moon = null); } } [BepInPlugin("chazman.RunicClock", "Runic Clock", "1.0.1")] public sealed class Plugin : BaseUnityPlugin { public const string Guid = "chazman.RunicClock"; public const string Name = "Runic Clock"; public const string Version = "1.0.1"; private ClockConfig _settings; private ClockView _view; private Player _player; private EnvMan _environment; private ZNet _network; private float _nextRefresh; private volatile bool _refreshRequested; private bool _ready; private bool _failed; private void Awake() { if (Application.isBatchMode) { ((BaseUnityPlugin)this).Logger.LogInfo((object)"RunicClock is client-only; no server runtime started."); return; } _settings = new ClockConfig(((BaseUnityPlugin)this).Config); _view = new ClockView(_settings); ((BaseUnityPlugin)this).Config.SettingChanged += SettingsChanged; ((BaseUnityPlugin)this).Logger.LogInfo((object)"Runic Clock 1.0.1 ready. Left Alt+C toggles the clock; all settings are local."); } private void SettingsChanged(object sender, SettingChangedEventArgs args) { _refreshRequested = true; } private void Update() { //IL_00c3: Unknown result type (might be due to invalid IL or missing references) //IL_00c8: Unknown result type (might be due to invalid IL or missing references) if (_settings == null || _failed) { return; } try { if (!_settings.Enabled.Value || !HasWorld()) { _ready = false; _nextRefresh = 0f; _player = null; _environment = null; _network = null; return; } if (_player != Player.m_localPlayer || _environment != EnvMan.instance || _network != ZNet.instance) { _player = Player.m_localPlayer; _environment = EnvMan.instance; _network = ZNet.instance; _ready = false; _nextRefresh = 0f; } if (!InputBlocked()) { KeyboardShortcut value = _settings.ToggleKey.Value; if (((KeyboardShortcut)(ref value)).IsDown()) { _settings.Visible.Value = !_settings.Visible.Value; } } if (!_settings.Visible.Value) { _ready = false; return; } float unscaledTime = Time.unscaledTime; if (_refreshRequested) { _refreshRequested = false; _nextRefresh = 0f; } if (unscaledTime < _nextRefresh && unscaledTime >= _nextRefresh - 0.25f) { return; } _nextRefresh = unscaledTime + 0.25f; _ready = ClockModel.TryGameTime(_environment.GetDayFraction(), _settings.Use24Hour.Value, out var text); if (_ready) { int day = _environment.GetDay(); if (day < 0) { _ready = false; return; } DateTime now = DateTime.Now; _view.SetText(text, "Day " + day.ToString(CultureInfo.InvariantCulture), "Local " + ClockModel.FormatTime(now.Hour, now.Minute, _settings.RealTime24Hour.Value), EnvMan.IsDay()); } } catch (Exception error) { Fail(error); } } private static bool HasWorld() { if ((Object)(object)Player.m_localPlayer != (Object)null && (Object)(object)EnvMan.instance != (Object)null && (Object)(object)ZNet.instance != (Object)null) { return (Object)(object)Hud.instance != (Object)null; } return false; } private static bool InputBlocked() { if (!Menu.IsVisible() && !Console.IsVisible() && !TextInput.IsVisible() && !InventoryGui.IsVisible() && !Minimap.IsOpen() && !StoreGui.IsVisible() && !Hud.IsPieceSelectionVisible() && !UnifiedPopup.IsVisible() && !ConnectPanel.IsVisible() && !Feedback.IsVisible() && !PlayerCustomizaton.IsBarberGuiVisible() && !ZInput.VirtualKeyboardOpen && !Game.IsPaused() && (!((Object)(object)TextViewer.instance != (Object)null) || !TextViewer.instance.IsVisible())) { if ((Object)(object)Chat.instance != (Object)null) { if (!Chat.instance.HasFocus()) { return Chat.instance.IsChatDialogWindowVisible(); } return true; } return false; } return true; } private void OnGUI() { //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_004e: Invalid comparison between Unknown and I4 if (_settings == null || _failed || !_ready || !_settings.Enabled.Value || !_settings.Visible.Value || Event.current == null || (int)Event.current.type != 7) { return; } try { if (HasWorld() && _player == Player.m_localPlayer && _environment == EnvMan.instance && _network == ZNet.instance && !Hud.instance.m_userHidden && Hud.instance.IsVisible() && (!((Object)(object)Hud.instance.m_loadingScreen != (Object)null) || !((Component)Hud.instance.m_loadingScreen).gameObject.activeInHierarchy) && (!_settings.HideInMenus.Value || !InputBlocked())) { _view.Draw(); } } catch (Exception error) { Fail(error); } } private void Fail(Exception error) { _failed = true; _ready = false; ((BaseUnityPlugin)this).Logger.LogError((object)("RunicClock stopped its overlay after an error; gameplay is unchanged. " + error)); } private void OnDestroy() { if (_settings != null) { ((BaseUnityPlugin)this).Config.SettingChanged -= SettingsChanged; } _view?.Dispose(); _view = null; _ready = false; _player = null; _environment = null; _network = null; } } }