Decompiled source of NjordWeatherService v0.9.3

NjordWeatherService.dll

Decompiled 2 days ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Configuration;
using HarmonyLib;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyTitle("Njord Weather Service")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("EZB")]
[assembly: AssemblyProduct("Njord Weather Service")]
[assembly: AssemblyCopyright("Copyright ©  2026")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("e3243d22-4307-4008-ba36-9f326008cde5")]
[assembly: AssemblyFileVersion("0.9.3")]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("0.9.3.0")]
namespace NjordWeatherService;

[BepInPlugin("nws.njordweatherservice", "Njord Weather Service", "0.9.3")]
[BepInDependency(/*Could not decode attribute arguments.*/)]
internal class NjordWeatherService : BaseUnityPlugin
{
	public const string PluginGUID = "nws.njordweatherservice";

	public const string PluginName = "Njord Weather Service";

	public const string PluginVersion = "0.9.3";

	internal static ConfigEntry<KeyCode> ToggleKey;

	internal static ConfigEntry<KeyCode> PreviousPageKey;

	internal static ConfigEntry<KeyCode> NextPageKey;

	internal static ConfigEntry<KeyCode> OpacityUpKey;

	internal static ConfigEntry<KeyCode> OpacityDownKey;

	internal static ConfigEntry<KeyCode> PreviousTabKey;

	internal static ConfigEntry<KeyCode> NextTabKey;

	internal static ConfigEntry<KeyCode> ModifierKey;

	internal static ConfigEntry<KeyCode> PreviousBiomeKey;

	internal static ConfigEntry<KeyCode> NextBiomeKey;

	internal static ConfigEntry<KeyCode> CurrentBiomeKey;

	internal static ConfigEntry<KeyCode>[] DirectBiomeKeys = new ConfigEntry<KeyCode>[9];

	private Harmony harmony;

	private void Awake()
	{
		//IL_023c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0246: Expected O, but got Unknown
		ToggleKey = ((BaseUnityPlugin)this).Config.Bind<KeyCode>("Keyboard", "ToggleWindow", (KeyCode)287, "F6 shows/hides NWS; hold the configured Modifier and press F6 to toggle Mini/Full while open.");
		ModifierKey = ((BaseUnityPlugin)this).Config.Bind<KeyCode>("Keyboard", "Modifier", (KeyCode)305, "Hold this key for outlook and opacity shortcuts. Defaults to RIGHT Control only.");
		PreviousPageKey = ((BaseUnityPlugin)this).Config.Bind<KeyCode>("Keyboard", "PreviousPage", (KeyCode)276, "Previous four forecasts in Mini mode; previous row in Full mode.");
		NextPageKey = ((BaseUnityPlugin)this).Config.Bind<KeyCode>("Keyboard", "NextPage", (KeyCode)275, "Next four forecasts in Mini mode; next row in Full mode.");
		PreviousBiomeKey = ((BaseUnityPlugin)this).Config.Bind<KeyCode>("Keyboard", "PreviousBiome", (KeyCode)273, "Cycle to previous biome.");
		NextBiomeKey = ((BaseUnityPlugin)this).Config.Bind<KeyCode>("Keyboard", "NextBiome", (KeyCode)274, "Cycle to next biome.");
		OpacityUpKey = ((BaseUnityPlugin)this).Config.Bind<KeyCode>("Keyboard", "IncreaseOpacity", (KeyCode)273, "Increase opacity by 10 percent while holding Modifier.");
		OpacityDownKey = ((BaseUnityPlugin)this).Config.Bind<KeyCode>("Keyboard", "DecreaseOpacity", (KeyCode)274, "Decrease opacity by 10 percent while holding Modifier.");
		PreviousTabKey = ((BaseUnityPlugin)this).Config.Bind<KeyCode>("Keyboard", "PreviousTab", (KeyCode)276, "Previous outlook while holding Modifier; wraps around.");
		NextTabKey = ((BaseUnityPlugin)this).Config.Bind<KeyCode>("Keyboard", "NextTab", (KeyCode)275, "Next outlook while holding Modifier; wraps around.");
		CurrentBiomeKey = ((BaseUnityPlugin)this).Config.Bind<KeyCode>("Keyboard", "CurrentBiome", (KeyCode)256, "Read and select player's current biome once without a modifier.");
		string[] array = new string[9] { "Meadows", "BlackForest", "Swamp", "Mountain", "Plains", "Mistlands", "Ashlands", "DeepNorth", "Ocean" };
		KeyCode[] array2 = new KeyCode[9];
		RuntimeHelpers.InitializeArray(array2, (RuntimeFieldHandle)/*OpCode not supported: LdMemberToken*/);
		KeyCode[] array3 = (KeyCode[])(object)array2;
		for (int i = 0; i < array.Length; i++)
		{
			DirectBiomeKeys[i] = ((BaseUnityPlugin)this).Config.Bind<KeyCode>("Keyboard", "Select" + array[i], array3[i], "Select " + array[i] + " forecast without a modifier.");
		}
		harmony = new Harmony("nws.njordweatherservice");
		harmony.PatchAll();
		((Component)this).gameObject.AddComponent<NwsMapPanel>();
		((BaseUnityPlugin)this).Logger.LogInfo((object)"Njord Weather Service v0.9.3 loaded.");
	}

