Decompiled source of Its Late Somewhere v1.0.0

Its_Late_Somewhere.dll

Decompiled 12 hours ago
using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading;
using BepInEx;
using BepInEx.Configuration;
using Steamworks;
using TMPro;
using UnityEngine;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: AssemblyVersion("0.0.0.0")]
namespace ItsLateSomewhere;

[BepInPlugin("cn.ontogether.itslatesomewhere", "It's Late Somewhere", "1.0.0")]
public sealed class ItsLateSomewherePlugin : BaseUnityPlugin
{
	private sealed class Label
	{
		public GameObject Root;

		public TextMeshProUGUI Text;

		public Image Icon;

		public string Shown;
	}

	private struct Resolved
	{
		public bool Valid;

		public int OffsetMinutes;

		public bool Estimated;
	}

	public const string PluginVersion = "1.0.0";

	private const string LobbyKey = "ot_localtime_offset";

	private const float TickInterval = 0.5f;

	private const float PublishInterval = 60f;

	private ConfigEntry<bool> _enabled;

	private ConfigEntry<KeyboardShortcut> _toggleKey;

	private ConfigEntry<bool> _use24Hour;

	private ConfigEntry<bool> _showEstimates;

	private ConfigEntry<bool> _showOnSelf;

	private ConfigEntry<bool> _showInPlayerList;

	private ConfigEntry<float> _textScale;

	private ConfigEntry<bool> _shareMyTimezone;

	private ConfigEntry<string> _timezoneOverride;

	private static readonly BindingFlags Private = BindingFlags.Instance | BindingFlags.NonPublic;

	private FieldInfo _pomoTextField;

	private FieldInfo _rowListField;

	private FieldInfo _rowSteamIdField;

	private FieldInfo _rowNameTextField;

	private readonly Dictionary<PlayerController, Label> _heads = new Dictionary<PlayerController, Label>();

	private readonly Dictionary<PlayerItemController, Label> _rows = new Dictionary<PlayerItemController, Label>();

	private readonly Dictionary<string, ZoneGuess> _locationCache = new Dictionary<string, ZoneGuess>();

	private readonly HashSet<string> _loggedResolutions = new HashSet<string>();

	private readonly List<PlayerController> _deadHeads = new List<PlayerController>();

	private readonly List<PlayerItemController> _deadRows = new List<PlayerItemController>();

	private PlayerPanelController _panel;

	private float _nextTick;

	private float _nextPanelSearch;

	private float _nextPublish;

	private ulong _publishedLobby;

	private string _publishedValue;

	private string _localSteamId;

	private bool _visible = true;

	private Sprite _sunSprite;

	private Sprite _moonSprite;

	private static volatile string _stage = "idle";

	private static long _stageSince;

	private static string _watchdogPath;

	private Thread _watchdog;

	private volatile bool _quitting;

	private static void Mark(string stage)
	{
		Interlocked.Exchange(ref _stageSince, DateTime.UtcNow.Ticks);
		_stage = stage;
	}

	private void WatchdogLoop()
	{
		string text = null;
		while (!_quitting)
		{
			Thread.Sleep(500);
			string stage = _stage;
			long num = Interlocked.Read(in _stageSince);
			double num2 = (double)(DateTime.UtcNow.Ticks - num) / 10000000.0;
			string text2 = stage + "@" + num;
			if (stage != "idle" && num2 > 3.0 && text2 != text)
			{
				text = text2;
				try
				{
					File.AppendAllText(_watchdogPath, DateTime.Now.ToString("HH:mm:ss", CultureInfo.InvariantCulture) + " main thread stuck for " + num2.ToString("0.0", CultureInfo.InvariantCulture) + "s in: " + stage + Environment.NewLine);
				}
				catch (Exception)
				{
				}
			}
		}
	}

