Decompiled source of Odins Almanac v0.1.4

plugins/OdinsAlmanac.dll

Decompiled 17 hours ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Text;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using TMPro;
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("OdinsAlmanac")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("0.1.4.0")]
[assembly: AssemblyInformationalVersion("0.1.4+39d9127df34e7e2ec15cd9e6478eef57292cfc9f")]
[assembly: AssemblyProduct("OdinsAlmanac")]
[assembly: AssemblyTitle("OdinsAlmanac")]
[assembly: AssemblyVersion("0.1.4.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 OdinsAlmanac
{
	internal sealed class Spell
	{
		public EnvSetup Env;

		public double Start;

		public double End = double.NaN;

		public float WindIntensity;

		public float WindFrom;
	}
	internal sealed class ForecastResult
	{
		public string BiomeName;

		public double Now;

		public Spell Current;

		public readonly List<Spell> Upcoming = new List<Spell>();

		public bool Overridden;

		public bool NeverChanges;
	}
	internal static class Forecast
	{
		private const int MaxPeriods = 200;

		private static Func<EnvMan, BiomeSector> _getBiome;

		private static Func<EnvMan, string> _getEnvironmentOverride;

		private static Func<EnvMan, List<EnvEntry>, EnvSetup> _selectWeightedEnvironment;

		private static FieldRef<EnvMan, string> _forceEnv;

		private static readonly List<EnvEntry> Entries = new List<EnvEntry>();

		private static readonly HashSet<string> LoggedBiomes = new HashSet<string>();

		internal static bool Init()
		{
			try
			{
				_getBiome = AccessTools.MethodDelegate<Func<EnvMan, BiomeSector>>(AccessTools.Method(typeof(EnvMan), "GetBiome", (Type[])null, (Type[])null), (object)null, true);
				_getEnvironmentOverride = AccessTools.MethodDelegate<Func<EnvMan, string>>(AccessTools.Method(typeof(EnvMan), "GetEnvironmentOverride", (Type[])null, (Type[])null), (object)null, true);
				_selectWeightedEnvironment = AccessTools.MethodDelegate<Func<EnvMan, List<EnvEntry>, EnvSetup>>(AccessTools.Method(typeof(EnvMan), "SelectWeightedEnvironment", (Type[])null, (Type[])null), (object)null, true);
				_forceEnv = AccessTools.FieldRefAccess<EnvMan, string>("m_forceEnv");
				return true;
			}
			catch (Exception ex)
			{
				Plugin.Log.LogError((object)("Couldn't find Valheim's weather code; a game update may have changed it. The almanac is closed. (" + ex.Message + ")"));
				return false;
			}
		}

		internal static ForecastResult Compute()
		{
			//IL_00ff: Unknown result type (might be due to invalid IL or missing references)
			//IL_0104: Unknown result type (might be due to invalid IL or missing references)
			//IL_0106: Unknown result type (might be due to invalid IL or missing references)
			//IL_010d: 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_0122: Unknown result type (might be due to invalid IL or missing references)
			EnvMan instance = EnvMan.instance;
			Camera mainCamera = Utils.GetMainCamera();
			if ((Object)(object)instance == (Object)null || (Object)(object)mainCamera == (Object)null || (Object)(object)ZNet.instance == (Object)null || WorldGenerator.instance == null)
			{
				return null;
			}
			long environmentDuration = instance.m_environmentDuration;
			if (environmentDuration <= 0)
			{
				return null;
			}
			double timeSeconds = ZNet.instance.GetTimeSeconds();
			BiomeSector val = _getBiome(instance);
			ForecastResult forecastResult = new ForecastResult
			{
				BiomeName = val.GetName(false),
				Now = timeSeconds
			};
			if (!string.IsNullOrEmpty(_forceEnv.Invoke(instance)) || !string.IsNullOrEmpty(_getEnvironmentOverride(instance)))
			{
				forecastResult.Overridden = true;
				forecastResult.Current = MakeSpell(instance, instance.GetCurrentEnvironment(), timeSeconds, timeSeconds);
				return forecastResult;
			}
			Entries.Clear();
			List<EnvEntry> availableEnvironments = instance.GetAvailableEnvironments(val);
			if (availableEnvironments != null)
			{
				Entries.AddRange(availableEnvironments);
			}
			if (Entries.Count == 0)
			{
				return null;
			}
			LogBiomeOnce(forecastResult.BiomeName);
			Vector3 position = ((Component)mainCamera).transform.position;
			bool ashlands = WorldGenerator.IsAshlands(position.x, position.z);
			bool deepNorth = WorldGenerator.IsDeepnorth(position.x, position.y);
			long num = (long)timeSeconds / environmentDuration;
			EnvSetup val2 = Pick(instance, num, ashlands, deepNorth);
			if (val2 == null)
			{
				return null;
			}
			forecastResult.Current = MakeSpell(instance, val2, timeSeconds, timeSeconds);
			int value = Plugin.ForecastCount.Value;
			Spell spell = forecastResult.Current;
			for (long num2 = num + 1; num2 <= num + 200; num2++)
			{
				EnvSetup val3 = Pick(instance, num2, ashlands, deepNorth);
				if (val3 != null && !(val3.m_name == spell.Env.m_name))
				{
					double num3 = (spell.End = (double)num2 * (double)environmentDuration);
					if (forecastResult.Upcoming.Count == value)
					{
						break;
					}
					spell = MakeSpell(instance, val3, num3, num3);
					forecastResult.Upcoming.Add(spell);
				}
			}
			forecastResult.NeverChanges = forecastResult.Upcoming.Count == 0 && UniqueWeathers() <= 1;
			return forecastResult;
		}

		private static EnvSetup Pick(EnvMan env, long period, bool ashlands, bool deepNorth)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0005: 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)
			State state = Random.state;
			try
			{
				Random.InitState((int)period);
				EnvSetup result = _selectWeightedEnvironment(env, Entries);
				foreach (EnvEntry entry in Entries)
				{
					if (entry.m_ashlandsOverride && ashlands)
					{
						result = entry.m_env;
					}
					if (entry.m_deepnorthOverride && deepNorth)
					{
						result = entry.m_env;
					}
				}
				return result;
			}
			finally
			{
				Random.state = state;
			}
		}

		private static Spell MakeSpell(EnvMan env, EnvSetup setup, double start, double windAt)
		{
			Spell spell = new Spell
			{
				Env = setup,
				Start = start
			};
			if (setup != null)
			{
				Wind(env, setup, (long)windAt, out spell.WindIntensity, out spell.WindFrom);
			}
			return spell;
		}

		private static void Wind(EnvMan env, EnvSetup setup, long timeSec, out float intensity, out float fromBearing)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_0082: Unknown result type (might be due to invalid IL or missing references)
			State state = Random.state;
			float num = 0f;
			float num2 = 0.5f;
			try
			{
				int[] array = new int[4] { 1, 2, 4, 8 };
				foreach (int num3 in array)
				{
					long num4 = env.m_windPeriodDuration / num3;
					if (num4 > 0)
					{
						Random.InitState((int)(timeSec / num4));
						num += Random.value * ((float)Math.PI * 2f / (float)num3);
						num2 += -0.5f / (float)num3 + Random.value / (float)num3;
					}
				}
			}
			finally
			{
				Random.state = state;
			}
			intensity = Mathf.Clamp(Mathf.Lerp(setup.m_windMin, setup.m_windMax, num2), 0.05f, 1f);
			fromBearing = Mathf.Repeat(num * 57.29578f + 180f, 360f);
		}

		private static int UniqueWeathers()
		{
			HashSet<string> hashSet = new HashSet<string>();
			foreach (EnvEntry entry in Entries)
			{
				if (entry.m_env != null)
				{
					hashSet.Add(entry.m_env.m_name);
				}
			}
			return hashSet.Count;
		}

		private static void LogBiomeOnce(string biome)
		{
			if (!LoggedBiomes.Add(biome))
			{
				return;
			}
			List<string> list = new List<string>();
			foreach (EnvEntry entry in Entries)
			{
				list.Add(((object)entry).ToString());
			}
			Plugin.Log.LogInfo((object)(biome + " weather: " + string.Join(", ", list)));
		}
	}
	internal static class ForecastText
	{
		private enum Kind
		{
			Clear,
			Mist,
			Gloom,
			Rain,
			Storm,
			Snow,
			Ash
		}

		private const string Value = "orange";

		private const string FlavorColor = "#B9B3A8";

		private const string NoteColor = "#B0B0B0";

		private static readonly StringBuilder Sb = new StringBuilder();

		private static readonly Dictionary<string, string> Names = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase)
		{
			["Clear"] = "Clear",
			["Twilight_Clear"] = "Clear twilight",
			["Heath clear"] = "Clear",
			["Misty"] = "Mist",
			["DeepForest Mist"] = "Forest mist",
			["Darklands_dark"] = "Gloom",
			["Rain"] = "Rain",
			["LightRain"] = "Light rain",
			["ThunderStorm"] = "Thunderstorm",
			["SwampRain"] = "Swamp rain",
			["Snow"] = "Snow",
			["SnowStorm"] = "Snowstorm",
			["Twilight_Snow"] = "Twilight snow",
			["Twilight_SnowStorm"] = "Twilight snowstorm",
			["Mistlands_clear"] = "Clear above the mist",
			["Mistlands_rain"] = "Rain over the mist",
			["Mistlands_thunder"] = "Thunder over the mist",
			["Ashlands_ashrain"] = "Ash rain",
			["Ashlands_misty"] = "Ash haze",
			["Ashlands_storm"] = "Ash storm",
			["Ashlands_CinderRain"] = "Cinder rain",
			["Ashlands_SeaStorm"] = "Sea storm"
		};

		private static readonly Dictionary<Kind, string[]> Remarks = new Dictionary<Kind, string[]>
		{
			[Kind.Clear] = new string[2] { "Fair skies. Get the boat out.", "Good drying weather. For hides, and for you." },
			[Kind.Mist] = new string[2] { "Can't see your own boots. Sail slowly, or not at all.", "Fog. Everything sounds closer than it is." },
			[Kind.Gloom] = new string[2] { "Gloomy. The trees like it. You won't.", "Dark at noon. Bring a torch and a friend." },
			[Kind.Rain] = new string[2] { "Wet. The mead is dry, though.", "Rain on the way. Fires out, cloaks on." },
			[Kind.Storm] = new string[2] { "Stay in port. The sea is in a mood.", "Thunder means Thor's drinking again. Stay in." },
			[Kind.Snow] = new string[2] { "Cold enough to freeze the mead. Dress for it.", "Snow coming. Wear the fur, not the face." },
			[Kind.Ash] = new string[2] { "Ash in your beard, fire in your boots.", "Hot, grey and angry. Like Odin before breakfast." }
		};

		private static readonly string[] Points = new string[8] { "north", "north-east", "east", "south-east", "south", "south-west", "west", "north-west" };

		internal static string Title(ForecastResult f)
		{
			return f.BiomeName + " forecast";
		}

		internal static string Body(ForecastResult f)
		{
			Sb.Clear();
			if (Plugin.ShowFlavor.Value)
			{
				Sb.Append("<i><color=").Append("#B9B3A8").Append('>')
					.Append(Remark(f))
					.Append("</color></i>\n\n");
			}
			AppendSpell("Now", f.Current, null);
			if (f.Overridden)
			{
				Sb.Append("\n<color=").Append("#B0B0B0").Append(">Something other than the sky is setting the weather here. No forecast until you leave it.</color>");
				return Sb.ToString();
			}
			if (f.Upcoming.Count == 0)
			{
				Sb.Append("\n<color=").Append("#B0B0B0").Append('>')
					.Append(f.NeverChanges ? "The weather here never changes." : "No change in sight.")
					.Append("</color>");
				return Sb.ToString();
			}
			for (int i = 0; i < f.Upcoming.Count; i++)
			{
				Sb.Append('\n');
				AppendSpell((i == 0) ? "Next" : "Then", f.Upcoming[i], Duration(f.Upcoming[i].Start - f.Now));
			}
			Sb.Append("\n<color=").Append("#B0B0B0").Append(">For this biome. The weather changes with it if you travel.</color>");
			return Sb.ToString();
		}

		private static void AppendSpell(string label, Spell s, string arrivesIn)
		{
			Sb.Append(label).Append(": <color=").Append("orange")
				.Append('>')
				.Append(Name(s.Env))
				.Append("</color>");
			if (arrivesIn != null)
			{
				Sb.Append(" in ").Append(arrivesIn);
			}
			if (label != "Now" && !double.IsNaN(s.End))
			{
				Sb.Append(", for ").Append(Duration(s.End - s.Start));
			}
			Sb.Append('\n');
			if (Plugin.ShowWind.Value && s.Env != null)
			{
				Sb.Append("  Wind: <color=").Append("orange").Append('>')
					.Append(WindWord(s.WindIntensity))
					.Append(", from the ")
					.Append(Compass(s.WindFrom))
					.Append("</color>\n");
			}
		}

		internal static string Name(EnvSetup env)
		{
			if (env == null)
			{
				return "Unknown";
			}
			if (Names.TryGetValue(env.m_name, out var value))
			{
				return value;
			}
			return Tidy(env.m_name);
		}

		private static string Tidy(string raw)
		{
			StringBuilder stringBuilder = new StringBuilder();
			for (int i = 0; i < raw.Length; i++)
			{
				char c = raw[i];
				if (c == '_' || c == '-')
				{
					c = ' ';
				}
				else if (char.IsUpper(c) && i > 0 && char.IsLower(raw[i - 1]))
				{
					stringBuilder.Append(' ');
				}
				stringBuilder.Append((stringBuilder.Length == 0) ? char.ToUpperInvariant(c) : char.ToLowerInvariant(c));
			}
			return stringBuilder.ToString().Replace("  ", " ").Trim();
		}

		private static string Remark(ForecastResult f)
		{
			if (f.Overridden)
			{
				return "This sky isn't the weather's doing. Odin won't guess.";
			}
			if (f.NeverChanges)
			{
				return "Same sky as always. Settle in.";
			}
			Spell spell = ((f.Upcoming.Count > 0) ? f.Upcoming[0] : f.Current);
			string[] array = Remarks[KindOf(spell.Env)];
			int num = (int)(Math.Abs((long)spell.Start) / 60 % array.Length);
			return array[num];
		}

		private static Kind KindOf(EnvSetup env)
		{
			if (env == null)
			{
				return Kind.Clear;
			}
			string text = env.m_name.ToLowerInvariant();
			if (text.Contains("ash") || text.Contains("cinder"))
			{
				return Kind.Ash;
			}
			if (text.Contains("storm") || text.Contains("thunder"))
			{
				return Kind.Storm;
			}
			if (text.Contains("snow") || env.m_isFreezing)
			{
				return Kind.Snow;
			}
			if (text.Contains("rain") || env.m_isWet)
			{
				return Kind.Rain;
			}
			if (text.Contains("mist") || text.Contains("fog"))
			{
				return Kind.Mist;
			}
			if (text.Contains("dark") || env.m_alwaysDark)
			{
				return Kind.Gloom;
			}
			return Kind.Clear;
		}

		internal static string Duration(double seconds)
		{
			if (seconds < 60.0)
			{
				return "under a minute";
			}
			int num = Mathf.RoundToInt((float)(seconds / 60.0));
			if (num < 60)
			{
				return $"{num} min";
			}
			if (num % 60 != 0)
			{
				return $"{num / 60} h {num % 60} min";
			}
			return $"{num / 60} h";
		}

		private static string WindWord(float intensity)
		{
			if (intensity < 0.2f)
			{
				return "calm";
			}
			if (intensity < 0.4f)
			{
				return "light";
			}
			if (intensity < 0.6f)
			{
				return "fresh";
			}
			if (intensity < 0.8f)
			{
				return "strong";
			}
			return "gale";
		}

		private static string Compass(float bearing)
		{
			return Points[Mathf.RoundToInt(bearing / 45f) % 8];
		}
	}
	internal class ForecastTooltip : MonoBehaviour
	{
		private const float RefreshInterval = 0.5f;

		private GameObject _tooltip;

		private RectTransform _panel;

		private TMP_Text _topic;

		private TMP_Text _text;

		private readonly Vector3[] _corners = (Vector3[])(object)new Vector3[4];

		private CanvasGroup _group;

		private float _shownAt;

		private float _fadeOutStart = -1f;

		private float _fadeOutLength;

		private float _nextRefresh;

		private void LateUpdate()
		{
			bool num = CanShow();
			if (num && ShowKeyDown())
			{
				if (IsOpen() && !IsFading())
				{
					Close();
				}
				else
				{
					Open();
				}
			}
			if (!num || !IsOpen())
			{
				Hide();
			}
			else
			{
				if ((Object)(object)_tooltip == (Object)null && !CreateTooltip())
				{
					return;
				}
				if (Time.time >= _nextRefresh)
				{
					_nextRefresh = Time.time + 0.5f;
					ForecastResult forecastResult = Forecast.Compute();
					if (forecastResult == null)
					{
						Hide();
						return;
					}
					_topic.text = ForecastText.Title(forecastResult);
					_text.text = ForecastText.Body(forecastResult);
					LayoutRebuilder.ForceRebuildLayoutImmediate(_panel);
				}
				if (!_tooltip.activeSelf)
				{
					_tooltip.SetActive(true);
					_tooltip.transform.SetAsLastSibling();
				}
				_group.alpha = Alpha();
				Place();
			}
		}

		private void OnDestroy()
		{
			if ((Object)(object)_tooltip != (Object)null)
			{
				Object.Destroy((Object)(object)_tooltip);
			}
		}

		private bool IsOpen()
		{
			return Time.time < _fadeOutStart + _fadeOutLength;
		}

		private bool IsFading()
		{
			return Time.time >= _fadeOutStart;
		}

		private void Open()
		{
			float num = (IsOpen() ? Alpha() : 0f);
			_shownAt = Time.time - num * Plugin.FadeInSeconds.Value;
			_fadeOutStart = Time.time + Plugin.ShowSeconds.Value;
			_fadeOutLength = Plugin.FadeOutSeconds.Value;
			_nextRefresh = 0f;
		}

		private void Close()
		{
			_fadeOutStart = Time.time;
			_fadeOutLength = Plugin.FadeInSeconds.Value;
		}

		private float Alpha()
		{
			float value = Plugin.FadeInSeconds.Value;
			float num = ((value > 0f) ? Mathf.Clamp01((Time.time - _shownAt) / value) : 1f);
			float num2 = ((_fadeOutLength > 0f) ? Mathf.Clamp01((Time.time - _fadeOutStart) / _fadeOutLength) : (IsFading() ? 1f : 0f));
			return num * (1f - num2);
		}

		private static bool CanShow()
		{
			Player localPlayer = Player.m_localPlayer;
			if ((Object)(object)localPlayer == (Object)null || ((Character)localPlayer).IsDead() || !HudVisible())
			{
				return false;
			}
			if (!InventoryGui.IsVisible() && !Menu.IsVisible() && !Minimap.IsOpen() && !TextInput.IsVisible() && !Console.IsVisible())
			{
				if ((Object)(object)Chat.instance != (Object)null)
				{
					return !Chat.instance.HasFocus();
				}
				return true;
			}
			return false;
		}

		private static bool HudVisible()
		{
			if ((Object)(object)Hud.instance != (Object)null && !Hud.IsUserHidden())
			{
				return Hud.instance.IsVisible();
			}
			return false;
		}

		private static bool ShowKeyDown()
		{
			//IL_0005: 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_000d: 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_0035: Unknown result type (might be due to invalid IL or missing references)
			KeyboardShortcut value = Plugin.ShowKey.Value;
			if ((int)((KeyboardShortcut)(ref value)).MainKey == 0 || !ZInput.GetKeyDown(((KeyboardShortcut)(ref value)).MainKey, false))
			{
				return false;
			}
			foreach (KeyCode modifier in ((KeyboardShortcut)(ref value)).Modifiers)
			{
				if (!ZInput.GetKey(modifier, false))
				{
					return false;
				}
			}
			return true;
		}

		private void Place()
		{
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_0057: Unknown result type (might be due to invalid IL or missing references)
			//IL_0063: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: 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_0077: 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_0089: Unknown result type (might be due to invalid IL or missing references)
			//IL_008e: Unknown result type (might be due to invalid IL or missing references)
			//IL_008f: 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_0095: Unknown result type (might be due to invalid IL or missing references)
			//IL_009a: Unknown result type (might be due to invalid IL or missing references)
			Vector2 val = default(Vector2);
			((Vector2)(ref val))..ctor(Plugin.PositionX.Value * (float)Screen.width, Plugin.PositionY.Value * (float)Screen.height);
			_tooltip.transform.position = Vector2.op_Implicit(val);
			_panel.GetWorldCorners(_corners);
			Vector2 val2 = Vector2.op_Implicit((_corners[0] + _corners[2]) / 2f);
			Transform transform = _tooltip.transform;
			transform.position += Vector2.op_Implicit(val - val2);
			Utils.ClampUIToScreen(_panel);
		}

		private bool CreateTooltip()
		{
			GameObject val = FindTooltipPrefab();
			if ((Object)(object)val == (Object)null)
			{
				return false;
			}
			Canvas componentInParent = ((Component)InventoryGui.instance).GetComponentInParent<Canvas>();
			Canvas val2 = ((componentInParent != null) ? componentInParent.rootCanvas : null);
			if ((Object)(object)val2 == (Object)null)
			{
				return false;
			}
			_tooltip = Object.Instantiate<GameObject>(val, ((Component)val2).transform);
			((Object)_tooltip).name = "OdinsAlmanac";
			ref RectTransform panel = ref _panel;
			Transform child = _tooltip.transform.GetChild(0);
			panel = (RectTransform)(object)((child is RectTransform) ? child : null);
			Transform obj = Utils.FindChild(_tooltip.transform, "Topic", (IterativeSearchType)0);
			_topic = ((obj != null) ? ((Component)obj).GetComponent<TMP_Text>() : null);
			Transform obj2 = Utils.FindChild(_tooltip.transform, "Text", (IterativeSearchType)0);
			_text = ((obj2 != null) ? ((Component)obj2).GetComponent<TMP_Text>() : null);
			if ((Object)(object)_panel == (Object)null || (Object)(object)_topic == (Object)null || (Object)(object)_text == (Object)null)
			{
				Object.Destroy((Object)(object)_tooltip);
				_tooltip = null;
				return false;
			}
			Graphic[] componentsInChildren = _tooltip.GetComponentsInChildren<Graphic>(true);
			for (int i = 0; i < componentsInChildren.Length; i++)
			{
				componentsInChildren[i].raycastTarget = false;
			}
			_group = _tooltip.GetComponent<CanvasGroup>();
			if ((Object)(object)_group == (Object)null)
			{
				_group = _tooltip.AddComponent<CanvasGroup>();
			}
			_group.interactable = false;
			_group.blocksRaycasts = false;
			_group.alpha = 0f;
			return true;
		}

		private static GameObject FindTooltipPrefab()
		{
			InventoryGui instance = InventoryGui.instance;
			if ((Object)(object)instance == (Object)null)
			{
				return null;
			}
			UITooltip val = (((Object)(object)instance.m_playerGrid != (Object)null && (Object)(object)instance.m_playerGrid.m_elementPrefab != (Object)null) ? instance.m_playerGrid.m_elementPrefab.GetComponentInChildren<UITooltip>(true) : null);
			if ((Object)(object)val != (Object)null && (Object)(object)val.m_tooltipPrefab != (Object)null)
			{
				return val.m_tooltipPrefab;
			}
			UITooltip[] componentsInChildren = ((Component)instance).GetComponentsInChildren<UITooltip>(true);
			foreach (UITooltip val2 in componentsInChildren)
			{
				if ((Object)(object)val2.m_tooltipPrefab != (Object)null)
				{
					return val2.m_tooltipPrefab;
				}
			}
			return null;
		}

		private void Hide()
		{
			if ((Object)(object)_tooltip != (Object)null && _tooltip.activeSelf)
			{
				_tooltip.SetActive(false);
			}
		}
	}
	[BepInPlugin("hevyh2o.valheim.odinsalmanac", "Odin's Almanac", "0.1.4")]
	public class Plugin : BaseUnityPlugin
	{
		public const string Guid = "hevyh2o.valheim.odinsalmanac";

		public const string Name = "Odin's Almanac";

		public const string Version = "0.1.4";

		internal static ManualLogSource Log;

		internal static ConfigEntry<KeyboardShortcut> ShowKey;

		internal static ConfigEntry<float> ShowSeconds;

		internal static ConfigEntry<float> FadeInSeconds;

		internal static ConfigEntry<float> FadeOutSeconds;

		internal static ConfigEntry<float> PositionX;

		internal static ConfigEntry<float> PositionY;

		internal static ConfigEntry<int> ForecastCount;

		internal static ConfigEntry<bool> ShowWind;

		internal static ConfigEntry<bool> ShowFlavor;

		private ForecastTooltip _tooltip;

		private void Awake()
		{
			//IL_0022: 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_006e: Expected O, but got Unknown
			//IL_00a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ab: Expected O, but got Unknown
			//IL_00de: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e8: Expected O, but got Unknown
			//IL_011b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0125: Expected O, but got Unknown
			//IL_0158: Unknown result type (might be due to invalid IL or missing references)
			//IL_0162: Expected O, but got Unknown
			//IL_0189: Unknown result type (might be due to invalid IL or missing references)
			//IL_0193: Expected O, but got Unknown
			Log = ((BaseUnityPlugin)this).Logger;
			ShowKey = ((BaseUnityPlugin)this).Config.Bind<KeyboardShortcut>("Display", "ShowKey", new KeyboardShortcut((KeyCode)107, Array.Empty<KeyCode>()), "Key that opens the almanac. Press again to close it early, or while it's fading to bring it back.");
			ShowSeconds = ((BaseUnityPlugin)this).Config.Bind<float>("Display", "ShowSeconds", 15f, new ConfigDescription("How long the forecast stays fully visible after pressing ShowKey, before it starts to fade.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(2f, 60f), Array.Empty<object>()));
			FadeInSeconds = ((BaseUnityPlugin)this).Config.Bind<float>("Display", "FadeInSeconds", 0.3f, new ConfigDescription("How long the forecast takes to fade in. Also used when closing it with ShowKey. 0 = instant.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 2f), Array.Empty<object>()));
			FadeOutSeconds = ((BaseUnityPlugin)this).Config.Bind<float>("Display", "FadeOutSeconds", 5f, new ConfigDescription("How long the forecast takes to fade away once ShowSeconds is up. 0 = vanish at once.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 30f), Array.Empty<object>()));
			PositionX = ((BaseUnityPlugin)this).Config.Bind<float>("Display", "PositionX", 0.5f, new ConfigDescription("Horizontal position of the forecast, 0 = left edge, 1 = right edge.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1f), Array.Empty<object>()));
			PositionY = ((BaseUnityPlugin)this).Config.Bind<float>("Display", "PositionY", 0.72f, new ConfigDescription("Vertical position of the forecast, 0 = bottom, 1 = top.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1f), Array.Empty<object>()));
			ForecastCount = ((BaseUnityPlugin)this).Config.Bind<int>("General", "ForecastCount", 2, new ConfigDescription("How many upcoming weather changes to show.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 3), Array.Empty<object>()));
			ShowWind = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "ShowWind", true, "Show wind strength and direction for each kind of weather.");
			ShowFlavor = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "ShowFlavor", true, "Show Odin's one-line remark about what's coming.");
			if (Forecast.Init())
			{
				_tooltip = ((Component)this).gameObject.AddComponent<ForecastTooltip>();
				((BaseUnityPlugin)this).Logger.LogInfo((object)"Odin's Almanac 0.1.4 loaded. Odin has licked a finger and held it up.");
			}
		}

		private void OnDestroy()
		{
			if ((Object)(object)_tooltip != (Object)null)
			{
				Object.Destroy((Object)(object)_tooltip);
			}
		}
	}
	internal static class BuildInfo
	{
		public const string Version = "0.1.4";
	}
}