	private void OnDestroy()
	{
		Harmony obj = harmony;
		if (obj != null)
		{
			obj.UnpatchSelf();
		}
	}
}
internal class NwsMapPanel : MonoBehaviour
{
	private const int WindowId = 731904;

	private const string UiVersion = "NWS UI 0.9.3";

	private const float UiScale = 0.9f;

	private const float FullHeight = 650f;

	private const float MiniHeight = 310f;

	private Rect windowRect = new Rect(25f, 115f, 870f, 650f);

	private static NwsMapPanel instance;

	private bool dragging;

	private bool visible;

	private bool miniMode = true;

	private int miniPage;

	private float opacity = 0.9f;

	private Biome selectedBiome;

	private Biome displayedCurrentBiome;

	private bool biomeChosen;

	private bool biomeDropdown;

	private readonly List<Biome> biomeOptions = new List<Biome>();

	private int tab;

	private List<WeatherForecast.Entry> forecast;

	private List<WeatherForecast.DayForecast> daily;

	private Vector2 scrollPosition;

	private double lastUpdate = double.NegativeInfinity;

	private Biome lastBiome;

	private int lastTab = -1;

	private GUIStyle title;

	private GUIStyle text;

	private GUIStyle small;

	private GUIStyle center;

	private GUIStyle iconStyle;

	private GUIStyle buttonStyle;

	private Texture2D background;

	private Texture2D tile;

	private Texture2D dark;

	private Texture2D selected;

	private static readonly MethodInfo IsOpenMethod = AccessTools.Method(typeof(Minimap), "IsOpen", (Type[])null, (Type[])null);

	private static readonly FieldInfo LargeRootField = AccessTools.Field(typeof(Minimap), "m_largeRoot");

	private static readonly Biome[] BiomeOrder;

	private static Texture2D Solid(Color c)
	{
		//IL_0002: Unknown result type (might be due to invalid IL or missing references)
		//IL_0007: Unknown result type (might be due to invalid IL or missing references)
		//IL_000a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0010: Unknown result type (might be due to invalid IL or missing references)
		//IL_0017: Expected O, but got Unknown
		Texture2D val = new Texture2D(1, 1);
		val.SetPixel(0, 0, c);
		val.Apply();
		return val;
	}

	private void Awake()
	{
		instance = this;
	}

	private void Update()
	{
		//IL_0027: 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_0074: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ab: 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_00b7: Unknown result type (might be due to invalid IL or missing references)
		//IL_00bc: 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_00f9: Unknown result type (might be due to invalid IL or missing references)
		//IL_01e9: Unknown result type (might be due to invalid IL or missing references)
		//IL_01ee: Unknown result type (might be due to invalid IL or missing references)
		//IL_01f5: Unknown result type (might be due to invalid IL or missing references)
		//IL_0137: Unknown result type (might be due to invalid IL or missing references)
		//IL_0177: Unknown result type (might be due to invalid IL or missing references)
		//IL_020a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0238: Unknown result type (might be due to invalid IL or missing references)
		//IL_018c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0252: Unknown result type (might be due to invalid IL or missing references)
		//IL_026c: Unknown result type (might be due to invalid IL or missing references)
		//IL_01ba: Unknown result type (might be due to invalid IL or missing references)
		//IL_01bf: Unknown result type (might be due to invalid IL or missing references)
		//IL_0281: Unknown result type (might be due to invalid IL or missing references)
		if ((Object)(object)Player.m_localPlayer == (Object)null || (Object)(object)ZNet.instance == (Object)null)
		{
			visible = false;
			return;
		}
		bool key = Input.GetKey(NjordWeatherService.ModifierKey.Value);
		if (Input.GetKeyDown(NjordWeatherService.ToggleKey.Value) && key)
		{
			if (visible)
			{
				miniMode = !miniMode;
				miniPage = 0;
				biomeDropdown = false;
			}
		}
		else if (Input.GetKeyDown(NjordWeatherService.ToggleKey.Value))
		{
			visible = !visible;
			dragging = false;
			biomeDropdown = false;
			if (visible)
			{
				displayedCurrentBiome = Player.m_localPlayer.GetCurrentBiome();
				selectedBiome = displayedCurrentBiome;
				biomeChosen = true;
				miniPage = 0;
				lastTab = -1;
				lastUpdate = double.NegativeInfinity;
			}
		}
		if (!visible)
		{
			return;
		}
		if (key)
		{
			if (Input.GetKeyDown(NjordWeatherService.OpacityUpKey.Value))
			{
				opacity = Mathf.Min(1f, Mathf.Round((opacity + 0.1f) * 10f) / 10f);
			}
			if (Input.GetKeyDown(NjordWeatherService.OpacityDownKey.Value))
			{
				opacity = Mathf.Max(0.1f, Mathf.Round((opacity - 0.1f) * 10f) / 10f);
			}
			int num = 0;
			if (Input.GetKeyDown(NjordWeatherService.PreviousTabKey.Value))
			{
				num = -1;
			}
			else if (Input.GetKeyDown(NjordWeatherService.NextTabKey.Value))
			{
				num = 1;
			}
			if (num != 0)
			{
				tab = (tab + num + 3) % 3;
				lastTab = -1;
				scrollPosition = Vector2.zero;
				miniPage = 0;
				Refresh();
			}
			return;
		}
		if (Input.GetKeyDown(NjordWeatherService.CurrentBiomeKey.Value))
		{
			displayedCurrentBiome = Player.m_localPlayer.GetCurrentBiome();
			SelectBiome(displayedCurrentBiome);
		}
		for (int i = 0; i < NjordWeatherService.DirectBiomeKeys.Length; i++)
		{
			if (Input.GetKeyDown(NjordWeatherService.DirectBiomeKeys[i].Value))
			{
				SelectBiome(BiomeOrder[i]);
				break;
			}
		}
		if (Input.GetKeyDown(NjordWeatherService.PreviousBiomeKey.Value))
		{
			CycleBiome(-1);
		}
		else if (Input.GetKeyDown(NjordWeatherService.NextBiomeKey.Value))
		{
			CycleBiome(1);
		}
		int num2 = 0;
		if (Input.GetKeyDown(NjordWeatherService.PreviousPageKey.Value))
		{
			num2 = -1;
		}
		else if (Input.GetKeyDown(NjordWeatherService.NextPageKey.Value))
		{
			num2 = 1;
		}
		if (num2 != 0)
		{
			int num3 = (((tab == 0) ? 24 : ((tab == 1) ? 9 : 15)) - 1) / 4;
			miniPage = Mathf.Clamp(miniPage + num2, 0, num3);
			if (!miniMode)
			{
				float num4 = ((tab == 0) ? 145f : 145f);
				float num5 = ((tab == 0) ? 870f : ((tab == 1) ? 505f : 825f));
				scrollPosition.y = Mathf.Clamp(scrollPosition.y + (float)num2 * num4, 0f, Mathf.Max(0f, num5 - 448f));
			}
		}
	}