	private void Awake()
	{
		//IL_003d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0105: Unknown result type (might be due to invalid IL or missing references)
		//IL_010f: Expected O, but got Unknown
		_enabled = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "Enabled", true, "Show other players' local time under their names.");
		_toggleKey = ((BaseUnityPlugin)this).Config.Bind<KeyboardShortcut>("General", "Toggle key", new KeyboardShortcut((KeyCode)284, (KeyCode[])(object)new KeyCode[0]), "Show / hide all clocks.");
		_use24Hour = ((BaseUnityPlugin)this).Config.Bind<bool>("Display", "24-hour clock", true, "false = 12-hour clock with AM/PM.");
		_showEstimates = ((BaseUnityPlugin)this).Config.Bind<bool>("Display", "Show estimates", true, "For players without this mod, guess their time from the Location on their ID card (shown with a ~).");
		_showOnSelf = ((BaseUnityPlugin)this).Config.Bind<bool>("Display", "Show on myself", false, "Also show your own clock above your head.");
		_showInPlayerList = ((BaseUnityPlugin)this).Config.Bind<bool>("Display", "Show in player list", true, "Add the clock next to each name in the player list panel.");
		_textScale = ((BaseUnityPlugin)this).Config.Bind<float>("Display", "Text scale", 0.7f, new ConfigDescription("Clock size relative to the name.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.3f, 1.5f), new object[0]));
		_shareMyTimezone = ((BaseUnityPlugin)this).Config.Bind<bool>("Privacy", "Share my timezone", true, "Publish your UTC offset (just the offset, e.g. +8, never your city) so other players with this mod see your exact time.");
		_timezoneOverride = ((BaseUnityPlugin)this).Config.Bind<string>("Privacy", "Timezone override", "", "Leave empty to use your system timezone. Otherwise e.g. \"+8\", \"-5:30\", \"UTC+9\" or a place such as \"Tokyo\".");
		_pomoTextField = typeof(PlayerController).GetField("_playerPomoTimeText", Private);
		_rowListField = typeof(PlayerPanelController).GetField("_playerItemControllers", Private);
		_rowSteamIdField = typeof(PlayerItemController).GetField("_playerSteamId", Private);
		_rowNameTextField = typeof(PlayerItemController).GetField("_playerNameText", Private);
		if (_rowListField == null || _rowSteamIdField == null || _rowNameTextField == null)
		{
			((BaseUnityPlugin)this).Logger.LogWarning((object)"Player list fields not found - clocks in the player list are disabled.");
		}
		_sunSprite = MakeIcon(sun: true);
		_moonSprite = MakeIcon(sun: false);
		_shareMyTimezone.SettingChanged += delegate
		{
			_nextPublish = 0f;
		};
		_timezoneOverride.SettingChanged += delegate
		{
			_nextPublish = 0f;
		};
		_watchdogPath = Path.Combine(Paths.BepInExRootPath, "ItsLateSomewhere-watchdog.log");
		_watchdog = new Thread(WatchdogLoop);
		_watchdog.IsBackground = true;
		_watchdog.Name = "ItsLateSomewhere watchdog";
		_watchdog.Start();
		((BaseUnityPlugin)this).Logger.LogInfo((object)("It's Late Somewhere 1.0.0 loaded. My offset: " + FormatOffset(LocalOffsetMinutes())));
	}

	private void Update()
	{
		//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 = _toggleKey.Value;
		if (((KeyboardShortcut)(ref value)).IsDown())
		{
			_visible = !_visible;
			_nextTick = 0f;
			((BaseUnityPlugin)this).Logger.LogInfo((object)("Clocks " + (_visible ? "shown" : "hidden")));
		}
		if (Time.unscaledTime < _nextTick)
		{
			return;
		}
		_nextTick = Time.unscaledTime + 0.5f;
		try
		{
			Tick();
		}
		catch (Exception ex)
		{
			((BaseUnityPlugin)this).Logger.LogError((object)("Tick failed at step '" + _stage + "': " + ex));
			_nextTick = Time.unscaledTime + 5f;
		}
		finally
		{
			Mark("idle");
		}
	}

	private void Tick()
	{
		//IL_0168: Unknown result type (might be due to invalid IL or missing references)
		Mark("purge");
		PurgeDestroyed();
		if ((Object)(object)_panel == (Object)null && Time.unscaledTime >= _nextPanelSearch)
		{
			_nextPanelSearch = Time.unscaledTime + 1f;
			Mark("find player panel");
			_panel = Object.FindAnyObjectByType<PlayerPanelController>();
		}
		if ((Object)(object)_panel == (Object)null)
		{
			return;
		}
		Mark("read lobby id");
		ulong num = CurrentLobby();
		Mark("publish offset to lobby " + num);
		Publish(num);
		bool flag = _enabled.Value && _visible;
		DateTime utcNow = DateTime.UtcNow;
		int num2 = Math.Min(_panel.PlayerControllers.Count, Math.Min(_panel.PlayerSteamIDs.Count, _panel.IDInfos.Count));
		for (int i = 0; i < num2; i++)
		{
			PlayerController val = _panel.PlayerControllers[i];
			if (!((Object)(object)val == (Object)null) && !((Object)(object)val.PlayerNameText == (Object)null))
			{
				string text = _panel.PlayerSteamIDs[i];
				Mark("resolve player " + i);
				bool flag2 = text == LocalSteamId();
				Resolved r = Resolve(text, _panel.IDInfos[i], flag2, num, ((TMP_Text)val.PlayerNameText).text);
				bool wanted = flag && r.Valid && (!flag2 || _showOnSelf.Value);
				Mark("head label player " + i);
				UpdateHead(val, wanted, r, utcNow);
			}
		}
		Mark("player list rows");
		UpdateRows(flag && _showInPlayerList.Value, num, utcNow);
	}

	private Resolved Resolve(string steamId, PlayerIDInfo info, bool isSelf, ulong lobby, string nameForLog)
	{
		Resolved result = default(Resolved);
		string text = null;
		int minutes;
		if (isSelf)
		{
			result.Valid = true;
			result.OffsetMinutes = LocalOffsetMinutes();
			text = "self";
		}
		else if (TryReadMemberOffset(lobby, steamId, out minutes))
		{
			result.Valid = true;
			result.OffsetMinutes = minutes;
			text = "lobby data";
		}
		else if (_showEstimates.Value)
		{
			string text2 = Decode(info.Location);
			Mark("guess timezone from location (" + text2.Length + " chars)");
			ZoneGuess zoneGuess = GuessCached(text2);
			if (zoneGuess != null)
			{
				result.Valid = true;
				result.Estimated = true;
				result.OffsetMinutes = zoneGuess.OffsetMinutesAt(DateTime.UtcNow);
				text = "location '" + text2 + "' (" + zoneGuess.Source + ")";
			}
		}
		string item = steamId + "|" + (text ?? "none") + "|" + result.OffsetMinutes;
		if (_loggedResolutions.Add(item))
		{
			((BaseUnityPlugin)this).Logger.LogInfo((object)("Player '" + nameForLog + "': " + (result.Valid ? (FormatOffset(result.OffsetMinutes) + " from " + text) : "no timezone info")));
		}
		return result;
	}

	private ZoneGuess GuessCached(string location)
	{
		if (string.IsNullOrEmpty(location))
		{
			return null;
		}
		if (!_locationCache.TryGetValue(location, out var value))
		{
			value = LocationZones.Guess(location);
			_locationCache[location] = value;
		}
		return value;
	}

	private bool TryReadMemberOffset(ulong lobby, string steamId, out int minutes)
	{
		//IL_0015: Unknown result type (might be due to invalid IL or missing references)
		//IL_001b: Unknown result type (might be due to invalid IL or missing references)
		minutes = 0;
		if (lobby == 0 || !ulong.TryParse(steamId, out var result))
		{
			return false;
		}
		string lobbyMemberData;
		try
		{
			lobbyMemberData = SteamMatchmaking.GetLobbyMemberData(new CSteamID(lobby), new CSteamID(result), "ot_localtime_offset");
		}
		catch (Exception)
		{
			return false;
		}
		if (!string.IsNullOrEmpty(lobbyMemberData) && int.TryParse(lobbyMemberData, NumberStyles.Integer, CultureInfo.InvariantCulture, out minutes) && minutes >= -840)
		{
			return minutes <= 840;
		}
		return false;
	}

	private void Publish(ulong lobby)
	{
		//IL_005c: Unknown result type (might be due to invalid IL or missing references)
		if (lobby == 0)
		{
			_publishedLobby = 0uL;
			return;
		}
		string text = (_shareMyTimezone.Value ? LocalOffsetMinutes().ToString(CultureInfo.InvariantCulture) : "");
		if (lobby == _publishedLobby && text == _publishedValue && Time.unscaledTime < _nextPublish)
		{
			return;
		}
		try
		{
			SteamMatchmaking.SetLobbyMemberData(new CSteamID(lobby), "ot_localtime_offset", text);
			if (lobby != _publishedLobby || text != _publishedValue)
			{
				((BaseUnityPlugin)this).Logger.LogInfo((object)((text.Length > 0) ? ("Shared my offset " + FormatOffset(LocalOffsetMinutes()) + " with lobby " + lobby) : "Not sharing my timezone (Privacy > Share my timezone = false)"));
			}
			_publishedLobby = lobby;
			_publishedValue = text;
		}
		catch (Exception ex)
		{
			((BaseUnityPlugin)this).Logger.LogWarning((object)("Could not write lobby member data: " + ex.Message));
		}
		_nextPublish = Time.unscaledTime + 60f;
	}

	private static ulong CurrentLobby()
	{
		try
		{
			MultiplayerManager i = MonoSingleton<MultiplayerManager>.I;
			if ((Object)(object)i != (Object)null && ulong.TryParse(i.LobbyCode, out var result))
			{
				return result;
			}
		}
		catch (Exception)
		{
		}
		return 0uL;
	}

	private string LocalSteamId()
	{
		//IL_0009: Unknown result type (might be due to invalid IL or missing references)
		if (_localSteamId == null)
		{
			try
			{
				ulong steamID = SteamUser.GetSteamID().m_SteamID;
				_localSteamId = steamID.ToString(CultureInfo.InvariantCulture);
			}
			catch (Exception)
			{
				_localSteamId = "";
			}
		}
		return _localSteamId;
	}

	private int LocalOffsetMinutes()
	{
		string text = (_timezoneOverride.Value ?? "").Trim();
		if (text.Length > 0)
		{
			ZoneGuess zoneGuess = LocationZones.Guess((text[0] == '+' || text[0] == '-') ? ("utc" + text) : text);
			if (zoneGuess != null)
			{
				return zoneGuess.OffsetMinutesAt(DateTime.UtcNow);
			}
		}
		return (int)Math.Round(TimeZoneInfo.Local.GetUtcOffset(DateTime.Now).TotalMinutes);
	}

	private static string Decode(byte[] bytes)
	{
		if (bytes == null || bytes.Length == 0)
		{
			return "";
		}
		try
		{
			return Encoding.Unicode.GetString(bytes).Replace("\0", "").Trim();
		}
		catch (Exception)
		{
			return "";
		}
	}

	private void UpdateHead(PlayerController player, bool wanted, Resolved r, DateTime utcNow)
	{
		//IL_0061: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b0: 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_0176: Unknown result type (might be due to invalid IL or missing references)
		//IL_011b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0120: Unknown result type (might be due to invalid IL or missing references)
		_heads.TryGetValue(player, out var value);
		if (!wanted)
		{
			if (value != null && value.Root.activeSelf)
			{
				value.Root.SetActive(false);
			}
			return;
		}
		TextMeshProUGUI playerNameText = player.PlayerNameText;
		if (value == null)
		{
			value = CreateLabel(playerNameText, ((TMP_Text)playerNameText).transform, "ItsLateSomewhere Head Clock");
			((TMP_Text)value.Text).rectTransform.pivot = new Vector2(0.5f, 1f);
			_heads[player] = value;
		}
		if (!value.Root.activeSelf)
		{
			value.Root.SetActive(true);
		}
		SetClock(value, playerNameText, r, utcNow, withOffset: false);
		Transform parent = value.Root.transform.parent;
		Vector3 val = BottomCenter(playerNameText, parent);
		TextMeshProUGUI val2 = (TextMeshProUGUI)((_pomoTextField != null) ? /*isinst with value type is only supported in some contexts*/: null);
		if ((Object)(object)val2 != (Object)null && ((Component)val2).gameObject.activeInHierarchy && ((Behaviour)val2).enabled && ((TMP_Text)val2).text != null && ((TMP_Text)val2).text.Trim().Length > 0)
		{
			Vector3 val3 = BottomCenter(val2, parent);
			if (val3.y < val.y)
			{
				val.y = val3.y;
			}
		}
		float num = ((TMP_Text)value.Text).fontSize * 0.15f;
		value.Root.transform.localPosition = new Vector3(val.x, val.y - num, val.z);
		PlaceIcon(value);
	}

	private static Vector3 BottomCenter(TextMeshProUGUI text, Transform space)
	{
		//IL_0001: 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)
		//IL_0009: Unknown result type (might be due to invalid IL or missing references)
		//IL_0031: 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_001c: 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_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_0059: 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_0063: Unknown result type (might be due to invalid IL or missing references)
		Bounds textBounds = ((TMP_Text)text).textBounds;
		Vector3 val = default(Vector3);
		if (((Bounds)(ref textBounds)).size.x > 0.001f || ((Bounds)(ref textBounds)).size.y > 0.001f)
		{
			((Vector3)(ref val))..ctor(((Bounds)(ref textBounds)).center.x, ((Bounds)(ref textBounds)).min.y, 0f);
		}
		else
		{
			Rect rect = ((TMP_Text)text).rectTransform.rect;
			((Vector3)(ref val))..ctor(((Rect)(ref rect)).center.x, ((Rect)(ref rect)).yMin, 0f);
		}
		return space.InverseTransformPoint(((TMP_Text)text).transform.TransformPoint(val));
	}

	private void UpdateRows(bool show, ulong lobby, DateTime utcNow)
	{
		//IL_00f6: Unknown result type (might be due to invalid IL or missing references)
		//IL_0189: Unknown result type (might be due to invalid IL or missing references)
		//IL_01db: Unknown result type (might be due to invalid IL or missing references)
		//IL_01e0: Unknown result type (might be due to invalid IL or missing references)
		//IL_01e4: Unknown result type (might be due to invalid IL or missing references)
		//IL_020d: Unknown result type (might be due to invalid IL or missing references)
		//IL_01fb: Unknown result type (might be due to invalid IL or missing references)
		//IL_0200: Unknown result type (might be due to invalid IL or missing references)
		//IL_021b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0249: Unknown result type (might be due to invalid IL or missing references)
		//IL_0232: Unknown result type (might be due to invalid IL or missing references)
		//IL_0237: Unknown result type (might be due to invalid IL or missing references)
		//IL_023b: Unknown result type (might be due to invalid IL or missing references)
		//IL_027d: Unknown result type (might be due to invalid IL or missing references)
		if (_rowListField == null || _rowSteamIdField == null || _rowNameTextField == null || !(_rowListField.GetValue(_panel) is List<PlayerItemController> list))
		{
			return;
		}
		for (int i = 0; i < list.Count; i++)
		{
			PlayerItemController val = list[i];
			if ((Object)(object)val == (Object)null || !((Component)val).gameObject.activeInHierarchy)
			{
				continue;
			}
			object? value = _rowNameTextField.GetValue(val);
			TextMeshProUGUI val2 = (TextMeshProUGUI)((value is TextMeshProUGUI) ? value : null);
			string text = _rowSteamIdField.GetValue(val) as string;
			if ((Object)(object)val2 == (Object)null || string.IsNullOrEmpty(text))
			{
				continue;
			}
			Resolved r = default(Resolved);
			int num = _panel.PlayerSteamIDs.IndexOf(text);
			if (show && num >= 0 && num < _panel.IDInfos.Count)
			{
				r = Resolve(text, _panel.IDInfos[num], text == LocalSteamId(), lobby, ((TMP_Text)val2).text);
			}
			_rows.TryGetValue(val, out var value2);
			if (!show || !r.Valid)
			{
				if (value2 != null && value2.Root.activeSelf)
				{
					value2.Root.SetActive(false);
				}
				continue;
			}
			if (value2 == null)
			{
				value2 = CreateLabel(val2, ((TMP_Text)val2).transform, "ItsLateSomewhere Row Clock");
				((TMP_Text)value2.Text).rectTransform.pivot = new Vector2(0f, 0.5f);
				((TMP_Text)value2.Text).alignment = (TextAlignmentOptions)513;
				_rows[val] = value2;
			}
			if (!value2.Root.activeSelf)
			{
				value2.Root.SetActive(true);
			}
			SetClock(value2, val2, r, utcNow, withOffset: true);
			Bounds textBounds = ((TMP_Text)val2).textBounds;
			float num2;
			if (!(((Bounds)(ref textBounds)).size.x > 0.001f))
			{
				Rect rect = ((TMP_Text)val2).rectTransform.rect;
				num2 = ((Rect)(ref rect)).xMax;
			}
			else
			{
				num2 = ((Bounds)(ref textBounds)).max.x;
			}
			float num3 = num2;
			float y;
			if (!(((Bounds)(ref textBounds)).size.y > 0.001f))
			{
				Rect rect2 = ((TMP_Text)val2).rectTransform.rect;
				y = ((Rect)(ref rect2)).center.y;
			}
			else
			{
				y = ((Bounds)(ref textBounds)).center.y;
			}
			float num4 = y;
			value2.Root.transform.localPosition = new Vector3(num3 + ((TMP_Text)value2.Text).fontSize * 1.6f, num4, 0f);
			PlaceIcon(value2);
		}
	}

	private Label CreateLabel(TextMeshProUGUI template, Transform parent, string objectName)
	{
		//IL_0019: Unknown result type (might be due to invalid IL or missing references)
		//IL_001f: Expected O, but got Unknown
		//IL_006c: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a8: Unknown result type (might be due to invalid IL or missing references)
		//IL_00bd: 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)
		//IL_00d3: Unknown result type (might be due to invalid IL or missing references)
		//IL_00fa: Unknown result type (might be due to invalid IL or missing references)
		//IL_0101: Expected O, but got Unknown
		GameObject val = new GameObject(objectName, new Type[1] { typeof(RectTransform) });
		val.layer = ((Component)template).gameObject.layer;
		val.transform.SetParent(parent, false);
		LayoutElement val2 = val.AddComponent<LayoutElement>();
		val2.ignoreLayout = true;
		TextMeshProUGUI val3 = val.AddComponent<TextMeshProUGUI>();
		((TMP_Text)val3).font = ((TMP_Text)template).font;
		((TMP_Text)val3).fontSharedMaterial = ((TMP_Text)template).fontSharedMaterial;
		((TMP_Text)val3).fontStyle = ((TMP_Text)template).fontStyle;
		((TMP_Text)val3).alignment = (TextAlignmentOptions)258;
		((TMP_Text)val3).overflowMode = (TextOverflowModes)0;
		((Graphic)val3).raycastTarget = false;
		((TMP_Text)val3).richText = false;
		RectTransform rectTransform = ((TMP_Text)val3).rectTransform;
		rectTransform.anchorMin = new Vector2(0.5f, 0.5f);
		rectTransform.anchorMax = new Vector2(0.5f, 0.5f);
		((Transform)rectTransform).localScale = Vector3.one;
		((Transform)rectTransform).localRotation = Quaternion.identity;
		GameObject val4 = new GameObject("Icon", new Type[1] { typeof(RectTransform) });
		val4.layer = val.layer;
		val4.transform.SetParent(val.transform, false);
		Image val5 = val4.AddComponent<Image>();
		((Graphic)val5).raycastTarget = false;
		val5.preserveAspect = true;
		Label label = new Label();
		label.Root = val;
		label.Text = val3;
		label.Icon = val5;
		return label;
	}

	private void SetClock(Label label, TextMeshProUGUI name, Resolved r, DateTime utcNow, bool withOffset)
	{
		//IL_00fc: Unknown result type (might be due to invalid IL or missing references)
		//IL_0101: 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_011f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0174: 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_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)
		DateTime dateTime = utcNow.AddMinutes(r.OffsetMinutes);
		int hour = dateTime.Hour;
		bool flag = hour >= 6 && hour < 18;
		bool flag2 = hour < 6;
		string text = dateTime.ToString(_use24Hour.Value ? "HH:mm" : "h:mm tt", CultureInfo.InvariantCulture);
		string text2 = (r.Estimated ? "~" : "") + text + (withOffset ? ("  " + FormatOffset(r.OffsetMinutes)) : "");
		float num = Mathf.Max(0.001f, ((TMP_Text)name).fontSize * _textScale.Value);
		if (!Mathf.Approximately(((TMP_Text)label.Text).fontSize, num))
		{
			((TMP_Text)label.Text).fontSize = num;
			((TMP_Text)label.Text).rectTransform.sizeDelta = new Vector2(num * 12f, num * 1.4f);
			label.Shown = null;
		}
		Color color = ((Graphic)name).color;
		if (flag2)
		{
			color.a *= 0.55f;
		}
		((Graphic)label.Text).color = color;
		label.Icon.sprite = (flag ? _sunSprite : _moonSprite);
		Color color2 = (flag ? new Color(1f, 0.8f, 0.28f, 1f) : new Color(0.78f, 0.84f, 1f, 1f));
		color2.a = (flag2 ? 0.6f : 1f);
		((Graphic)label.Icon).color = color2;
		if (text2 != label.Shown)
		{
			((TMP_Text)label.Text).text = text2;
			((TMP_Text)label.Text).ForceMeshUpdate(false, false);
			label.Shown = text2;
		}
	}

	private static void PlaceIcon(Label label)
	{
		//IL_0021: Unknown result type (might be due to invalid IL or missing references)
		//IL_0036: 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_0060: Unknown result type (might be due to invalid IL or missing references)
		//IL_0070: 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_0078: Unknown result type (might be due to invalid IL or missing references)
		//IL_0092: 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)
		//IL_00b9: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d6: Unknown result type (might be due to invalid IL or missing references)
		float num = ((TMP_Text)label.Text).fontSize * 1.05f;
		RectTransform rectTransform = ((Graphic)label.Icon).rectTransform;
		rectTransform.sizeDelta = new Vector2(num, num);
		rectTransform.anchorMin = new Vector2(0.5f, 0.5f);
		rectTransform.anchorMax = new Vector2(0.5f, 0.5f);
		rectTransform.pivot = new Vector2(1f, 0.5f);
		Bounds textBounds = ((TMP_Text)label.Text).textBounds;
		float num2 = ((((Bounds)(ref textBounds)).size.x > 0.001f) ? ((Bounds)(ref textBounds)).min.x : 0f);
		float num3 = ((((Bounds)(ref textBounds)).size.y > 0.001f) ? ((Bounds)(ref textBounds)).center.y : 0f);
		((Transform)rectTransform).localPosition = new Vector3(num2 - num * 0.2f, num3, 0f);
	}

	private void PurgeDestroyed()
	{
		_deadHeads.Clear();
		foreach (KeyValuePair<PlayerController, Label> head in _heads)
		{
			if ((Object)(object)head.Key == (Object)null || (Object)(object)head.Value.Root == (Object)null)
			{
				_deadHeads.Add(head.Key);
			}
		}
		for (int i = 0; i < _deadHeads.Count; i++)
		{
			Label label = _heads[_deadHeads[i]];
			if ((Object)(object)label.Root != (Object)null)
			{
				Object.Destroy((Object)(object)label.Root);
			}
			_heads.Remove(_deadHeads[i]);
		}
		_deadRows.Clear();
		foreach (KeyValuePair<PlayerItemController, Label> row in _rows)
		{
			if ((Object)(object)row.Key == (Object)null || (Object)(object)row.Value.Root == (Object)null)
			{
				_deadRows.Add(row.Key);
			}
		}
		for (int j = 0; j < _deadRows.Count; j++)
		{
			Label label2 = _rows[_deadRows[j]];
			if ((Object)(object)label2.Root != (Object)null)
			{
				Object.Destroy((Object)(object)label2.Root);
			}
			_rows.Remove(_deadRows[j]);
		}
	}

	private void OnDestroy()
	{
		_quitting = true;
		foreach (Label value in _heads.Values)
		{
			if ((Object)(object)value.Root != (Object)null)
			{
				Object.Destroy((Object)(object)value.Root);
			}
		}
		foreach (Label value2 in _rows.Values)
		{
			if ((Object)(object)value2.Root != (Object)null)
			{
				Object.Destroy((Object)(object)value2.Root);
			}
		}
	}

	private static string FormatOffset(int minutes)
	{
		string text = ((minutes < 0) ? "-" : "+");
		int num = Math.Abs(minutes);
		int num2 = num / 60;
		int num3 = num % 60;
		return "UTC" + text + num2.ToString(CultureInfo.InvariantCulture) + ((num3 != 0) ? (":" + num3.ToString("00", CultureInfo.InvariantCulture)) : "");
	}

	private static Sprite MakeIcon(bool sun)
	{
		//IL_0006: Unknown result type (might be due to invalid IL or missing references)
		//IL_000c: Expected O, but got Unknown
		//IL_01e7: Unknown result type (might be due to invalid IL or missing references)
		//IL_01f6: Unknown result type (might be due to invalid IL or missing references)
		//IL_01a1: Unknown result type (might be due to invalid IL or missing references)
		//IL_01a6: Unknown result type (might be due to invalid IL or missing references)
		Texture2D val = new Texture2D(64, 64, (TextureFormat)4, false);
		((Object)val).name = (sun ? "ItsLateSomewhere Sun" : "ItsLateSomewhere Moon");
		((Texture)val).wrapMode = (TextureWrapMode)1;
		((Texture)val).filterMode = (FilterMode)1;
		Color32[] array = (Color32[])(object)new Color32[4096];
		for (int i = 0; i < 64; i++)
		{
			for (int j = 0; j < 64; j++)
			{
				float num = (float)j + 0.5f - 32f;
				float num2 = (float)i + 0.5f - 32f;
				float num3 = Mathf.Sqrt(num * num + num2 * num2);
				float num4;
				if (sun)
				{
					num4 = Mathf.Clamp01(14.5f - num3);
					if (num3 > 19f && num3 < 30f)
					{
						float num5 = Mathf.Atan2(num2, num);
						float num6 = (float)Math.PI / 4f;
						float num7 = Mathf.Abs(Mathf.Repeat(num5 + num6 * 0.5f, num6) - num6 * 0.5f);
						float num8 = 3.2f - (num3 - 19f) * 0.12f;
						float num9 = Mathf.Clamp01(num8 - num7 * num3 + 0.5f) * Mathf.Clamp01(30f - num3) * Mathf.Clamp01(num3 - 19f);
						num4 = Mathf.Max(num4, num9);
					}
				}
				else
				{
					float num10 = num - 11f;
					float num11 = num2 - 8f;
					float num12 = Mathf.Sqrt(num10 * num10 + num11 * num11);
					num4 = Mathf.Clamp01(25.5f - num3) * (1f - Mathf.Clamp01(21.5f - num12));
				}
				ref Color32 reference = ref array[i * 64 + j];
				reference = new Color32(byte.MaxValue, byte.MaxValue, byte.MaxValue, (byte)Mathf.RoundToInt(num4 * 255f));
			}
		}
		val.SetPixels32(array);
		val.Apply(false, true);
		return Sprite.Create(val, new Rect(0f, 0f, 64f, 64f), new Vector2(0.5f, 0.5f), 100f);
	}
}
internal enum DstRule
{
	None,
	NorthAmerica,
	Europe,
	Australia,
	NewZealand
}
internal sealed class ZoneGuess
{
	public readonly int StandardMinutes;