	private void SelectBiome(Biome biome)
	{
		//IL_0013: Unknown result type (might be due to invalid IL or missing references)
		//IL_0014: Unknown result type (might be due to invalid IL or missing references)
		//IL_002f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0034: 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_000e: Unknown result type (might be due to invalid IL or missing references)
		if (!biomeChosen || selectedBiome != biome)
		{
			selectedBiome = biome;
			biomeChosen = true;
			biomeDropdown = false;
			miniPage = 0;
			scrollPosition = Vector2.zero;
			lastTab = -1;
			lastUpdate = double.NegativeInfinity;
			Refresh();
		}
	}

	private void CycleBiome(int direction)
	{
		//IL_0006: Unknown result type (might be due to invalid IL or missing references)
		int num = Array.IndexOf(BiomeOrder, selectedBiome);
		if (num < 0)
		{
			num = 0;
		}
		SelectBiome(BiomeOrder[(num + direction + BiomeOrder.Length) % BiomeOrder.Length]);
	}

	private void OnDestroy()
	{
		if ((Object)(object)instance == (Object)(object)this)
		{
			instance = null;
		}
		Texture2D[] array = (Texture2D[])(object)new Texture2D[4] { background, tile, dark, selected };
		foreach (Texture2D val in array)
		{
			if ((Object)(object)val != (Object)null)
			{
				Object.Destroy((Object)(object)val);
			}
		}
	}

	private static bool MapIsOpen()
	{
		Minimap val = Minimap.instance;
		if ((Object)(object)val == (Object)null)
		{
			return false;
		}
		if (IsOpenMethod != null)
		{
			try
			{
				return (bool)IsOpenMethod.Invoke(val, null);
			}
			catch
			{
				return false;
			}
		}
		if (LargeRootField != null)
		{
			object? value = LargeRootField.GetValue(val);
			GameObject val2 = (GameObject)((value is GameObject) ? value : null);
			if ((Object)(object)val2 != (Object)null)
			{
				return val2.activeInHierarchy;
			}
			return false;
		}
		return false;
	}

	internal static bool BlocksMapMouse()
	{
		//IL_001b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0020: 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_0049: Unknown result type (might be due to invalid IL or missing references)
		//IL_0056: Unknown result type (might be due to invalid IL or missing references)
		if ((Object)(object)instance == (Object)null || !instance.visible)
		{
			return false;
		}
		Vector3 mousePosition = Input.mousePosition;
		if (!instance.dragging)
		{
			return ((Rect)(ref instance.windowRect)).Contains(new Vector2(mousePosition.x / 0.9f, ((float)Screen.height - mousePosition.y) / 0.9f));
		}
		return true;
	}

	private static GUIStyle Style(int size, Color color, bool bold = false, TextAnchor alignment = (TextAnchor)3)
	{
		//IL_000a: Unknown result type (might be due to invalid IL or missing references)
		//IL_000f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0016: Unknown result type (might be due to invalid IL or missing references)
		//IL_0023: 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_002f: 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_0036: Unknown result type (might be due to invalid IL or missing references)
		//IL_003e: Expected O, but got Unknown
		GUIStyle val = new GUIStyle(GUI.skin.label)
		{
			fontSize = size,
			fontStyle = (FontStyle)(bold ? 1 : 0)
		};
		val.normal.textColor = color;
		val.alignment = alignment;
		val.clipping = (TextClipping)1;
		return val;
	}

	private void Init()
	{
		//IL_0024: Unknown result type (might be due to invalid IL or missing references)
		//IL_0048: Unknown result type (might be due to invalid IL or missing references)
		//IL_006c: 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_00b1: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c5: Unknown result type (might be due to invalid IL or missing references)
		//IL_00e8: Unknown result type (might be due to invalid IL or missing references)
		//IL_00fc: Unknown result type (might be due to invalid IL or missing references)
		//IL_0110: Unknown result type (might be due to invalid IL or missing references)
		//IL_0124: Unknown result type (might be due to invalid IL or missing references)
		if (!((Object)(object)background != (Object)null))
		{
			background = Solid(new Color(0.075f, 0.13f, 0.15f, 0.98f));
			tile = Solid(new Color(0.14f, 0.23f, 0.25f, 1f));
			dark = Solid(new Color(0.11f, 0.18f, 0.2f, 1f));
			selected = Solid(new Color(0.21f, 0.32f, 0.34f, 1f));
			title = Style(18, new Color(1f, 0.88f, 0.72f), bold: true, (TextAnchor)3);
			text = Style(12, Color.white, bold: false, (TextAnchor)3);
			small = Style(10, new Color(0.65f, 0.83f, 0.87f), bold: false, (TextAnchor)3);
			center = Style(13, Color.white, bold: true, (TextAnchor)4);
			iconStyle = Style(26, Color.white, bold: true, (TextAnchor)4);
			buttonStyle = Style(16, Color.white, bold: true, (TextAnchor)4);
		}
	}

	private void OnGUI()
	{
		//IL_003b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0040: Unknown result type (might be due to invalid IL or missing references)
		//IL_0050: Unknown result type (might be due to invalid IL or missing references)
		//IL_0055: Unknown result type (might be due to invalid IL or missing references)
		//IL_005a: Unknown result type (might be due to invalid IL or missing references)
		//IL_005b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0074: Unknown result type (might be due to invalid IL or missing references)
		//IL_0083: Unknown result type (might be due to invalid IL or missing references)
		//IL_0089: Expected O, but got Unknown
		//IL_009c: 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_00b8: Expected O, but got Unknown
		//IL_00b3: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b8: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c7: Unknown result type (might be due to invalid IL or missing references)
		if (!visible)
		{
			dragging = false;
			return;
		}
		Init();
		Refresh();
		((Rect)(ref windowRect)).height = (miniMode ? 310f : 650f);
		Matrix4x4 matrix = GUI.matrix;
		GUI.matrix = Matrix4x4.Scale(new Vector3(0.9f, 0.9f, 1f)) * matrix;
		bool enabled = GUI.enabled;
		GUI.enabled = MapIsOpen();
		Color color = GUI.color;
		GUIStyle val = new GUIStyle(GUI.skin.window);
		val.normal.background = null;
		windowRect = GUI.Window(731904, windowRect, new WindowFunction(DrawWindow), GUIContent.none, val);
		GUI.color = color;
		GUI.enabled = enabled;
		GUI.matrix = matrix;
		((Rect)(ref windowRect)).x = Mathf.Clamp(((Rect)(ref windowRect)).x, 0f, Mathf.Max(0f, (float)Screen.width / 0.9f - ((Rect)(ref windowRect)).width));
		((Rect)(ref windowRect)).y = Mathf.Clamp(((Rect)(ref windowRect)).y, 0f, Mathf.Max(0f, (float)Screen.height / 0.9f - ((Rect)(ref windowRect)).height));
	}

	private void Refresh()
	{
		//IL_004f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0047: Unknown result type (might be due to invalid IL or missing references)
		//IL_0054: 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)
		//IL_0075: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ac: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ed: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ee: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ce: Unknown result type (might be due to invalid IL or missing references)
		if ((Object)(object)EnvMan.instance == (Object)null || (Object)(object)Player.m_localPlayer == (Object)null || (Object)(object)ZNet.instance == (Object)null)
		{
			forecast = null;
			return;
		}
		ZNet.instance.GetTimeSeconds();
		Biome val = (biomeChosen ? selectedBiome : Player.m_localPlayer.GetCurrentBiome());
		if ((forecast == null && daily == null) || tab != lastTab || val != lastBiome || !((double)Time.realtimeSinceStartup >= lastUpdate) || !((double)Time.realtimeSinceStartup - lastUpdate < 60.0))
		{
			if (tab == 0)
			{
				forecast = WeatherForecast.GetHourly(val);
				daily = null;
			}
			else
			{
				daily = WeatherForecast.GetDaily((tab == 1) ? 3 : 5, val);
				forecast = null;
			}
			lastUpdate = Time.realtimeSinceStartup;
			lastBiome = val;
			lastTab = tab;
		}
	}

	private void Label(Rect r, string value, GUIStyle style)
	{
		//IL_0000: Unknown result type (might be due to invalid IL or missing references)
		GUI.Label(r, value, style);
	}

	private void DrawTint(Rect r, Texture2D texture)
	{
		//IL_0000: Unknown result type (might be due to invalid IL or missing references)
		//IL_001a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0024: Unknown result type (might be due to invalid IL or missing references)
		Color color = GUI.color;
		GUI.color = new Color(1f, 1f, 1f, opacity);
		GUI.DrawTexture(r, (Texture)(object)texture);
		GUI.color = color;
	}