	public readonly DstRule Rule;

	public readonly string Source;

	public ZoneGuess(int standardMinutes, DstRule rule, string source)
	{
		StandardMinutes = standardMinutes;
		Rule = rule;
		Source = source;
	}

	public int OffsetMinutesAt(DateTime utc)
	{
		return StandardMinutes + (LocationZones.IsDaylight(Rule, StandardMinutes, utc) ? 60 : 0);
	}
}
internal static class LocationZones
{
	private struct Entry
	{
		public string[] Keywords;

		public string Iso;

		public int Minutes;

		public DstRule Rule;
	}

	private const string AccentFrom = "àáâãäåāăąçćčďèéêëēėęěìíîïīįłñńňòóôõöøōőœŕřśšşßţťùúûüūůűųýÿźżž";

	private const string AccentTo = "aaaaaaaaacccdeeeeeeeeiiiiiilnnnooooooooorrsssstuuuuuuuuuyyzzz";

	private static readonly List<Entry> Entries;

	private static readonly Dictionary<string, int> IsoIndex;

	private static readonly Regex UtcPattern;

	static LocationZones()
	{
		Entries = new List<Entry>();
		IsoIndex = new Dictionary<string, int>();
		UtcPattern = new Regex("(?:utc|gmt)\\s*([+\\-−])\\s*(\\d{1,2})(?:\\s*[:.h]?\\s*(\\d{2}))?", RegexOptions.IgnoreCase);
		Add("cn", 480, DstRule.None, "china", "prc", "mainland", "beijing", "shanghai", "guangzhou", "shenzhen", "chengdu", "chongqing", "hangzhou", "wuhan", "nanjing", "tianjin", "xian", "xi an", "suzhou", "qingdao", "dalian", "xiamen", "harbin", "shenyang", "kunming", "changsha", "zhengzhou", "hefei", "jinan", "fuzhou", "nanning", "guiyang", "lanzhou", "urumqi", "lhasa", "中国", "中國", "大陆", "内地", "北京", "上海", "广州", "廣州", "深圳", "成都", "重庆", "重慶", "杭州", "武汉", "南京", "天津", "西安", "苏州", "青岛", "大连", "厦门", "哈尔滨", "沈阳", "昆明", "长沙", "郑州", "合肥", "济南", "福州", "南宁", "贵阳", "兰州", "南昌", "石家庄", "太原", "呼和浩特", "长春", "海口", "三亚", "宁波", "无锡", "东莞", "佛山", "珠海", "温州", "乌鲁木齐", "拉萨", "银川", "西宁", "四川", "浙江", "江苏", "湖北", "湖南", "广东", "广西", "山东", "山西", "河南", "河北", "福建", "安徽", "江西", "云南", "贵州", "陕西", "甘肃", "辽宁", "吉林", "黑龙江", "东北", "内蒙古", "新疆", "西藏", "宁夏", "青海", "海南");
		Add("hk", 480, DstRule.None, "hong kong", "hongkong", "hk", "hkt", "香港");
		Add("mo", 480, DstRule.None, "macau", "macao", "澳门", "澳門");
		Add("tw", 480, DstRule.None, "taiwan", "taipei", "kaohsiung", "taichung", "tainan", "tw", "台湾", "臺灣", "台灣", "台北", "臺北", "高雄", "台中", "台南");
		Add("jp", 540, DstRule.None, "japan", "tokyo", "osaka", "kyoto", "yokohama", "nagoya", "sapporo", "fukuoka", "kobe", "okinawa", "hokkaido", "jp", "jst", "nihon", "nippon", "日本", "东京", "東京", "大阪", "京都", "横浜", "名古屋", "札幌", "福岡", "沖縄", "北海道", "にほん");
		Add("kr", 540, DstRule.None, "korea", "south korea", "seoul", "busan", "incheon", "daegu", "kr", "kst", "韩国", "韓國", "首尔", "한국", "대한민국", "서울", "부산");
		Add("mn", 480, DstRule.None, "mongolia", "ulaanbaatar", "蒙古");
		Add("sg", 480, DstRule.None, "singapore", "sg", "sgt", "新加坡");
		Add("my", 480, DstRule.None, "malaysia", "kuala lumpur", "penang", "马来西亚", "馬來西亞");
		Add("ph", 480, DstRule.None, "philippines", "manila", "cebu", "ph", "pinas", "菲律宾");
		Add("id", 420, DstRule.None, "indonesia", "jakarta", "bandung", "surabaya", "印尼", "印度尼西亚");
		Add(null, 480, DstRule.None, "bali");
		Add("th", 420, DstRule.None, "thailand", "bangkok", "phuket", "chiang mai", "泰国", "泰國");
		Add("vn", 420, DstRule.None, "vietnam", "viet nam", "hanoi", "ha noi", "saigon", "ho chi minh", "vn", "越南");
		Add("kh", 420, DstRule.None, "cambodia", "phnom penh", "柬埔寨");
		Add("mm", 390, DstRule.None, "myanmar", "burma", "yangon", "缅甸");
		Add("in", 330, DstRule.None, "india", "delhi", "new delhi", "mumbai", "bombay", "bangalore", "bengaluru", "chennai", "kolkata", "hyderabad", "pune", "ist", "印度");
		Add("pk", 300, DstRule.None, "pakistan", "karachi", "lahore", "islamabad", "巴基斯坦");
		Add("bd", 360, DstRule.None, "bangladesh", "dhaka", "孟加拉");
		Add("np", 345, DstRule.None, "nepal", "kathmandu", "尼泊尔");
		Add("lk", 330, DstRule.None, "sri lanka", "colombo", "斯里兰卡");
		Add("au", 600, DstRule.Australia, "australia", "aussie", "sydney", "melbourne", "canberra", "nsw", "new south wales", "victoria", "tasmania", "hobart", "aest", "澳大利亚", "澳洲", "悉尼", "墨尔本");
		Add(null, 600, DstRule.None, "brisbane", "queensland", "gold coast");
		Add(null, 480, DstRule.None, "perth", "western australia");
		Add(null, 570, DstRule.Australia, "adelaide", "south australia");
		Add(null, 570, DstRule.None, "darwin");
		Add("nz", 720, DstRule.NewZealand, "new zealand", "aotearoa", "auckland", "wellington", "christchurch", "nz", "新西兰", "紐西蘭");
		Add("ae", 240, DstRule.None, "uae", "united arab emirates", "dubai", "abu dhabi", "迪拜", "阿联酋");
		Add("sa", 180, DstRule.None, "saudi", "saudi arabia", "riyadh", "jeddah", "沙特");
		Add("qa", 180, DstRule.None, "qatar", "doha");
		Add("kw", 180, DstRule.None, "kuwait");
		Add("il", 120, DstRule.Europe, "israel", "tel aviv", "jerusalem", "以色列");
		Add("tr", 180, DstRule.None, "turkey", "turkiye", "türkiye", "istanbul", "ankara", "izmir", "土耳其");
		Add("ir", 210, DstRule.None, "iran", "tehran", "伊朗");
		Add("kz", 300, DstRule.None, "kazakhstan", "almaty", "astana", "哈萨克斯坦");
		Add("uz", 300, DstRule.None, "uzbekistan", "tashkent");
		Add("eg", 120, DstRule.None, "egypt", "cairo", "埃及");
		Add("gb", 0, DstRule.Europe, "uk", "united kingdom", "england", "britain", "great britain", "scotland", "wales", "northern ireland", "london", "manchester", "birmingham", "liverpool", "edinburgh", "glasgow", "leeds", "bristol", "cardiff", "belfast", "gmt", "bst", "英国", "英國", "伦敦", "倫敦");
		Add("ie", 0, DstRule.Europe, "ireland", "dublin", "爱尔兰");
		Add("pt", 0, DstRule.Europe, "portugal", "lisbon", "lisboa", "porto", "葡萄牙");
		Add("is", 0, DstRule.None, "iceland", "reykjavik", "冰岛");
		Add("fr", 60, DstRule.Europe, "france", "paris", "lyon", "marseille", "toulouse", "法国", "法國", "巴黎");
		Add("de", 60, DstRule.Europe, "germany", "deutschland", "berlin", "munich", "münchen", "munchen", "hamburg", "frankfurt", "cologne", "köln", "koln", "stuttgart", "德国", "德國", "柏林");
		Add("es", 60, DstRule.Europe, "spain", "españa", "espana", "madrid", "barcelona", "valencia", "seville", "sevilla", "西班牙");
		Add("it", 60, DstRule.Europe, "italy", "italia", "rome", "roma", "milan", "milano", "naples", "napoli", "turin", "torino", "florence", "firenze", "venice", "意大利", "義大利");
		Add("nl", 60, DstRule.Europe, "netherlands", "holland", "nederland", "amsterdam", "rotterdam", "the hague", "utrecht", "荷兰");
		Add("be", 60, DstRule.Europe, "belgium", "belgique", "belgie", "brussels", "antwerp", "比利时");
		Add("ch", 60, DstRule.Europe, "switzerland", "schweiz", "suisse", "zurich", "zürich", "geneva", "genève", "bern", "瑞士");
		Add("at", 60, DstRule.Europe, "austria", "österreich", "osterreich", "vienna", "wien", "奥地利");
		Add("se", 60, DstRule.Europe, "sweden", "sverige", "stockholm", "gothenburg", "瑞典");
		Add("no", 60, DstRule.Europe, "norway", "norge", "oslo", "挪威");
		Add("dk", 60, DstRule.Europe, "denmark", "danmark", "copenhagen", "丹麦");
		Add("pl", 60, DstRule.Europe, "poland", "polska", "warsaw", "warszawa", "krakow", "kraków", "波兰");
		Add("cz", 60, DstRule.Europe, "czech", "czechia", "czech republic", "prague", "praha", "捷克");
		Add("hu", 60, DstRule.Europe, "hungary", "budapest", "匈牙利");
		Add("hr", 60, DstRule.Europe, "croatia", "zagreb");
		Add("rs", 60, DstRule.Europe, "serbia", "belgrade");
		Add(null, 60, DstRule.Europe, "cet", "cest");
		Add("fi", 120, DstRule.Europe, "finland", "suomi", "helsinki", "芬兰");
		Add("gr", 120, DstRule.Europe, "greece", "athens", "希腊");
		Add("ro", 120, DstRule.Europe, "romania", "bucharest", "罗马尼亚");
		Add("bg", 120, DstRule.Europe, "bulgaria", "sofia");
		Add("ua", 120, DstRule.Europe, "ukraine", "kyiv", "kiev", "kharkiv", "odesa", "odessa", "乌克兰");
		Add("ee", 120, DstRule.Europe, "estonia", "tallinn");
		Add("lv", 120, DstRule.Europe, "latvia", "riga");
		Add("lt", 120, DstRule.Europe, "lithuania", "vilnius");
		Add("by", 180, DstRule.None, "belarus", "minsk");
		Add("ru", 180, DstRule.None, "russia", "moscow", "saint petersburg", "st petersburg", "россия", "москва", "俄罗斯", "俄羅斯", "莫斯科");
		Add(null, 420, DstRule.None, "novosibirsk");
		Add(null, 600, DstRule.None, "vladivostok");
		Add("za", 120, DstRule.None, "south africa", "johannesburg", "cape town", "durban", "南非");
		Add("ng", 60, DstRule.None, "nigeria", "lagos", "abuja");
		Add("ke", 180, DstRule.None, "kenya", "nairobi");
		Add("ma", 60, DstRule.None, "morocco", "casablanca", "rabat");
		Add("us", -300, DstRule.NorthAmerica, "usa", "us", "united states", "america", "united states of america", "east coast", "new york", "nyc", "ny", "boston", "washington dc", "dc", "philadelphia", "miami", "atlanta", "florida", "georgia", "virginia", "north carolina", "south carolina", "ohio", "michigan", "detroit", "pennsylvania", "new jersey", "massachusetts", "maryland", "connecticut", "est", "edt", "美国", "美國", "纽约", "紐約");
		Add(null, -360, DstRule.NorthAmerica, "chicago", "illinois", "texas", "houston", "dallas", "austin", "san antonio", "minnesota", "wisconsin", "missouri", "tennessee", "nashville", "louisiana", "new orleans", "alabama", "iowa", "kansas", "oklahoma", "芝加哥");
		Add(null, -420, DstRule.NorthAmerica, "colorado", "denver", "utah", "salt lake city", "new mexico", "montana", "idaho", "mst", "mdt");
		Add(null, -420, DstRule.None, "arizona", "phoenix");
		Add(null, -480, DstRule.NorthAmerica, "california", "west coast", "los angeles", "san francisco", "sf", "san diego", "san jose", "seattle", "washington state", "oregon", "portland", "las vegas", "nevada", "pst", "pdt", "加州", "洛杉矶", "洛杉磯", "旧金山", "西雅图");
		Add(null, -540, DstRule.NorthAmerica, "alaska", "anchorage");
		Add(null, -600, DstRule.None, "hawaii", "honolulu", "夏威夷");
		Add("ca", -300, DstRule.NorthAmerica, "canada", "toronto", "ontario", "ottawa", "montreal", "montréal", "quebec", "québec", "加拿大", "多伦多");
		Add(null, -480, DstRule.NorthAmerica, "vancouver", "british columbia", "温哥华");
		Add(null, -420, DstRule.NorthAmerica, "calgary", "edmonton", "alberta");
		Add(null, -360, DstRule.NorthAmerica, "winnipeg", "manitoba");
		Add(null, -240, DstRule.NorthAmerica, "halifax", "nova scotia");
		Add("mx", -360, DstRule.None, "mexico", "méxico", "mexico city", "ciudad de mexico", "cdmx", "guadalajara", "monterrey", "墨西哥");
		Add("br", -180, DstRule.None, "brazil", "brasil", "sao paulo", "são paulo", "rio de janeiro", "rio", "brasilia", "brasília", "巴西");
		Add("ar", -180, DstRule.None, "argentina", "buenos aires", "阿根廷");
		Add("cl", -240, DstRule.None, "chile", "santiago", "智利");
		Add("co", -300, DstRule.None, "colombia", "bogota", "bogotá", "medellin", "哥伦比亚");
		Add("pe", -300, DstRule.None, "peru", "perú", "lima", "秘鲁");
		Add("ve", -240, DstRule.None, "venezuela", "caracas");
		Add("uy", -180, DstRule.None, "uruguay", "montevideo");
		Add("cu", -300, DstRule.NorthAmerica, "cuba", "havana");
		Add("pr", -240, DstRule.None, "puerto rico");
		Add(null, -180, DstRule.None, "south america", "latin america", "latam", "南美");
	}