	private void DrawBiomeSelector()
	{
		//IL_002a: 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_00a8: Unknown result type (might be due to invalid IL or missing references)
		if (!biomeChosen || (Object)(object)EnvMan.instance == (Object)null)
		{
			return;
		}
		if (GUI.Button(new Rect(130f, 49f, 245f, 25f), ((object)Unsafe.As<Biome, Biome>(ref selectedBiome)/*cast due to .constrained prefix*/).ToString() + "  ▾"))
		{
			biomeDropdown = !biomeDropdown;
		}
		if (!biomeDropdown)
		{
			return;
		}
		biomeOptions.Clear();
		foreach (BiomeEnvSetup biome in EnvMan.instance.m_biomes)
		{
			if (!biomeOptions.Contains(biome.m_biome))
			{
				biomeOptions.Add(biome.m_biome);
			}
		}
	}

	private void DrawBiomeMenu()
	{
		//IL_0038: Unknown result type (might be due to invalid IL or missing references)
		//IL_005f: Unknown result type (might be due to invalid IL or missing references)
		//IL_006b: 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_008d: Unknown result type (might be due to invalid IL or missing references)
		if (!biomeDropdown)
		{
			return;
		}
		Rect r = default(Rect);
		((Rect)(ref r))..ctor(130f, 76f, 245f, (float)(Mathf.Min(biomeOptions.Count, 10) * 29 + 8));
		DrawTint(r, background);
		for (int i = 0; i < biomeOptions.Count && i < 10; i++)
		{
			if (GUI.Button(new Rect(135f, (float)(80 + i * 29), 235f, 27f), ((object)biomeOptions[i]/*cast due to .constrained prefix*/).ToString()))
			{
				SelectBiome(biomeOptions[i]);
				biomeDropdown = false;
			}
		}
	}

	private void DrawWindow(int id)
	{
		//IL_0024: Unknown result type (might be due to invalid IL or missing references)
		//IL_0048: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a0: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ca: Unknown result type (might be due to invalid IL or missing references)
		//IL_0141: 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_01ae: Unknown result type (might be due to invalid IL or missing references)
		//IL_0208: Unknown result type (might be due to invalid IL or missing references)
		//IL_0280: Unknown result type (might be due to invalid IL or missing references)
		//IL_0343: Unknown result type (might be due to invalid IL or missing references)
		//IL_0349: Unknown result type (might be due to invalid IL or missing references)
		//IL_0314: Unknown result type (might be due to invalid IL or missing references)
		//IL_029f: Unknown result type (might be due to invalid IL or missing references)
		//IL_040c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0390: Unknown result type (might be due to invalid IL or missing references)
		//IL_0395: Unknown result type (might be due to invalid IL or missing references)
		//IL_039a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0432: Unknown result type (might be due to invalid IL or missing references)
		//IL_0438: Invalid comparison between Unknown and I4
		//IL_02cc: Unknown result type (might be due to invalid IL or missing references)
		//IL_02d1: Unknown result type (might be due to invalid IL or missing references)
		//IL_0441: Unknown result type (might be due to invalid IL or missing references)
		//IL_041e: Unknown result type (might be due to invalid IL or missing references)
		//IL_03cf: Unknown result type (might be due to invalid IL or missing references)
		DrawTint(new Rect(0f, 0f, 870f, miniMode ? 310f : 650f), background);
		if (GUI.Button(new Rect(625f, 16f, 96f, 30f), miniMode ? "FULL" : "MINI"))
		{
			miniMode = !miniMode;
			miniPage = 0;
			biomeDropdown = false;
		}
		DrawBiomeSelector();
		Label(new Rect(20f, 17f, 600f, 32f), "NWS | NJORD WEATHER SERVICE", title);
		Label(new Rect(20f, 49f, 110f, 22f), "FORECAST BIOME", small);
		if ((Object)(object)Player.m_localPlayer != (Object)null)
		{
			Label(new Rect(393f, 49f, 230f, 25f), " " + ((object)Unsafe.As<Biome, Biome>(ref displayedCurrentBiome)/*cast due to .constrained prefix*/).ToString(), small);
		}
		Label(new Rect(680f, 84f, 165f, 16f), "Opacity " + Mathf.RoundToInt(opacity * 100f) + "%", small);
		if ((Object)(object)EnvMan.instance != (Object)null && (Object)(object)ZNet.instance != (Object)null)
		{
			Label(new Rect(745f, 15f, 105f, 22f), "Day " + (EnvMan.instance.GetDay() + 1), center);
			int num = Mathf.FloorToInt(EnvMan.instance.GetDayFraction() * 1440f);
			Label(new Rect(745f, 39f, 105f, 26f), $"{num / 60:00}:{num % 60:00}", center);
		}
		string[] array = new string[3] { "24 Hours", "3 Days", "5 Days" };
		Rect val = default(Rect);
		for (int i = 0; i < 3; i++)
		{
			((Rect)(ref val))..ctor((float)(14 + i * 284), 103f, 276f, 32f);
			DrawTint(val, (tab == i) ? selected : dark);
			if (GUI.Button(val, array[i], buttonStyle) && tab != i)
			{
				tab = i;
				lastTab = -1;
				scrollPosition = Vector2.zero;
				miniPage = 0;
				Refresh();
			}
		}
		if (miniMode)
		{
			DrawMini();
			Label(new Rect(20f, 279f, 830f, 22f), " ", small);
		}
		else
		{
			scrollPosition = GUI.BeginScrollView(new Rect(14f, 146f, 842f, 448f), scrollPosition, new Rect(0f, 0f, 818f, (float)((tab == 0) ? 870 : ((daily == null) ? 505 : (34 + daily.Count * 157)))));
			if (tab == 0)
			{
				DrawHourly();
			}
			else
			{
				DrawDaily();
			}
			GUI.EndScrollView();
			Label(new Rect(20f, 605f, 830f, 24f), "NWS UI 0.9.3 ", small);
		}
		DrawBiomeMenu();
		Rect val2 = default(Rect);
		((Rect)(ref val2))..ctor(0f, 0f, 610f, 43f);
		Event current = Event.current;
		if ((int)current.type == 0 && current.button == 0 && ((Rect)(ref val2)).Contains(current.mousePosition))
		{
			dragging = true;
		}
		if ((int)current.rawType == 1)
		{
			dragging = false;
		}
		GUI.DragWindow(val2);
	}

	private int DailyCount()
	{
		if (daily == null)
		{
			return 0;
		}
		int num = 0;
		foreach (WeatherForecast.DayForecast item in daily)
		{
			for (int i = 0; i < 3; i++)
			{
				if (item.Periods[i].HasValue)
				{
					num++;
				}
			}
		}
		return num;
	}

	private void DailyPosition(int index, out int day, out int part)
	{
		for (day = 0; day < daily.Count; day++)
		{
			for (part = 0; part < 3; part++)
			{
				if (daily[day].Periods[part].HasValue && index-- == 0)
				{
					return;
				}
			}
		}
		day = 0;
		part = 0;
	}

	private void DrawMini()
	{
		//IL_0181: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a4: Unknown result type (might be due to invalid IL or missing references)
		//IL_0124: Unknown result type (might be due to invalid IL or missing references)
		int num = ((tab != 0) ? ((daily != null) ? DailyCount() : 0) : ((forecast != null) ? forecast.Count : 0));
		int num2 = Mathf.Max(1, (num + 3) / 4);
		miniPage = Mathf.Clamp(miniPage, 0, num2 - 1);
		Rect r = default(Rect);
		for (int i = 0; i < 4; i++)
		{
			int num3 = miniPage * 4 + i;
			if (num3 >= num)
			{
				break;
			}
			((Rect)(ref r))..ctor((float)(17 + i * 211), 146f, 201f, 126f);
			if (tab == 0)
			{
				WeatherForecast.Entry f = forecast[num3];
				DrawCard(r, "Day " + f.Day + " · " + f.Time, f);
				continue;
			}
			DailyPosition(num3, out var day, out var part);
			string[] array = new string[3] { "Morning", "Afternoon", "Evening" };
			WeatherForecast.Entry? entry = daily[day].Periods[part];
			if (entry.HasValue)
			{
				DrawCard(r, "Day " + daily[day].Day + " · " + array[part], entry.Value);
			}
		}
		Label(new Rect(385f, 279f, 200f, 20f), miniPage * 4 + 1 + "–" + Mathf.Min(num, (miniPage + 1) * 4) + " of " + num + "   (" + (miniPage + 1) + "/" + num2 + ")", small);
	}

	private void DrawHourly()
	{
		//IL_0030: Unknown result type (might be due to invalid IL or missing references)
		if (forecast != null)
		{
			for (int i = 0; i < forecast.Count; i++)
			{
				int num = i % 4;
				int num2 = i / 4;
				DrawCard(new Rect((float)(num * 204), (float)(num2 * 145), 195f, 137f), "Day " + forecast[i].Day + " · " + forecast[i].Time, forecast[i]);
			}
		}
	}

	private void DrawDaily()
	{
		//IL_0047: 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_009d: 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_0120: Unknown result type (might be due to invalid IL or missing references)
		if (daily == null)
		{
			return;
		}
		string[] array = new string[3] { "Morning · 09:00", "Afternoon · 15:00", "Evening · 21:00" };
		for (int i = 0; i < 3; i++)
		{
			Label(new Rect((float)(65 + i * 250), 0f, 245f, 24f), array[i], Style(14, new Color(0.72f, 0.86f, 0.88f), bold: true, (TextAnchor)4));
		}
		Rect r = default(Rect);
		for (int j = 0; j < daily.Count; j++)
		{
			float num = 34 + j * 157;
			Label(new Rect(0f, num, 58f, 145f), "Day " + daily[j].Day, Style(13, Color.white, bold: true, (TextAnchor)4));
			for (int k = 0; k < 3; k++)
			{
				((Rect)(ref r))..ctor((float)(65 + k * 250), num, 242f, 145f);
				WeatherForecast.Entry? entry = daily[j].Periods[k];
				if (entry.HasValue)
				{
					DrawCard(r, array[k], entry.Value);
				}
			}
		}
	}