	private static void Add(string iso, int minutes, DstRule rule, params string[] keywords)
	{
		Entry item = default(Entry);
		item.Keywords = new string[keywords.Length];
		for (int i = 0; i < keywords.Length; i++)
		{
			item.Keywords[i] = Normalize(keywords[i]).Trim();
		}
		item.Iso = iso;
		item.Minutes = minutes;
		item.Rule = rule;
		if (iso != null && !IsoIndex.ContainsKey(iso))
		{
			IsoIndex[iso] = Entries.Count;
		}
		Entries.Add(item);
	}

	public static ZoneGuess Guess(string location)
	{
		if (string.IsNullOrEmpty(location))
		{
			return null;
		}
		Match match = UtcPattern.Match(location);
		if (match.Success)
		{
			int num = int.Parse(match.Groups[2].Value, CultureInfo.InvariantCulture);
			int num2 = (match.Groups[3].Success ? int.Parse(match.Groups[3].Value, CultureInfo.InvariantCulture) : 0);
			if (num <= 14 && num2 < 60)
			{
				int num3 = num * 60 + num2;
				if (match.Groups[1].Value != "+")
				{
					num3 = -num3;
				}
				return new ZoneGuess(num3, DstRule.None, "offset");
			}
		}
		string text = FindFlag(location);
		if (text != null && IsoIndex.TryGetValue(text, out var value))
		{
			return new ZoneGuess(Entries[value].Minutes, Entries[value].Rule, "flag " + text);
		}
		string text2 = " " + Normalize(location) + " ";
		int num4 = 0;
		int num5 = -1;
		string text3 = null;
		for (int i = 0; i < Entries.Count; i++)
		{
			string[] keywords = Entries[i].Keywords;
			int num6 = ((Entries[i].Iso == null) ? 1000 : 0);
			foreach (string text4 in keywords)
			{
				int num7 = num6 + text4.Length;
				if (num7 > num4 && (IsAsciiWord(text4) ? text2.Contains(" " + text4 + " ") : text2.Contains(text4)))
				{
					num4 = num7;
					num5 = i;
					text3 = text4;
				}
			}
		}
		if (num5 < 0)
		{
			return null;
		}
		return new ZoneGuess(Entries[num5].Minutes, Entries[num5].Rule, "keyword '" + text3 + "'");
	}