	private void DrawCard(Rect r, string heading, WeatherForecast.Entry f)
	{
		//IL_0001: 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_0055: Unknown result type (might be due to invalid IL or missing references)
		//IL_007b: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ab: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b8: Unknown result type (might be due to invalid IL or missing references)
		//IL_0128: Unknown result type (might be due to invalid IL or missing references)
		//IL_012d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0143: Unknown result type (might be due to invalid IL or missing references)
		//IL_0165: Unknown result type (might be due to invalid IL or missing references)
		//IL_0112: Unknown result type (might be due to invalid IL or missing references)
		//IL_00fc: Unknown result type (might be due to invalid IL or missing references)
		DrawTint(r, tile);
		float num = ((Rect)(ref r)).x + 8f;
		float num2 = ((Rect)(ref r)).width - 16f;
		Label(new Rect(num, ((Rect)(ref r)).y + 6f, num2, 21f), heading, Style(13, new Color(0.68f, 0.87f, 0.9f), bold: true, (TextAnchor)4));
		Label(new Rect(num, ((Rect)(ref r)).y + 29f, num2, 35f), WeatherIcon(f.Weather), iconStyle);
		Label(new Rect(num, ((Rect)(ref r)).y + 67f, num2, 23f), f.Weather, Style(14, Color.white, bold: false, (TextAnchor)4));
		Color color = ((f.Strength == "Strong") ? new Color(1f, 0.49f, 0.4f) : ((f.Strength == "Moderate") ? new Color(1f, 0.77f, 0.34f) : new Color(0.47f, 0.85f, 0.66f)));
		Label(new Rect(num, ((Rect)(ref r)).y + 101f, num2, 25f), Arrow(f.Direction) + "  " + f.Strength, Style(16, color, bold: true, (TextAnchor)4));
	}

	private static string WeatherIcon(string name)
	{
		string text = (name ?? "").ToLowerInvariant();
		if (text.Contains("thunder") || text.Contains("storm"))
		{
			return "⚡";
		}
		if (text.Contains("snow") || text.Contains("blizzard"))
		{
			return "❄";
		}
		if (text.Contains("rain"))
		{
			return "☂";
		}
		if (text.Contains("fog") || text.Contains("mist"))
		{
			return "≋";
		}
		if (text.Contains("cloud"))
		{
			return "☁";
		}
		return "☼";
	}

	private static string Arrow(string direction)
	{
		return direction switch
		{
			"N" => "↑", 
			"NE" => "↗", 
			"E" => "→", 
			"SE" => "↘", 
			"S" => "↓", 
			"SW" => "↙", 
			"W" => "←", 
			"NW" => "↖", 
			_ => "·", 
		};
	}

	static NwsMapPanel()
	{
		Biome[] array = new Biome[9];
		RuntimeHelpers.InitializeArray(array, (RuntimeFieldHandle)/*OpCode not supported: LdMemberToken*/);
		BiomeOrder = (Biome[])(object)array;
	}
}
[HarmonyPatch(typeof(Minimap), "Update")]
internal static class NwsMapInputPatch
{
	private static bool Prefix()
	{
		if (NwsMapPanel.BlocksMapMouse() && (Input.GetMouseButton(0) || Input.GetMouseButton(1)))
		{
			return false;
		}
		return true;
	}
}
internal static class WeatherForecast
{
	internal struct Entry
	{
		internal string Time;

		internal int Day;

		internal string Weather;

		internal string Direction;

		internal string Strength;
	}

	internal struct DayForecast
	{
		internal int Day;

		internal Entry?[] Periods;
	}

	internal static List<Entry> GetHourly(Biome biome)
	{
		//IL_006c: Unknown result type (might be due to invalid IL or missing references)
		List<Entry> list = new List<Entry>();
		if (!Ready())
		{
			return list;
		}
		double timeSeconds = ZNet.instance.GetTimeSeconds();
		double num = EnvMan.instance.m_dayLengthSec;
		double dayStart = Math.Floor(timeSeconds / num) * num;
		int num2 = (int)Math.Floor(ClockFraction(timeSeconds, num) * 24.0);
		for (int i = 0; i < 24; i++)
		{
			double hour = num2 + i;
			double timestamp = ((i == 0) ? timeSeconds : TimestampForHour(dayStart, num, hour));
			list.Add(Sample(timestamp, biome));
		}
		return list;
	}

	internal static List<DayForecast> GetDaily(int days, Biome biome)
	{
		//IL_00ab: Unknown result type (might be due to invalid IL or missing references)
		List<DayForecast> list = new List<DayForecast>();
		if (!Ready())
		{
			return list;
		}
		double timeSeconds = ZNet.instance.GetTimeSeconds();
		double num = EnvMan.instance.m_dayLengthSec;
		double dayStart = Math.Floor(timeSeconds / num) * num;
		int num2 = days * 3;
		int num3 = 0;
		while (num2 > 0)
		{
			DayForecast item = new DayForecast
			{
				Day = EnvMan.instance.GetDay(timeSeconds) + num3 + 1,
				Periods = new Entry?[3]
			};
			double[] array = new double[3] { 9.0, 15.0, 21.0 };
			for (int i = 0; i < 3; i++)
			{
				double num4 = TimestampForHour(dayStart, num, (double)(num3 * 24) + array[i]);
				if (!(num4 < timeSeconds))
				{
					item.Periods[i] = Sample(num4, biome);
					num2--;
					if (num2 == 0)
					{
						break;
					}
				}
			}
			if (item.Periods[0].HasValue || item.Periods[1].HasValue || item.Periods[2].HasValue)
			{
				list.Add(item);
			}
			num3++;
		}
		return list;
	}