	private static string Normalize(string s)
	{
		string text = s.ToLowerInvariant();
		StringBuilder stringBuilder = new StringBuilder(text.Length);
		bool flag = false;
		for (int i = 0; i < text.Length; i++)
		{
			char c = text[i];
			int num = ((c > '\u007f') ? "àáâãäåāăąçćčďèéêëēėęěìíîïīįłñńňòóôõöøōőœŕřśšşßţťùúûüūůűųýÿźżž".IndexOf(c) : (-1));
			if (num >= 0)
			{
				c = "aaaaaaaaacccdeeeeeeeeiiiiiilnnnooooooooorrsssstuuuuuuuuuyyzzz"[num];
			}
			if (char.IsLetterOrDigit(c))
			{
				stringBuilder.Append(c);
				flag = false;
			}
			else if (!flag)
			{
				stringBuilder.Append(' ');
				flag = true;
			}
		}
		return stringBuilder.ToString();
	}

	private static bool IsAsciiWord(string s)
	{
		for (int i = 0; i < s.Length; i++)
		{
			if (s[i] > '\u007f')
			{
				return false;
			}
		}
		return true;
	}

	private static string FindFlag(string s)
	{
		for (int i = 0; i + 3 < s.Length; i++)
		{
			if (s[i] == '\ud83c' && s[i + 1] >= '\udde6' && s[i + 1] <= '\uddff' && s[i + 2] == '\ud83c' && s[i + 3] >= '\udde6' && s[i + 3] <= '\uddff')
			{
				char c = (char)(97 + (s[i + 1] - 56806));
				char c2 = (char)(97 + (s[i + 3] - 56806));
				string text = new string(new char[2] { c, c2 });
				if (!(text == "uk"))
				{
					return text;
				}
				return "gb";
			}
		}
		return null;
	}