	private static bool Ready()
	{
		if ((Object)(object)EnvMan.instance != (Object)null && (Object)(object)Player.m_localPlayer != (Object)null && (Object)(object)ZNet.instance != (Object)null && WorldGenerator.instance != null && EnvMan.instance.m_dayLengthSec > 0 && EnvMan.instance.m_environmentDuration > 0)
		{
			return EnvMan.instance.m_windPeriodDuration >= 8;
		}
		return false;
	}

	private static double TimestampForHour(double dayStart, double length, double hour)
	{
		double num = Math.Floor(hour / 24.0);
		double displayed = (hour - num * 24.0) / 24.0;
		return dayStart + num * length + RawFraction(displayed) * length;
	}

	private static Entry Sample(double timestamp, Biome biome)
	{
		//IL_0061: 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_0331: 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_00a7: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ac: Unknown result type (might be due to invalid IL or missing references)
		//IL_00eb: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f0: Unknown result type (might be due to invalid IL or missing references)
		EnvMan instance = EnvMan.instance;
		Player localPlayer = Player.m_localPlayer;
		Entry result = new Entry
		{
			Time = Clock(timestamp, instance.m_dayLengthSec),
			Day = instance.GetDay(timestamp) + 1,
			Weather = "Unknown",
			Direction = "--",
			Strength = "--"
		};
		List<EnvEntry> list = null;
		if (biome == localPlayer.GetCurrentBiome())
		{
			BiomeSector biomeSector = WorldGenerator.instance.GetBiomeSector(((Component)localPlayer).transform.position, false);
			list = instance.GetAvailableEnvironments(biomeSector);
		}
		else
		{
			foreach (BiomeEnvSetup biome2 in instance.m_biomes)
			{
				if (biome2.m_biome == biome)
				{
					list = biome2.m_environments;
					break;
				}
			}
		}
		if (list == null || list.Count == 0)
		{
			return result;
		}
		List<EnvEntry> list2 = new List<EnvEntry>(list);
		long num = (long)timestamp;
		State state = Random.state;
		try
		{
			Random.InitState((int)(num / instance.m_environmentDuration));
			float num2 = 0f;
			foreach (EnvEntry item in list2)
			{
				if (!item.m_ashlandsOverride && !item.m_deepnorthOverride)
				{
					num2 += item.m_weight;
				}
			}
			EnvSetup val = null;
			if (num2 > 0f)
			{
				float num3 = Random.Range(0f, num2);
				float num4 = 0f;
				foreach (EnvEntry item2 in list2)
				{
					if (!item2.m_ashlandsOverride && !item2.m_deepnorthOverride)
					{
						num4 += item2.m_weight;
						if (num4 >= num3)
						{
							val = item2.m_env;
							break;
						}
					}
				}
			}
			if (val == null)
			{
				return result;
			}
			float num5 = 0f;
			float num6 = 0.5f;
			int[] array = new int[4] { 1, 2, 4, 8 };
			foreach (int num7 in array)
			{
				long num8 = instance.m_windPeriodDuration / num7;
				if (num8 > 0)
				{
					Random.InitState((int)(num / num8));
					num5 += Random.value * ((float)Math.PI * 2f / (float)num7);
					num6 += -0.5f / (float)num7 + Random.value / (float)num7;
				}
			}
			num6 = Mathf.Lerp(val.m_windMin, val.m_windMax, num6);
			float num9 = Mathf.Repeat(num5 * 57.29578f, 360f);
			string[] array2 = new string[8] { "N", "NE", "E", "SE", "S", "SW", "W", "NW" };
			result.Weather = val.m_name;
			result.Direction = array2[Mathf.FloorToInt((num9 + 22.5f) / 45f) % 8];
			result.Strength = ((num6 < 0.33f) ? "Light" : ((num6 < 0.66f) ? "Moderate" : "Strong"));
			return result;
		}
		finally
		{
			Random.state = state;
		}
	}

	private static double RawFraction(double displayed)
	{
		if (displayed >= 0.25 && displayed <= 0.75)
		{
			return 0.15 + (displayed - 0.25) * 1.4;
		}
		if (displayed < 0.25)
		{
			return displayed * 0.6;
		}
		return 0.85 + (displayed - 0.75) * 0.6;
	}

	private static double ClockFraction(double timestamp, double dayLength)
	{
		double num = (timestamp % dayLength + dayLength) % dayLength / dayLength;
		if (num >= 0.15 && num <= 0.85)
		{
			return 0.25 + (num - 0.15) / 1.4;
		}
		if (num < 0.15)
		{
			return num / 0.6;
		}
		return 0.75 + (num - 0.85) / 0.6;
	}

	private static string Clock(double timestamp, double dayLength)
	{
		int num = (int)Math.Floor(ClockFraction(timestamp, dayLength) * 1440.0 + 1E-05);
		return $"{num / 60:00}:{num % 60:00}";
	}
}