	public static bool IsDaylight(DstRule rule, int standardMinutes, DateTime utc)
	{
		switch (rule)
		{
		case DstRule.None:
			return false;
		case DstRule.Europe:
		{
			DateTime dateTime2 = LastSunday(utc.Year, 3).AddHours(1.0);
			DateTime dateTime3 = LastSunday(utc.Year, 10).AddHours(1.0);
			if (utc >= dateTime2)
			{
				return utc < dateTime3;
			}
			return false;
		}
		default:
		{
			DateTime dateTime = utc.AddMinutes(standardMinutes);
			int year = dateTime.Year;
			switch (rule)
			{
			case DstRule.NorthAmerica:
				if (dateTime >= NthSunday(year, 3, 2).AddHours(2.0))
				{
					return dateTime < NthSunday(year, 11, 1).AddHours(1.0);
				}
				return false;
			case DstRule.Australia:
				if (dateTime >= NthSunday(year, 4, 1).AddHours(2.0))
				{
					return !(dateTime < NthSunday(year, 10, 1).AddHours(2.0));
				}
				return true;
			case DstRule.NewZealand:
				if (dateTime >= NthSunday(year, 4, 1).AddHours(2.0))
				{
					return !(dateTime < LastSunday(year, 9).AddHours(2.0));
				}
				return true;
			default:
				return false;
			}
		}
		}
	}

	private static DateTime NthSunday(int year, int month, int n)
	{
		DateTime dateTime = new DateTime(year, month, 1);
		int num = (0 - dateTime.DayOfWeek + 7) % 7;
		return dateTime.AddDays(num + 7 * (n - 1));
	}

	private static DateTime LastSunday(int year, int month)
	{
		DateTime dateTime = new DateTime(year, month, DateTime.DaysInMonth(year, month));
		return dateTime.AddDays(0 - dateTime.DayOfWeek);
	}
}