Decompiled source of MoonPhases v1.0.1

plugins/MoonPhases.dll

Decompiled 5 days ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using System.Threading;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using UnityEngine;
using UnityEngine.Rendering;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyCompany("MoonPhases")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.1.0")]
[assembly: AssemblyInformationalVersion("1.0.1")]
[assembly: AssemblyProduct("MoonPhases")]
[assembly: AssemblyTitle("MoonPhases")]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.1.0")]
[module: UnverifiableCode]
[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 MoonPhases
{
	internal struct EclipseEvent
	{
		public bool IsSolar;

		public EclipseKind Kind;

		public double MaximumDays;

		public double Magnitude;

		public double PartialStartDays;

		public double PartialEndDays;

		public double CentralStartDays;

		public double CentralEndDays;

		public double PenumbralStartDays;

		public double PenumbralEndDays;

		public double MoonAngularRadiusDeg;

		public double MoonDistanceKm;
	}
	internal enum EclipseKind
	{
		None,
		Penumbral,
		Partial,
		Total,
		Annular
	}
	internal static class EclipseVisuals
	{
		public static double VisualObscuration(LunarState state, double magnitudePerSecond, double durationSeconds)
		{
			double separation = VisualSeparation(state, magnitudePerSecond, durationSeconds);
			return ObscurationAtSeparation(state, separation);
		}

		public static double VisualSeparation(LunarState state, double magnitudePerSecond, double durationSeconds)
		{
			if (durationSeconds <= 0.0 || magnitudePerSecond <= 0.0 || state.SolarObscuration01 <= 0.0)
			{
				return state.SolarSeparationDeg;
			}
			double num = Math.Max(state.SolarPeakMagnitude, state.SolarMagnitude);
			double num2 = magnitudePerSecond * (durationSeconds * 0.5);
			if (num2 <= 1E-09 || num <= 0.0)
			{
				return state.SolarSeparationDeg;
			}
			double num3 = Math.Max(0.0, (num - state.SolarMagnitude) / num2);
			double num4 = num - num2 * (num3 * num3 * num3) / (1.0 + num3 * num3);
			return Math.Max(0.0, state.SunAngularRadiusDeg + state.ObserverMoonRadiusDeg - 2.0 * state.SunAngularRadiusDeg * num4);
		}

		public static double ObscurationAtSeparation(LunarState state, double separation)
		{
			double sunAngularRadiusDeg = state.SunAngularRadiusDeg;
			double observerMoonRadiusDeg = state.ObserverMoonRadiusDeg;
			return LunarModel.CircleOverlapArea(sunAngularRadiusDeg, observerMoonRadiusDeg, separation) / (Math.PI * sunAngularRadiusDeg * sunAngularRadiusDeg);
		}
	}
	internal struct LitDiscKey : IEquatable<LitDiscKey>
	{
		public int PhaseAngle;

		public int SunPositionAngle;

		public int ShadowX;

		public int ShadowY;

		public int UmbraRadius;

		public int PenumbraRadius;

		public bool Eclipse;

		public bool Equals(LitDiscKey other)
		{
			if (PhaseAngle == other.PhaseAngle && SunPositionAngle == other.SunPositionAngle && Eclipse == other.Eclipse)
			{
				if (Eclipse)
				{
					if (ShadowX == other.ShadowX && ShadowY == other.ShadowY && UmbraRadius == other.UmbraRadius)
					{
						return PenumbraRadius == other.PenumbraRadius;
					}
					return false;
				}
				return true;
			}
			return false;
		}

		public override bool Equals(object obj)
		{
			if (obj is LitDiscKey other)
			{
				return Equals(other);
			}
			return false;
		}

		public override int GetHashCode()
		{
			return (PhaseAngle * 397) ^ SunPositionAngle;
		}
	}
	internal sealed class LitDiscParameters
	{
		public float PhaseAngleDeg;

		public Vector2 SunDirection2D = Vector2.right;

		public float TerminatorSoftness = 0.06f;

		public bool Eclipse;

		public Vector2 ShadowCenter;

		public float UmbraRadius;

		public float PenumbraRadius;

		public float TotalityBrightness = 1f;
	}
	internal static class LunarModel
	{
		public const double EarthSynodicMonth = 29.530588;

		public const double EarthSiderealMonth = 27.321661;

		public const double EarthDraconicMonth = 27.212221;

		public const double EarthAnomalisticMonth = 27.55455;

		public const double EarthInclinationDeg = 5.145;

		public const double Eccentricity = 0.0549;

		public const double SemiMajorAxisKm = 384400.0;

		public const double MoonRadiusKm = 1737.4;

		public const double PlanetRadiusKm = 6378.14;

		public const double SunAngularRadiusDeg = 0.26656;

		public const double SunParallaxDeg = 0.0024428;

		public const double AnomalisticEpoch01 = 0.5599166666666666;

		public const double DraconicEpoch01 = 0.44643611111111114;

		public const double SiderealEpoch01 = 0.7930277777777778;

		public static readonly double MeanMoonAngularRadiusDeg = Math.Asin(0.004519771071800209) / (Math.PI / 180.0);

		public static LunarState Calculate(double astroTimeDays, LunarSettings settings)
		{
			LunarState s = CalculateGeocentric(astroTimeDays, settings);
			ApplySolarObserver(ref s, settings);
			return s;
		}

		private static LunarState CalculateGeocentric(double astroTimeDays, LunarSettings settings)
		{
			LunarState s = new LunarState
			{
				AstroTimeDays = astroTimeDays
			};
			s.SynodicPhase01 = Phase01(astroTimeDays, settings.SynodicPeriodDays, 0.0);
			s.SiderealPhase01 = Phase01(astroTimeDays, settings.SiderealPeriodDays, 0.7930277777777778);
			s.DraconicPhase01 = Phase01(astroTimeDays, settings.DraconicPeriodDays, 0.44643611111111114);
			s.AnomalisticPhase01 = Phase01(astroTimeDays, settings.AnomalisticPeriodDays, 0.5599166666666666);
			double num = s.AnomalisticPhase01 * 2.0 * Math.PI;
			double num2 = num;
			double num3 = num;
			double num4 = 384400.0;
			if (settings.EllipticalOrbit)
			{
				num2 = SolveKepler(num, 0.0549);
				num3 = 2.0 * Math.Atan2(Math.Sqrt(1.0549) * Math.Sin(num2 / 2.0), Math.Sqrt(0.9451) * Math.Cos(num2 / 2.0));
				if (settings.DistanceVariation)
				{
					num4 = 384400.0 * (1.0 - 0.0549 * Math.Cos(num2));
				}
			}
			else if (settings.DistanceVariation)
			{
				num4 = 384400.0 * (1.0 - 0.0549 * Math.Cos(num));
			}
			s.MeanAnomalyRad = num;
			s.EccentricAnomalyRad = num2;
			s.TrueAnomalyRad = num3;
			s.EquationOfCenterDeg = Wrap180((num3 - num) / (Math.PI / 180.0));
			s.ElongationDeg = Wrap360(s.SynodicPhase01 * 360.0 + s.EquationOfCenterDeg);
			s.ArgumentOfLatitudeDeg = Wrap360(s.DraconicPhase01 * 360.0 + s.EquationOfCenterDeg);
			s.LunarLatitudeDeg = (settings.OrbitalInclination ? (Math.Asin(Math.Sin(settings.InclinationDeg * (Math.PI / 180.0)) * Math.Sin(s.ArgumentOfLatitudeDeg * (Math.PI / 180.0))) / (Math.PI / 180.0)) : 0.0);
			s.MoonDistanceKm = num4;
			s.MoonAngularRadiusDeg = Math.Asin(1737.4 / num4) / (Math.PI / 180.0);
			s.SunAngularRadiusDeg = 0.26656;
			double num5 = Math.Cos(s.ElongationDeg * (Math.PI / 180.0)) * Math.Cos(s.LunarLatitudeDeg * (Math.PI / 180.0));
			s.SunMoonSeparationDeg = Math.Acos(Clamp(num5, -1.0, 1.0)) / (Math.PI / 180.0);
			s.PhaseAngleDeg = 180.0 - s.SunMoonSeparationDeg;
			s.IlluminatedFraction = (1.0 - num5) / 2.0;
			s.IsWaxing = s.ElongationDeg < 180.0;
			s.ObserverOffsetE = s.SignedElongationDeg;
			s.ObserverOffsetB = s.LunarLatitudeDeg;
			s.ObserverMoonRadiusDeg = s.MoonAngularRadiusDeg;
			ComputeSolar(ref s);
			double num6 = Math.Asin(6378.14 / num4) / (Math.PI / 180.0);
			s.ShadowSeparationDeg = 180.0 - s.SunMoonSeparationDeg;
			s.UmbraRadiusDeg = settings.UmbraEnlargement * (num6 + 0.0024428 - s.SunAngularRadiusDeg);
			s.PenumbraRadiusDeg = settings.UmbraEnlargement * (num6 + 0.0024428 + s.SunAngularRadiusDeg);
			double num7 = Math.PI * s.MoonAngularRadiusDeg * s.MoonAngularRadiusDeg;
			s.UmbralCoverage01 = CircleOverlapArea(s.MoonAngularRadiusDeg, s.UmbraRadiusDeg, s.ShadowSeparationDeg) / num7;
			s.PenumbralCoverage01 = CircleOverlapArea(s.MoonAngularRadiusDeg, s.PenumbraRadiusDeg, s.ShadowSeparationDeg) / num7;
			s.UmbralMagnitude = (s.UmbraRadiusDeg + s.MoonAngularRadiusDeg - s.ShadowSeparationDeg) / (2.0 * s.MoonAngularRadiusDeg);
			s.PenumbralMagnitude = (s.PenumbraRadiusDeg + s.MoonAngularRadiusDeg - s.ShadowSeparationDeg) / (2.0 * s.MoonAngularRadiusDeg);
			s.LunarEclipse = ClassifyLunar(s.ShadowSeparationDeg, s.MoonAngularRadiusDeg, s.UmbraRadiusDeg, s.PenumbraRadiusDeg);
			double num8 = Math.Max(0.0, s.PenumbralCoverage01 - s.UmbralCoverage01);
			s.LunarEclipseDimming01 = Clamp(num8 * 0.5 + s.UmbralCoverage01 * 0.97, 0.0, 1.0);
			double phaseAngleDeg = s.PhaseAngleDeg;
			double num9 = 0.026 * phaseAngleDeg + 4E-09 * Math.Pow(phaseAngleDeg, 4.0);
			double num10 = 384400.0 / num4 * (384400.0 / num4);
			s.RelativeBrightness = Math.Pow(10.0, -0.4 * num9) * num10 * (1.0 - s.LunarEclipseDimming01);
			s.EarthshineFactor01 = Math.Pow(1.0 - s.IlluminatedFraction, 2.0);
			return s;
		}

		private static void ComputeSolar(ref LunarState s)
		{
			double value = Math.Cos(s.ObserverOffsetE * (Math.PI / 180.0)) * Math.Cos(s.ObserverOffsetB * (Math.PI / 180.0));
			s.SolarSeparationDeg = Math.Acos(Clamp(value, -1.0, 1.0)) / (Math.PI / 180.0);
			double sunAngularRadiusDeg = s.SunAngularRadiusDeg;
			double observerMoonRadiusDeg = s.ObserverMoonRadiusDeg;
			s.SolarObscuration01 = CircleOverlapArea(sunAngularRadiusDeg, observerMoonRadiusDeg, s.SolarSeparationDeg) / (Math.PI * sunAngularRadiusDeg * sunAngularRadiusDeg);
			s.SolarMagnitude = Math.Max(0.0, (sunAngularRadiusDeg + observerMoonRadiusDeg - s.SolarSeparationDeg) / (2.0 * sunAngularRadiusDeg));
			s.SolarPeakMagnitude = s.SolarMagnitude;
			s.SolarEclipse = ClassifySolar(s.SolarSeparationDeg, sunAngularRadiusDeg, observerMoonRadiusDeg);
		}

		private static void ApplySolarObserver(ref LunarState s, LunarSettings settings)
		{
			double signedElongationDeg = s.SignedElongationDeg;
			double num = 1.0 - SmoothStep(4.0, 16.0, Math.Abs(signedElongationDeg));
			if (num <= 0.0)
			{
				return;
			}
			long num2 = (long)Math.Round(s.AstroTimeDays / settings.SynodicPeriodDays);
			if (settings.CachedLunation != num2)
			{
				double num3 = (double)num2 * settings.SynodicPeriodDays;
				double num4 = 0.03 * settings.SynodicPeriodDays;
				double num5 = num3 - num4;
				double num6 = num3 + num4;
				for (int i = 0; i < 60; i++)
				{
					double num7 = num6 - 0.6180339887498949 * (num6 - num5);
					double num8 = num5 + 0.6180339887498949 * (num6 - num5);
					if (CalculateGeocentric(num7, settings).SunMoonSeparationDeg < CalculateGeocentric(num8, settings).SunMoonSeparationDeg)
					{
						num6 = num8;
					}
					else
					{
						num5 = num7;
					}
				}
				LunarState lunarState = CalculateGeocentric((num5 + num6) / 2.0, settings);
				double signedElongationDeg2 = lunarState.SignedElongationDeg;
				double lunarLatitudeDeg = lunarState.LunarLatitudeDeg;
				double num9 = Math.Sqrt(signedElongationDeg2 * signedElongationDeg2 + lunarLatitudeDeg * lunarLatitudeDeg);
				double num10 = Math.Asin(6378.14 / lunarState.MoonDistanceKm) / (Math.PI / 180.0);
				double num11 = Math.Min(num9, num10);
				double num12 = ((num9 > 1E-09) ? (num11 / num9) : 0.0);
				double num13 = ((num10 > 0.0) ? Math.Min(1.0, num11 / num10) : 1.0);
				settings.CachedParallaxE = (0.0 - signedElongationDeg2) * num12;
				settings.CachedParallaxB = (0.0 - lunarLatitudeDeg) * num12;
				settings.CachedObserverDistanceKm = 6378.14 * Math.Sqrt(Math.Max(0.0, 1.0 - num13 * num13));
				settings.CachedLunation = num2;
				double num14 = Math.Sqrt((signedElongationDeg2 + settings.CachedParallaxE) * (signedElongationDeg2 + settings.CachedParallaxE) + (lunarLatitudeDeg + settings.CachedParallaxB) * (lunarLatitudeDeg + settings.CachedParallaxB));
				double num15 = Math.Asin(1737.4 / (lunarState.MoonDistanceKm - settings.CachedObserverDistanceKm)) / (Math.PI / 180.0);
				settings.CachedPeakMagnitude = Math.Max(0.0, (0.26656 + num15 - num14) / 0.53312);
			}
			s.ObserverOffsetE = signedElongationDeg + settings.CachedParallaxE * num;
			s.ObserverOffsetB = s.LunarLatitudeDeg + settings.CachedParallaxB * num;
			double num16 = Math.Asin(1737.4 / (s.MoonDistanceKm - settings.CachedObserverDistanceKm)) / (Math.PI / 180.0);
			s.ObserverMoonRadiusDeg = s.MoonAngularRadiusDeg + (num16 - s.MoonAngularRadiusDeg) * num;
			ComputeSolar(ref s);
			s.SolarPeakMagnitude = settings.CachedPeakMagnitude;
		}

		public static double SmoothStep(double edge0, double edge1, double x)
		{
			double num = Clamp((x - edge0) / (edge1 - edge0), 0.0, 1.0);
			return num * num * (3.0 - 2.0 * num);
		}

		public static EclipseKind ClassifySolar(double separation, double sunRadius, double moonRadius)
		{
			if (separation >= sunRadius + moonRadius)
			{
				return EclipseKind.None;
			}
			if (moonRadius >= sunRadius && separation <= moonRadius - sunRadius)
			{
				return EclipseKind.Total;
			}
			if (sunRadius > moonRadius && separation <= sunRadius - moonRadius)
			{
				return EclipseKind.Annular;
			}
			return EclipseKind.Partial;
		}

		public static EclipseKind ClassifyLunar(double separation, double moonRadius, double umbraRadius, double penumbraRadius)
		{
			if (separation >= penumbraRadius + moonRadius)
			{
				return EclipseKind.None;
			}
			if (separation >= umbraRadius + moonRadius)
			{
				return EclipseKind.Penumbral;
			}
			if (separation <= umbraRadius - moonRadius)
			{
				return EclipseKind.Total;
			}
			return EclipseKind.Partial;
		}

		public static List<EclipseEvent> FindEclipses(double fromDays, int lunations, LunarSettings settings)
		{
			List<EclipseEvent> list = new List<EclipseEvent>();
			double synodicPeriodDays = settings.SynodicPeriodDays;
			double num = Math.Floor(fromDays / synodicPeriodDays) * synodicPeriodDays;
			for (int i = 0; i <= lunations * 2 + 1; i++)
			{
				double num2 = num + (double)i * synodicPeriodDays * 0.5;
				bool flag = i % 2 == 0;
				double num3 = 0.03 * synodicPeriodDays;
				double num4 = MinimizeSeparation(num2 - num3, num2 + num3, flag, settings);
				if (num4 < fromDays)
				{
					continue;
				}
				LunarState lunarState = Calculate(num4, settings);
				EclipseKind eclipseKind = (flag ? lunarState.SolarEclipse : lunarState.LunarEclipse);
				if (eclipseKind == EclipseKind.None)
				{
					continue;
				}
				EclipseEvent item = new EclipseEvent
				{
					IsSolar = flag,
					Kind = eclipseKind,
					MaximumDays = num4,
					Magnitude = (flag ? lunarState.SolarMagnitude : ((eclipseKind == EclipseKind.Penumbral) ? lunarState.PenumbralMagnitude : lunarState.UmbralMagnitude)),
					MoonAngularRadiusDeg = lunarState.MoonAngularRadiusDeg,
					MoonDistanceKm = lunarState.MoonDistanceKm
				};
				Func<double, bool> condition = (flag ? ((Func<double, bool>)((double t) => Calculate(t, settings).SolarEclipse != EclipseKind.None)) : ((eclipseKind == EclipseKind.Penumbral) ? ((Func<double, bool>)((double t) => Calculate(t, settings).LunarEclipse != EclipseKind.None)) : ((Func<double, bool>)delegate(double t)
				{
					EclipseKind lunarEclipse = Calculate(t, settings).LunarEclipse;
					return lunarEclipse == EclipseKind.Partial || lunarEclipse == EclipseKind.Total;
				})));
				item.PartialStartDays = FindBoundary(num4, 0.0 - num3, condition);
				item.PartialEndDays = FindBoundary(num4, num3, condition);
				if (flag || eclipseKind == EclipseKind.Penumbral)
				{
					item.PenumbralStartDays = item.PartialStartDays;
					item.PenumbralEndDays = item.PartialEndDays;
				}
				else
				{
					Func<double, bool> condition2 = (double t) => Calculate(t, settings).LunarEclipse != EclipseKind.None;
					item.PenumbralStartDays = FindBoundary(num4, 0.0 - num3, condition2);
					item.PenumbralEndDays = FindBoundary(num4, num3, condition2);
				}
				if (eclipseKind == EclipseKind.Total || eclipseKind == EclipseKind.Annular)
				{
					Func<double, bool> condition3 = (flag ? ((Func<double, bool>)delegate(double t)
					{
						EclipseKind solarEclipse = Calculate(t, settings).SolarEclipse;
						return solarEclipse == EclipseKind.Total || solarEclipse == EclipseKind.Annular;
					}) : ((Func<double, bool>)((double t) => Calculate(t, settings).LunarEclipse == EclipseKind.Total)));
					item.CentralStartDays = FindBoundary(num4, 0.0 - num3, condition3);
					item.CentralEndDays = FindBoundary(num4, num3, condition3);
				}
				else
				{
					item.CentralStartDays = (item.CentralEndDays = num4);
				}
				list.Add(item);
			}
			return list;
		}

		private static double MinimizeSeparation(double from, double to, bool solar, LunarSettings settings)
		{
			double num = from;
			double num2 = to;
			double num3 = num2 - 0.6180339887498949 * (num2 - num);
			double num4 = num + 0.6180339887498949 * (num2 - num);
			for (int i = 0; i < 60; i++)
			{
				if (SyzygyDistance(num3, solar, settings) < SyzygyDistance(num4, solar, settings))
				{
					num2 = num4;
				}
				else
				{
					num = num3;
				}
				num3 = num2 - 0.6180339887498949 * (num2 - num);
				num4 = num + 0.6180339887498949 * (num2 - num);
			}
			return (num + num2) / 2.0;
		}

		private static double SyzygyDistance(double t, bool solar, LunarSettings settings)
		{
			LunarState lunarState = Calculate(t, settings);
			if (!solar)
			{
				return lunarState.ShadowSeparationDeg;
			}
			return lunarState.SolarSeparationDeg;
		}

		private static double FindBoundary(double inside, double reach, Func<double, bool> condition)
		{
			double num = inside + reach;
			if (condition(num))
			{
				return num;
			}
			for (int i = 0; i < 40; i++)
			{
				double num2 = (inside + num) / 2.0;
				if (condition(num2))
				{
					inside = num2;
				}
				else
				{
					num = num2;
				}
			}
			return (inside + num) / 2.0;
		}

		public static double CircleOverlapArea(double r1, double r2, double distance)
		{
			if (distance >= r1 + r2)
			{
				return 0.0;
			}
			double num = Math.Min(r1, r2);
			if (distance <= Math.Abs(r1 - r2))
			{
				return Math.PI * num * num;
			}
			double num2 = distance * distance;
			double num3 = r1 * r1 * Math.Acos(Clamp((num2 + r1 * r1 - r2 * r2) / (2.0 * distance * r1), -1.0, 1.0));
			double num4 = r2 * r2 * Math.Acos(Clamp((num2 + r2 * r2 - r1 * r1) / (2.0 * distance * r2), -1.0, 1.0));
			double num5 = 0.5 * Math.Sqrt(Math.Max(0.0, (0.0 - distance + r1 + r2) * (distance + r1 - r2) * (distance - r1 + r2) * (distance + r1 + r2)));
			return num3 + num4 - num5;
		}

		public static double SolveKepler(double meanAnomaly, double eccentricity)
		{
			double num = meanAnomaly;
			for (int i = 0; i < 6; i++)
			{
				num -= (num - eccentricity * Math.Sin(num) - meanAnomaly) / (1.0 - eccentricity * Math.Cos(num));
			}
			return num;
		}

		public static double Phase01(double time, double period, double epoch01)
		{
			double num = time / period + epoch01;
			return num - Math.Floor(num);
		}

		public static double Wrap360(double degrees)
		{
			double num = degrees % 360.0;
			if (!(num < 0.0))
			{
				return num;
			}
			return num + 360.0;
		}

		public static double Wrap180(double degrees)
		{
			double num = Wrap360(degrees);
			if (!(num > 180.0))
			{
				return num;
			}
			return num - 360.0;
		}

		public static double Clamp(double value, double min, double max)
		{
			if (!(value < min))
			{
				if (!(value > max))
				{
					return value;
				}
				return max;
			}
			return min;
		}

		public static string KindName(EclipseKind kind)
		{
			return kind switch
			{
				EclipseKind.Penumbral => "penumbral", 
				EclipseKind.Partial => "partial", 
				EclipseKind.Total => "total", 
				EclipseKind.Annular => "annular", 
				_ => "none", 
			};
		}
	}
	internal sealed class LunarSettings
	{
		public double SynodicPeriodDays = 29.530588;

		public double InclinationDeg = 5.145;

		public bool EllipticalOrbit = true;

		public bool DistanceVariation = true;

		public bool OrbitalInclination = true;

		public double UmbraEnlargement = 1.02;

		internal long CachedLunation = long.MinValue;

		internal double CachedParallaxE;

		internal double CachedParallaxB;

		internal double CachedObserverDistanceKm;

		internal double CachedPeakMagnitude;

		public double TimeScale => SynodicPeriodDays / 29.530588;

		public double SiderealPeriodDays => 27.321661 * TimeScale;

		public double DraconicPeriodDays => 27.212221 * TimeScale;

		public double AnomalisticPeriodDays => 27.55455 * TimeScale;
	}
	internal struct LunarState
	{
		public double AstroTimeDays;

		public double SynodicPhase01;

		public double SiderealPhase01;

		public double DraconicPhase01;

		public double AnomalisticPhase01;

		public double MeanAnomalyRad;

		public double EccentricAnomalyRad;

		public double TrueAnomalyRad;

		public double EquationOfCenterDeg;

		public double ElongationDeg;

		public double ArgumentOfLatitudeDeg;

		public double LunarLatitudeDeg;

		public double MoonDistanceKm;

		public double MoonAngularRadiusDeg;

		public double SunAngularRadiusDeg;

		public double SunMoonSeparationDeg;

		public double PhaseAngleDeg;

		public double IlluminatedFraction;

		public bool IsWaxing;

		public double RelativeBrightness;

		public double EarthshineFactor01;

		public double ObserverOffsetE;

		public double ObserverOffsetB;

		public double ObserverMoonRadiusDeg;

		public double SolarSeparationDeg;

		public double SolarObscuration01;

		public double SolarMagnitude;

		public double SolarPeakMagnitude;

		public EclipseKind SolarEclipse;

		public double ShadowSeparationDeg;

		public double UmbraRadiusDeg;

		public double PenumbraRadiusDeg;

		public double PenumbralMagnitude;

		public double UmbralMagnitude;

		public double PenumbralCoverage01;

		public double UmbralCoverage01;

		public EclipseKind LunarEclipse;

		public double LunarEclipseDimming01;

		public double SignedElongationDeg => LunarModel.Wrap180(ElongationDeg);

		public double LibrationLongitudeDeg => 0.0 - EquationOfCenterDeg;

		public double LibrationLatitudeDeg => 6.68 * Math.Sin(ArgumentOfLatitudeDeg * Math.PI / 180.0);
	}
	internal sealed class LunarSurface
	{
		public const string AlbedoFile = "moon_albedo.png";

		public const string NormalFile = "moon_normal.png";

		private readonly byte[] albedo;

		private readonly int albedoWidth;

		private readonly int albedoHeight;

		private readonly byte[] normal;

		private readonly int normalWidth;

		private readonly int normalHeight;

		public bool HasAlbedo => albedo != null;

		public bool HasHeight => normal != null;

		public string Description { get; private set; }

		private LunarSurface(byte[] albedo, int albedoWidth, int albedoHeight, byte[] normal, int normalWidth, int normalHeight, string description)
		{
			this.albedo = albedo;
			this.albedoWidth = albedoWidth;
			this.albedoHeight = albedoHeight;
			this.normal = normal;
			this.normalWidth = normalWidth;
			this.normalHeight = normalHeight;
			Description = description;
		}

		public static LunarSurface Load(string folder, int maximumWidth)
		{
			int width;
			int height;
			string note;
			byte[] array = ReadGrey(Path.Combine(folder, "moon_albedo.png"), maximumWidth, out width, out height, out note);
			if (array == null)
			{
				Plugin.Log.LogInfo((object)("Lunar maps unavailable (" + note + "); using the procedural surface."));
				return null;
			}
			int width2;
			int height2;
			string note2;
			byte[] array2 = ReadNormal(Path.Combine(folder, "moon_normal.png"), maximumWidth, out width2, out height2, out note2);
			string description = $"albedo {width}x{height}" + ((array2 != null) ? $", relief {width2}x{height2}" : (", no relief (" + note2 + ")"));
			return new LunarSurface(array, width, height, array2, width2, height2, description);
		}

		private static byte[] ReadNormal(string path, int maximumWidth, out int width, out int height, out string note)
		{
			return Read(path, maximumWidth, grey: false, out width, out height, out note);
		}

		private static byte[] ReadGrey(string path, int maximumWidth, out int width, out int height, out string note)
		{
			return Read(path, maximumWidth, grey: true, out width, out height, out note);
		}

		private static byte[] Read(string path, int maximumWidth, bool grey, out int width, out int height, out string note)
		{
			//IL_0031: 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_003f: Expected O, but got Unknown
			//IL_010c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0111: Unknown result type (might be due to invalid IL or missing references)
			//IL_0121: Unknown result type (might be due to invalid IL or missing references)
			//IL_012b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0139: Unknown result type (might be due to invalid IL or missing references)
			//IL_0118: Unknown result type (might be due to invalid IL or missing references)
			//IL_014b: Unknown result type (might be due to invalid IL or missing references)
			width = (height = 0);
			note = null;
			if (!File.Exists(path))
			{
				note = Path.GetFileName(path) + " not found";
				return null;
			}
			Texture2D val = null;
			try
			{
				val = new Texture2D(2, 2, (TextureFormat)4, false, true)
				{
					hideFlags = (HideFlags)61
				};
				if (!LoadImage(val, File.ReadAllBytes(path)))
				{
					note = Path.GetFileName(path) + " could not be read";
					return null;
				}
				int num = Mathf.Max(1, Mathf.CeilToInt((float)((Texture)val).width / (float)maximumWidth));
				width = ((Texture)val).width / num;
				height = ((Texture)val).height / num;
				Color32[] pixels = val.GetPixels32();
				int num2 = (grey ? 1 : 2);
				byte[] array = new byte[width * height * num2];
				for (int i = 0; i < height; i++)
				{
					for (int j = 0; j < width; j++)
					{
						int num3 = 0;
						int num4 = 0;
						int num5 = 0;
						for (int k = 0; k < num; k++)
						{
							int num6 = i * num + k;
							if (num6 >= ((Texture)val).height)
							{
								continue;
							}
							for (int l = 0; l < num; l++)
							{
								int num7 = j * num + l;
								if (num7 < ((Texture)val).width)
								{
									Color32 val2 = pixels[num6 * ((Texture)val).width + num7];
									num3 += (grey ? (val2.r * 77 + val2.g * 150 + val2.b * 29 >> 8) : val2.r);
									num4 += val2.g;
									num5++;
								}
							}
						}
						int num8 = (i * width + j) * num2;
						array[num8] = (byte)((num5 > 0) ? ((uint)(num3 / num5)) : 0u);
						if (!grey)
						{
							array[num8 + 1] = (byte)((num5 > 0) ? ((uint)(num4 / num5)) : 0u);
						}
					}
				}
				return array;
			}
			catch (Exception ex)
			{
				note = Path.GetFileName(path) + ": " + ex.Message;
				return null;
			}
			finally
			{
				if ((Object)(object)val != (Object)null)
				{
					Object.Destroy((Object)(object)val);
				}
			}
		}

		public float SampleAlbedo(float x, float y, float z, float longitudeOffsetDeg)
		{
			SphereToUv(x, y, z, longitudeOffsetDeg, out var u, out var v);
			return Bilinear(albedo, albedoWidth, albedoHeight, u, v) * (1f / 128f);
		}

		public void SampleSlope(float x, float y, float z, float longitudeOffsetDeg, float strength, out float east, out float north)
		{
			east = (north = 0f);
			if (normal != null)
			{
				SphereToUv(x, y, z, longitudeOffsetDeg, out var u, out var v);
				east = (Bilinear(normal, normalWidth, normalHeight, u, v, 2) / 127.5f - 1f) * strength;
				north = (Bilinear(normal, normalWidth, normalHeight, u, v, 2, 1) / 127.5f - 1f) * strength;
			}
		}

		private static bool LoadImage(Texture2D texture, byte[] data)
		{
			MethodInfo method = typeof(ImageConversion).GetMethod("LoadImage", BindingFlags.Static | BindingFlags.Public, null, new Type[3]
			{
				typeof(Texture2D),
				typeof(byte[]),
				typeof(bool)
			}, null);
			if (method == null)
			{
				return false;
			}
			return (bool)method.Invoke(null, new object[3] { texture, data, false });
		}

		private static void SphereToUv(float x, float y, float z, float longitudeOffsetDeg, out float u, out float v)
		{
			float num = Mathf.Atan2(x, z) * 57.29578f + longitudeOffsetDeg;
			num = Mathf.Repeat(num + 180f, 360f) - 180f;
			u = (num + 180f) / 360f;
			v = 0.5f + Mathf.Asin(Mathf.Clamp(y, -1f, 1f)) / (float)Math.PI;
		}

		private static float Bilinear(byte[] map, int width, int height, float u, float v, int stride = 1, int channel = 0)
		{
			u -= Mathf.Floor(u);
			float num = u * (float)width - 0.5f;
			float num2 = Mathf.Clamp(v, 0f, 1f) * (float)height - 0.5f;
			int num3 = Mathf.FloorToInt(num);
			int num4 = Mathf.Clamp(Mathf.FloorToInt(num2), 0, height - 1);
			int num5 = Mathf.Clamp(num4 + 1, 0, height - 1);
			float num6 = num - (float)num3;
			float num7 = num2 - (float)num4;
			int num8 = (num3 % width + width) % width;
			int num9 = (num8 + 1) % width;
			float num10 = (float)(int)map[(num4 * width + num8) * stride + channel] * (1f - num6) + (float)(int)map[(num4 * width + num9) * stride + channel] * num6;
			float num11 = (float)(int)map[(num5 * width + num8) * stride + channel] * (1f - num6) + (float)(int)map[(num5 * width + num9) * stride + channel] * num6;
			return num10 * (1f - num7) + num11 * num7;
		}
	}
	internal static class MathF
	{
		public const float PI = (float)Math.PI;
	}
	internal enum MoonPathMode
	{
		Astronomical,
		Vanilla
	}
	internal struct MoonSnapshot
	{
		public bool Valid;

		public LunarState State;

		public Vector3 SunDir;

		public Vector3 MoonDir;

		public Vector3 MoonTrueDir;

		public Vector3 PoleAxis;

		public Quaternion QuadRotation;

		public Vector3 EclipseMoonDir;

		public Quaternion EclipseRotation;

		public float DisplayScale;

		public float MoonRadiusDisplayDeg;

		public float SunRadiusDisplayDeg;

		public Vector2 SunDirection2D;

		public Vector2 SunCenterOnDisc;

		public float SunRadiusOnDisc;

		public Vector2 ShadowCenterOnDisc;

		public float UmbraOnDisc;

		public float PenumbraOnDisc;

		public float MoonAltitudeDeg;

		public float SunAltitudeDeg;

		public float NightOpacity;

		public float SkyFogVisibility;

		public float HorizonFade;

		public float Moonlight01;

		public double VisualSolarObscuration01;
	}
	internal enum MoonSurfaceMode
	{
		Procedural,
		Realistic
	}
	internal sealed class MoonTextures : IDisposable
	{
		public const float DiscRadiusUv = 0.47f;

		private readonly int size;

		private readonly float[] nx;

		private readonly float[] ny;

		private readonly float[] nz;

		private readonly float[] edge;

		private float[] albedo;

		private float[] pendingAlbedo;

		private float[] normalX;

		private float[] normalY;

		private float[] normalZ;

		private float[] pendingNormalX;

		private float[] pendingNormalY;

		private float[] pendingNormalZ;

		private LunarSurface surface;

		private MoonSurfaceMode mode;

		private MoonSurfaceMode pendingMode;

		private float surfaceLongitudeOffset;

		private float reliefStrength = 1f;

		private bool librationJobRunning;

		private float appliedLibrationLon;

		private float appliedLibrationLat;

		private float pendingLibrationLon;

		private float pendingLibrationLat;

		private readonly float[] roughness;

		private readonly Color32[] buffer;

		private readonly Color32[] maskBuffer;

		private const float KneeStart = 0.22f;

		private const float KneeRange = 0.12f;

		public Texture2D Albedo { get; private set; }

		public Texture2D Disc { get; private set; }

		public Texture2D Lit { get; private set; }

		public Texture2D LitMask { get; private set; }

		public Texture2D SunOccluder { get; private set; }

		public Texture2D Corona { get; private set; }

		public int Size => size;

		public MoonSurfaceMode Mode => mode;

		public MoonTextures(int size)
		{
			//IL_026f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0274: 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_02d6: Unknown result type (might be due to invalid IL or missing references)
			this.size = size;
			int num = size * size;
			nx = new float[num];
			ny = new float[num];
			nz = new float[num];
			edge = new float[num];
			albedo = new float[num];
			roughness = new float[num];
			buffer = (Color32[])(object)new Color32[num];
			float num2 = 1f / ((float)size * 0.47f);
			for (int i = 0; i < size; i++)
			{
				for (int j = 0; j < size; j++)
				{
					int num3 = i * size + j;
					float num4 = (((float)j + 0.5f) / (float)size - 0.5f) / 0.47f;
					float num5 = (((float)i + 0.5f) / (float)size - 0.5f) / 0.47f;
					float num6 = Mathf.Sqrt(num4 * num4 + num5 * num5);
					edge[num3] = Mathf.Clamp01((1f - num6) / (1.2f * num2) + 0.5f);
					float num7 = ((num6 > 1f) ? (num4 / num6) : num4);
					float num8 = ((num6 > 1f) ? (num5 / num6) : num5);
					nx[num3] = num7;
					ny[num3] = num8;
					nz[num3] = Mathf.Sqrt(Mathf.Max(0f, 1f - num7 * num7 - num8 * num8));
					roughness[num3] = Noise(num7 * 12f, num8 * 12f, 11) - 0.5f + 0.35f * (Noise(num7 * 30f, num8 * 30f, 12) - 0.5f);
				}
			}
			albedo = ComputeAlbedo(0f, 0f);
			Albedo = CreateTexture("MoonPhases_Albedo");
			Lit = CreateTexture("MoonPhases_Lit");
			LitMask = CreateTexture("MoonPhases_LitMask");
			maskBuffer = (Color32[])(object)new Color32[num];
			SunOccluder = CreateTexture("MoonPhases_SunOccluder");
			Corona = CreateTexture("MoonPhases_Corona");
			for (int k = 0; k < num; k++)
			{
				byte b = ToByte(edge[k]);
				byte b2 = ToByte(albedo[k]);
				buffer[k] = new Color32(b2, b2, b2, b);
			}
			Upload(Albedo);
			BuildCorona();
			Disc = CreateTexture("MoonPhases_Disc");
			for (int l = 0; l < num; l++)
			{
				buffer[l] = new Color32(byte.MaxValue, byte.MaxValue, byte.MaxValue, ToByte(edge[l]));
			}
			Upload(Disc);
			Array.Clear(buffer, 0, buffer.Length);
			Upload(Lit);
			UploadFrom(LitMask, maskBuffer);
			Upload(SunOccluder);
		}

		public bool SetSurface(LunarSurface newSurface, MoonSurfaceMode newMode, float longitudeOffsetDeg, float relief)
		{
			if (newMode != MoonSurfaceMode.Procedural && (newSurface == null || !newSurface.HasAlbedo))
			{
				newMode = MoonSurfaceMode.Procedural;
			}
			bool num = newMode != mode || newSurface != surface || !Mathf.Approximately(longitudeOffsetDeg, surfaceLongitudeOffset) || !Mathf.Approximately(relief, reliefStrength);
			surface = newSurface;
			mode = newMode;
			surfaceLongitudeOffset = longitudeOffsetDeg;
			reliefStrength = relief;
			if (num)
			{
				appliedLibrationLon = float.NaN;
			}
			return num;
		}

		public bool UpdateLibration(float longitudeDeg, float latitudeDeg)
		{
			//IL_00be: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c3: Unknown result type (might be due to invalid IL or missing references)
			float[] array = Interlocked.Exchange(ref pendingAlbedo, null);
			if (array != null)
			{
				albedo = array;
				normalX = pendingNormalX;
				normalY = pendingNormalY;
				normalZ = pendingNormalZ;
				pendingNormalX = (pendingNormalY = (pendingNormalZ = null));
				appliedLibrationLon = pendingLibrationLon;
				appliedLibrationLat = pendingLibrationLat;
				librationJobRunning = false;
				for (int i = 0; i < buffer.Length; i++)
				{
					byte b = ToByte(albedo[i]);
					buffer[i] = new Color32(b, b, b, ToByte(edge[i]));
				}
				Upload(Albedo);
				return true;
			}
			if (!librationJobRunning && (float.IsNaN(appliedLibrationLon) || Mathf.Abs(longitudeDeg - appliedLibrationLon) > 0.5f || Mathf.Abs(latitudeDeg - appliedLibrationLat) > 0.5f))
			{
				librationJobRunning = true;
				pendingLibrationLon = longitudeDeg;
				pendingLibrationLat = latitudeDeg;
				pendingMode = mode;
				ThreadPool.QueueUserWorkItem(delegate
				{
					float[] value = ComputeAlbedo(longitudeDeg, latitudeDeg);
					Interlocked.Exchange(ref pendingAlbedo, value);
				});
			}
			return false;
		}

		private float[] ComputeAlbedo(float longitudeDeg, float latitudeDeg)
		{
			MoonSurfaceMode num = pendingMode;
			LunarSurface lunarSurface = surface;
			bool flag = num != MoonSurfaceMode.Procedural && lunarSurface != null && lunarSurface.HasAlbedo;
			bool flag2 = flag && reliefStrength > 0.001f && lunarSurface.HasHeight;
			float[] array = new float[nx.Length];
			float[] array2 = (flag2 ? new float[nx.Length] : null);
			float[] array3 = (flag2 ? new float[nx.Length] : null);
			float[] array4 = (flag2 ? new float[nx.Length] : null);
			float num2 = Mathf.Cos(latitudeDeg * ((float)Math.PI / 180f));
			float num3 = Mathf.Sin(latitudeDeg * ((float)Math.PI / 180f));
			float num4 = Mathf.Cos(longitudeDeg * ((float)Math.PI / 180f));
			float num5 = Mathf.Sin(longitudeDeg * ((float)Math.PI / 180f));
			for (int i = 0; i < array.Length; i++)
			{
				if (!(edge[i] <= 0f))
				{
					float y = ny[i] * num2 - nz[i] * num3;
					float num6 = ny[i] * num3 + nz[i] * num2;
					float x = nx[i] * num4 + num6 * num5;
					float z = (0f - nx[i]) * num5 + num6 * num4;
					array[i] = (flag ? Mathf.Clamp(lunarSurface.SampleAlbedo(x, y, z, surfaceLongitudeOffset), 0.2f, 1.6f) : SurfaceAlbedo(x, y, z, nz[i]));
					if (flag2)
					{
						lunarSurface.SampleSlope(x, y, z, surfaceLongitudeOffset, reliefStrength, out var east, out var north);
						float num7 = Mathf.Max(1E-05f, Mathf.Sqrt(nz[i] * nz[i] + nx[i] * nx[i]));
						float num8 = nz[i] / num7;
						float num9 = (0f - nx[i]) / num7;
						float num10 = (0f - ny[i]) * nx[i] / num7;
						float num11 = num7;
						float num12 = (0f - ny[i]) * nz[i] / num7;
						east = Mathf.Clamp(east, -0.8f, 0.8f);
						north = Mathf.Clamp(north, -0.8f, 0.8f);
						float num13 = nx[i] + east * num8 + north * num10;
						float num14 = ny[i] + north * num11;
						float num15 = nz[i] + east * num9 + north * num12;
						float num16 = 1f / Mathf.Max(1E-05f, Mathf.Sqrt(num13 * num13 + num14 * num14 + num15 * num15));
						array2[i] = num13 * num16;
						array3[i] = num14 * num16;
						array4[i] = num15 * num16;
					}
				}
			}
			pendingNormalX = array2;
			pendingNormalY = array3;
			pendingNormalZ = array4;
			return array;
		}

		public void UpdateLit(LitDiscParameters p)
		{
			//IL_0031: 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)
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			//IL_0040: Unknown result type (might be due to invalid IL or missing references)
			//IL_03a6: Unknown result type (might be due to invalid IL or missing references)
			//IL_03ab: Unknown result type (might be due to invalid IL or missing references)
			//IL_03c9: Unknown result type (might be due to invalid IL or missing references)
			//IL_03ce: Unknown result type (might be due to invalid IL or missing references)
			//IL_0259: Unknown result type (might be due to invalid IL or missing references)
			//IL_025b: Unknown result type (might be due to invalid IL or missing references)
			//IL_025f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0275: 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_0285: Unknown result type (might be due to invalid IL or missing references)
			//IL_02b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_02c8: Unknown result type (might be due to invalid IL or missing references)
			//IL_02dd: Unknown result type (might be due to invalid IL or missing references)
			float num = p.PhaseAngleDeg * ((float)Math.PI / 180f);
			float num2 = Mathf.Sin(num);
			Vector2 val = ((((Vector2)(ref p.SunDirection2D)).sqrMagnitude > 1E-08f) ? ((Vector2)(ref p.SunDirection2D)).normalized : Vector2.right);
			float num3 = num2 * val.x;
			float num4 = num2 * val.y;
			float num5 = Mathf.Cos(num);
			float num6 = Mathf.Max(0.002f, p.TerminatorSoftness);
			Color val2 = default(Color);
			((Color)(ref val2))..ctor(1f, 0.52f, 0.3f);
			Color val3 = default(Color);
			((Color)(ref val3))..ctor(0.78f, 0.24f, 0.1f);
			for (int i = 0; i < buffer.Length; i++)
			{
				float num7 = ((normalX != null) ? (normalX[i] * num3 + normalY[i] * num4 + normalZ[i] * num5 + roughness[i] * num6 * 0.6f) : (nx[i] * num3 + ny[i] * num4 + nz[i] * num5 + roughness[i] * num6 * 0.6f));
				float num8 = SmoothStep(0f - num6, num6, num7);
				float num9 = Mathf.Max(0f, num7);
				float num10 = ((num9 > 0f) ? Mathf.Min(2f, 2f * num9 / (num9 + nz[i] + 0.02f)) : 0f);
				float num11 = albedo[i] * num10 * 0.5f;
				float value = num11;
				float value2 = num11;
				float value3 = num11;
				if (p.Eclipse)
				{
					float num12 = nx[i] - p.ShadowCenter.x;
					float num13 = ny[i] - p.ShadowCenter.y;
					float num14 = Mathf.Sqrt(num12 * num12 + num13 * num13);
					float num15 = 1f - Mathf.Clamp01((num14 - p.UmbraRadius) / Mathf.Max(0.001f, p.PenumbraRadius - p.UmbraRadius));
					num15 = num15 * num15 * (3f - 2f * num15);
					float num16 = 1f - num15;
					float num17 = SmoothStep(p.UmbraRadius + 0.1f, p.UmbraRadius - 0.02f, num14);
					float num18 = Mathf.Clamp01(1f - num14 / Mathf.Max(0.001f, p.UmbraRadius));
					Color val4 = Color.Lerp(val2, val3, num18) * Mathf.Lerp(0.14f, 0.035f, num18) * p.TotalityBrightness;
					float num19 = albedo[i] * 0.5f * Mathf.Max(0.35f, nz[i]);
					value = num11 * num16 + num19 * val4.r * num17;
					value2 = num11 * num16 + num19 * val4.g * num17;
					value3 = num11 * num16 + num19 * val4.b * num17;
					float num20 = SmoothStep(p.UmbraRadius + 0.18f, p.UmbraRadius + 0.02f, num14) * (1f - num17);
					value *= 1f - 0.3f * num20;
					value2 *= 1f - 0.05f * num20;
					value3 *= 1f + 0.12f * num20;
					num8 = Mathf.Max(num8, num17);
				}
				value = Knee(value);
				value2 = Knee(value2);
				value3 = Knee(value3);
				byte b = ToByte(num8 * edge[i]);
				buffer[i] = new Color32(ToByte(value), ToByte(value2), ToByte(value3), b);
				maskBuffer[i] = new Color32(byte.MaxValue, byte.MaxValue, byte.MaxValue, b);
			}
			Upload(Lit);
			UploadFrom(LitMask, maskBuffer);
		}

		public void UpdateSunOccluder(Vector2 sunCenter, float sunRadius)
		{
			//IL_004c: 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_00ca: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cf: 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_003a: Unknown result type (might be due to invalid IL or missing references)
			float num = 1f / ((float)size * 0.47f);
			for (int i = 0; i < buffer.Length; i++)
			{
				if (edge[i] <= 0f)
				{
					buffer[i] = new Color32((byte)0, (byte)0, (byte)0, (byte)0);
					continue;
				}
				float num2 = nx[i] - sunCenter.x;
				float num3 = ny[i] - sunCenter.y;
				float num4 = Mathf.Sqrt(num2 * num2 + num3 * num3);
				float num5 = Mathf.Clamp01((sunRadius - num4) / (1.5f * num) + 0.5f);
				float num6 = 1f - SmoothStep(sunRadius, sunRadius * 2f, num4);
				num6 *= num6;
				num5 = Mathf.Max(num5, num6);
				buffer[i] = new Color32((byte)6, (byte)7, (byte)10, ToByte(num5 * edge[i]));
			}
			Upload(SunOccluder);
		}

		private void BuildCorona()
		{
			//IL_0130: Unknown result type (might be due to invalid IL or missing references)
			//IL_0135: Unknown result type (might be due to invalid IL or missing references)
			for (int i = 0; i < size; i++)
			{
				for (int j = 0; j < size; j++)
				{
					float num = (((float)j + 0.5f) / (float)size - 0.5f) * 8f;
					float num2 = (((float)i + 0.5f) / (float)size - 0.5f) * 8f;
					float num3 = Mathf.Sqrt(num * num + num2 * num2);
					float num4 = Mathf.Atan2(num2, num);
					float num5 = 0.55f + 0.45f * Noise(Mathf.Cos(num4) * 3f + 7f, Mathf.Sin(num4) * 3f + 7f, 5) + 0.25f * Noise(Mathf.Cos(num4) * 9f + 3f, Mathf.Sin(num4) * 9f + 3f, 6);
					float num6 = ((num3 < 1f) ? 1f : (Mathf.Pow(num3, -2.6f) * num5));
					float num7 = Mathf.Clamp01((4f - num3) / 1.5f);
					float value = Mathf.Clamp01(num6 * num7);
					buffer[i * size + j] = new Color32((byte)242, (byte)246, byte.MaxValue, ToByte(value));
				}
			}
			Upload(Corona);
		}

		private static float SurfaceAlbedo(float x, float y, float z, float viewZ)
		{
			float num = 0f;
			num = Mathf.Max(num, Blob(x, y, -0.33f, 0.47f, 0.27f, 0.23f));
			num = Mathf.Max(num, Blob(x, y, -0.6f, 0.1f, 0.26f, 0.42f));
			num = Mathf.Max(num, Blob(x, y, 0.22f, 0.43f, 0.17f, 0.15f));
			num = Mathf.Max(num, Blob(x, y, 0.4f, 0.14f, 0.21f, 0.16f));
			num = Mathf.Max(num, Blob(x, y, 0.77f, 0.3f, 0.09f, 0.11f));
			num = Mathf.Max(num, Blob(x, y, 0.62f, -0.13f, 0.12f, 0.17f));
			num = Mathf.Max(num, Blob(x, y, 0.4f, -0.27f, 0.09f, 0.09f));
			num = Mathf.Max(num, Blob(x, y, -0.18f, -0.36f, 0.16f, 0.12f));
			num = Mathf.Max(num, Blob(x, y, -0.47f, -0.42f, 0.09f, 0.09f));
			num = Mathf.Max(num, Blob(x, y, 0.02f, 0.7f, 0.36f, 0.07f) * 0.45f);
			num = Mathf.Max(num, Blob(x, y, 0.05f, 0.18f, 0.1f, 0.08f) * 0.7f);
			num *= 0.75f + 0.5f * Noise(x * 6f, y * 6f, 3);
			num *= SmoothStep(-0.05f, 0.2f, z);
			float num2 = 0.5f * (Noise(x * 9f, y * 9f, 7) - 0.5f) + 0.35f * (Noise(x * 22f, y * 22f, 1) - 0.5f) + 0.25f * (Noise(x * 55f, y * 55f, 2) - 0.5f);
			float num3 = 1f - 0.38f * Mathf.Clamp01(num) + 0.1f * num2;
			float num4 = Mathf.Exp((0f - ((x + 0.15f) * (x + 0.15f) + (y + 0.72f) * (y + 0.72f))) / 0.0006f);
			float num5 = Mathf.Exp((0f - ((x + 0.33f) * (x + 0.33f) + (y - 0.18f) * (y - 0.18f))) / 0.0005f);
			return Mathf.Clamp((num3 + (0.25f * num4 + 0.15f * num5) + 0.04f * (1f - viewZ)) * 0.92f, 0.3f, 1f);
		}

		private static float Blob(float x, float y, float cx, float cy, float rx, float ry)
		{
			float num = x + 0.06f * (Noise(x * 5f + cx * 7f, y * 5f, 21) - 0.5f);
			float num2 = y + 0.06f * (Noise(x * 5f, y * 5f + cy * 7f, 22) - 0.5f);
			float num3 = (num - cx) / rx;
			float num4 = (num2 - cy) / ry;
			float num5 = num3 * num3 + num4 * num4;
			return 1f - SmoothStep(0.35f, 1.5f, num5 + 0.5f * (Noise(x * 11f + cx * 13f, y * 11f + cy * 13f, 4) - 0.5f));
		}

		private static float Noise(float x, float y, int seed)
		{
			int num = Mathf.FloorToInt(x);
			int num2 = Mathf.FloorToInt(y);
			float num3 = x - (float)num;
			float num4 = y - (float)num2;
			num3 = num3 * num3 * (3f - 2f * num3);
			num4 = num4 * num4 * (3f - 2f * num4);
			float num5 = Hash(num, num2, seed);
			float num6 = Hash(num + 1, num2, seed);
			float num7 = Mathf.Lerp(Hash(num, num2 + 1, seed), Hash(num + 1, num2 + 1, seed), num3);
			return Mathf.Lerp(Mathf.Lerp(num5, num6, num3), num7, num4);
		}

		private static float Hash(int x, int y, int seed)
		{
			int num = x * 374761393 + y * 668265263 + seed * 144665;
			int num2 = (num ^ (num >>> 13)) * 1274126177;
			return (float)(uint)((num2 ^ (num2 >>> 16)) & 0xFFFFFF) / 16777215f;
		}

		private static float SmoothStep(float edge0, float edge1, float x)
		{
			float num = Mathf.Clamp01((x - edge0) / (edge1 - edge0));
			return num * num * (3f - 2f * num);
		}

		private static float Knee(float value)
		{
			if (value <= 0.22f)
			{
				return value;
			}
			return 0.22f + 0.12f * (1f - Mathf.Exp((0f - (value - 0.22f)) / 0.12f));
		}

		private static byte ToByte(float value)
		{
			return (byte)Mathf.Clamp(Mathf.RoundToInt(value * 255f), 0, 255);
		}

		private Texture2D CreateTexture(string name)
		{
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: Expected O, but got Unknown
			return new Texture2D(size, size, (TextureFormat)4, true, true)
			{
				name = name,
				filterMode = (FilterMode)2,
				wrapMode = (TextureWrapMode)1,
				anisoLevel = 1,
				hideFlags = (HideFlags)61
			};
		}

		private static void UploadFrom(Texture2D texture, Color32[] pixels)
		{
			texture.SetPixels32(pixels);
			texture.Apply(true, false);
		}

		private void Upload(Texture2D texture)
		{
			texture.SetPixels32(buffer);
			texture.Apply(true, false);
		}

		public void Dispose()
		{
			DestroyTexture(Albedo);
			DestroyTexture(Disc);
			DestroyTexture(Lit);
			DestroyTexture(LitMask);
			DestroyTexture(SunOccluder);
			DestroyTexture(Corona);
			Texture2D val = (Corona = null);
			Texture2D val3 = val;
			val = (SunOccluder = val3);
			Texture2D val5 = val;
			val = (LitMask = val5);
			Texture2D val7 = val;
			val = (Lit = val7);
			Texture2D val9 = val;
			val = (Disc = val9);
			Texture2D val11 = val;
			Albedo = val11;
		}

		private static void DestroyTexture(Texture2D texture)
		{
			if ((Object)(object)texture != (Object)null)
			{
				Object.Destroy((Object)(object)texture);
			}
		}
	}
	[BepInPlugin("com.codex.valheim.moonphases", "Moon Phases", "1.0.1")]
	[BepInProcess("valheim.exe")]
	public sealed class Plugin : BaseUnityPlugin
	{
		[Serializable]
		[CompilerGenerated]
		private sealed class <>c
		{
			public static readonly <>c <>9 = new <>c();

			public static ConsoleOptionsFetcher <>9__90_0;

			public static ConsoleOptionsFetcher <>9__90_1;

			public static ConsoleOptionsFetcher <>9__90_3;

			internal List<string> <RegisterCommands>b__90_0()
			{
				return new List<string> { "astronomical", "vanilla" };
			}

			internal List<string> <RegisterCommands>b__90_1()
			{
				return new List<string> { "realistic", "procedural" };
			}

			internal List<string> <RegisterCommands>b__90_3()
			{
				return new List<string> { "dawn", "noon", "dusk", "midnight" };
			}
		}

		public const string PluginGuid = "com.codex.valheim.moonphases";

		public const string PluginName = "Moon Phases";

		public const string PluginVersion = "1.0.1";

		private static readonly string[] PhaseNames = new string[8] { "New moon", "Waxing crescent", "First quarter", "Waxing gibbous", "Full moon", "Waning gibbous", "Last quarter", "Waning crescent" };

		private ConfigEntry<bool> enabledSetting;

		private ConfigEntry<KeyCode> toggleKeySetting;

		private ConfigEntry<MoonPathMode> moonPathSetting;

		private ConfigEntry<MoonSurfaceMode> moonSurfaceSetting;

		private ConfigEntry<float> moonSurfaceReliefSetting;

		private ConfigEntry<float> moonSizeSetting;

		private ConfigEntry<float> brightnessSetting;

		private ConfigEntry<bool> eclipsesSetting;

		private ConfigEntry<float> solarTotalitySetting;

		private ConfigEntry<bool> eclipseLightingSetting;

		private ConfigEntry<bool> coronaSetting;

		private ConfigEntry<bool> moonlightSetting;

		private ConfigEntry<bool> moonlightFollowsMoonSetting;

		private ConfigEntry<float> nightLightSetting;

		private ConfigEntry<float> nightAmbientSetting;

		private ConfigEntry<float> nightFogSetting;

		private ConfigEntry<float> cycleLengthSetting;

		private ConfigEntry<double> epochOffsetSetting;

		private ConfigEntry<float> inclinationSetting;

		private ConfigEntry<bool> ellipticalOrbitSetting;

		private ConfigEntry<bool> distanceVariationSetting;

		private ConfigEntry<bool> orbitalInclinationSetting;

		private ConfigEntry<bool> librationSetting;

		private ConfigEntry<bool> earthshineSetting;

		private ConfigEntry<bool> atmosphericTintSetting;

		private ConfigEntry<float> moonlightGammaSetting;

		private ConfigEntry<float> solarDiscScaleSetting;

		private ConfigEntry<float> moonSurfaceLongitudeSetting;

		private ConfigEntry<float> terminatorSoftnessSetting;

		private ConfigEntry<float> earthshineBrightnessSetting;

		private ConfigEntry<float> bloodMoonBrightnessSetting;

		private ConfigEntry<float> daytimeOpacitySetting;

		private ConfigEntry<float> blueTintSetting;

		private ConfigEntry<int> textureSizeSetting;

		private Harmony harmony;

		private FileSystemWatcher configWatcher;

		private long configChangedAtTicks;

		private long configHandledAtTicks;

		private bool loadingConfigFile;

		private readonly VanillaSkybox vanillaSky = new VanillaSkybox();

		private SkyMoonRenderer skyRenderer;

		private LunarSettings lunarSettings = new LunarSettings();

		private LunarSurface lunarSurface;

		private bool surfaceLoaded;

		private bool rendererFailed;

		private string rendererError;

		private MoonSnapshot snapshot;

		private int snapshotFrame = -1;

		private float snapshotDayFraction = -1f;

		private bool visualsApplied;

		private int lastSkyId;

		private bool suspended;

		private const double SetDayLeadSeconds = 10.0;

		internal static Plugin Instance { get; private set; }

		internal static ManualLogSource Log { get; private set; }

		internal PluginSettings Settings { get; } = new PluginSettings();

		internal bool Active
		{
			get
			{
				if (Settings.Enabled)
				{
					return !suspended;
				}
				return false;
			}
		}

		internal bool LightingActive
		{
			get
			{
				if (Active)
				{
					if (!Settings.Moonlight)
					{
						if (Settings.Eclipses)
						{
							return Settings.SolarEclipseLighting;
						}
						return false;
					}
					return true;
				}
				return false;
			}
		}

		private void Awake()
		{
			//IL_003b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0045: Expected O, but got Unknown
			Instance = this;
			Log = ((BaseUnityPlugin)this).Logger;
			BindConfig();
			ReloadSettings(recreateTextures: false);
			((BaseUnityPlugin)this).Config.SettingChanged += OnConfigSettingChanged;
			harmony = new Harmony("com.codex.valheim.moonphases");
			SceneLighting.Install(harmony);
			RegisterCommands();
			StartConfigWatcher();
			((BaseUnityPlugin)this).Logger.LogInfo((object)("Moon Phases 1.0.1 loaded; " + SceneLighting.Describe() + "."));
		}

		private void OnConfigSettingChanged(object sender, SettingChangedEventArgs args)
		{
			if (!loadingConfigFile)
			{
				ReloadSettings((object)args.ChangedSetting == textureSizeSetting);
			}
		}

		private void StartConfigWatcher()
		{
			string configFilePath = ((BaseUnityPlugin)this).Config.ConfigFilePath;
			try
			{
				configWatcher = new FileSystemWatcher(Path.GetDirectoryName(configFilePath), Path.GetFileName(configFilePath));
				configWatcher.NotifyFilter = NotifyFilters.FileName | NotifyFilters.Size | NotifyFilters.LastWrite | NotifyFilters.CreationTime;
				configWatcher.Changed += OnConfigFileChanged;
				configWatcher.Created += OnConfigFileChanged;
				configWatcher.Renamed += OnConfigFileChanged;
				configWatcher.EnableRaisingEvents = true;
			}
			catch (Exception ex)
			{
				configWatcher?.Dispose();
				configWatcher = null;
				((BaseUnityPlugin)this).Logger.LogWarning((object)("Could not watch config file: " + ex.Message));
			}
		}

		private void OnConfigFileChanged(object sender, FileSystemEventArgs args)
		{
			Interlocked.Exchange(ref configChangedAtTicks, DateTime.UtcNow.Ticks);
		}

		private void ReloadWatchedConfig()
		{
			long num = Interlocked.Read(in configChangedAtTicks);
			if (num == 0L || num == configHandledAtTicks || DateTime.UtcNow.Ticks - num < TimeSpan.FromMilliseconds(300.0).Ticks)
			{
				return;
			}
			configHandledAtTicks = num;
			int textureSize = Settings.TextureSize;
			try
			{
				loadingConfigFile = true;
				((BaseUnityPlugin)this).Config.Reload();
				loadingConfigFile = false;
				ReloadSettings(textureSizeSetting.Value != textureSize);
				((BaseUnityPlugin)this).Logger.LogInfo((object)"Moon Phases config reloaded.");
			}
			catch (Exception ex)
			{
				loadingConfigFile = false;
				Interlocked.Exchange(ref configChangedAtTicks, DateTime.UtcNow.Ticks);
				((BaseUnityPlugin)this).Logger.LogWarning((object)("Could not reload config file; retrying: " + ex.Message));
			}
		}

		private void BindConfig()
		{
			//IL_00af: Unknown result type (might be due to invalid IL or missing references)
			//IL_00be: Expected O, but got Unknown
			//IL_00b9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c3: Expected O, but got Unknown
			//IL_00f2: Unknown result type (might be due to invalid IL or missing references)
			//IL_0101: Expected O, but got Unknown
			//IL_00fc: Unknown result type (might be due to invalid IL or missing references)
			//IL_0106: Expected O, but got Unknown
			//IL_0135: Unknown result type (might be due to invalid IL or missing references)
			//IL_0144: Expected O, but got Unknown
			//IL_013f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0149: Expected O, but got Unknown
			//IL_0199: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a8: Expected O, but got Unknown
			//IL_01a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ad: Expected O, but got Unknown
			//IL_0260: Unknown result type (might be due to invalid IL or missing references)
			//IL_026f: Expected O, but got Unknown
			//IL_026a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0274: Expected O, but got Unknown
			//IL_02a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_02b2: Expected O, but got Unknown
			//IL_02ad: Unknown result type (might be due to invalid IL or missing references)
			//IL_02b7: Expected O, but got Unknown
			//IL_02e6: Unknown result type (might be due to invalid IL or missing references)
			//IL_02f5: Expected O, but got Unknown
			//IL_02f0: Unknown result type (might be due to invalid IL or missing references)
			//IL_02fa: Expected O, but got Unknown
			//IL_0329: Unknown result type (might be due to invalid IL or missing references)
			//IL_0338: Expected O, but got Unknown
			//IL_0333: Unknown result type (might be due to invalid IL or missing references)
			//IL_033d: Expected O, but got Unknown
			//IL_0395: Unknown result type (might be due to invalid IL or missing references)
			//IL_03a4: Expected O, but got Unknown
			//IL_039f: Unknown result type (might be due to invalid IL or missing references)
			//IL_03a9: Expected O, but got Unknown
			//IL_049e: Unknown result type (might be due to invalid IL or missing references)
			//IL_04ad: Expected O, but got Unknown
			//IL_04a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_04b2: Expected O, but got Unknown
			//IL_04e1: Unknown result type (might be due to invalid IL or missing references)
			//IL_04f0: Expected O, but got Unknown
			//IL_04eb: Unknown result type (might be due to invalid IL or missing references)
			//IL_04f5: Expected O, but got Unknown
			//IL_0524: Unknown result type (might be due to invalid IL or missing references)
			//IL_0533: Expected O, but got Unknown
			//IL_052e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0538: Expected O, but got Unknown
			//IL_0567: Unknown result type (might be due to invalid IL or missing references)
			//IL_0576: Expected O, but got Unknown
			//IL_0571: Unknown result type (might be due to invalid IL or missing references)
			//IL_057b: Expected O, but got Unknown
			//IL_05aa: Unknown result type (might be due to invalid IL or missing references)
			//IL_05b9: Expected O, but got Unknown
			//IL_05b4: Unknown result type (might be due to invalid IL or missing references)
			//IL_05be: Expected O, but got Unknown
			//IL_05ed: Unknown result type (might be due to invalid IL or missing references)
			//IL_05fc: Expected O, but got Unknown
			//IL_05f7: Unknown result type (might be due to invalid IL or missing references)
			//IL_0601: Expected O, but got Unknown
			//IL_0630: Unknown result type (might be due to invalid IL or missing references)
			//IL_063f: Expected O, but got Unknown
			//IL_063a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0644: Expected O, but got Unknown
			//IL_0673: Unknown result type (might be due to invalid IL or missing references)
			//IL_0682: Expected O, but got Unknown
			//IL_067d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0687: Expected O, but got Unknown
			//IL_06bd: Unknown result type (might be due to invalid IL or missing references)
			//IL_06cc: Expected O, but got Unknown
			//IL_06c7: Unknown result type (might be due to invalid IL or missing references)
			//IL_06d1: Expected O, but got Unknown
			enabledSetting = ((BaseUnityPlugin)this).Config.Bind<bool>("1 - General", "Enabled", true, "Turns the whole moon system on or off. Everything this mod does is local to your client.");
			toggleKeySetting = ((BaseUnityPlugin)this).Config.Bind<KeyCode>("1 - General", "ToggleKey", (KeyCode)127, "Key that turns the mod off and on while playing, to compare with the vanilla sky. Only lasts for the session.");
			moonPathSetting = ((BaseUnityPlugin)this).Config.Bind<MoonPathMode>("2 - Moon", "MoonPath", MoonPathMode.Astronomical, "Astronomical: the Moon is placed by the orbital model, so it rises and sets at the hours its phase implies, shows up in daylight near the quarters and is missing from part of some nights. It is a model, not an ephemeris: one observer for the whole world and no seasons. Vanilla: it stays opposite the Sun, rising at sunset every night as in the base game, with only the phase and eclipses changing.");
			moonSurfaceSetting = ((BaseUnityPlugin)this).Config.Bind<MoonSurfaceMode>("2 - Moon", "MoonSurface", MoonSurfaceMode.Realistic, "Realistic: the lunar maps shipped with the mod, baked from real colour and elevation surveys of the Moon, so the seas and craters are where they belong. Procedural: a surface the mod draws itself. Falls back to procedural when the map files are missing.");
			moonSurfaceReliefSetting = ((BaseUnityPlugin)this).Config.Bind<float>("2 - Moon", "MoonSurfaceRelief", 0.5f, new ConfigDescription("Strength of the relief on the realistic Moon surface. It only shows near the terminator, where the Sun grazes the craters. 0 turns it off; above 1 it looks noisy.", (AcceptableValueBase)new AcceptableValueRange<float>(0f, 4f), Array.Empty<object>()));
			moonSizeSetting = ((BaseUnityPlugin)this).Config.Bind<float>("2 - Moon", "SizeScale", 1f, new ConfigDescription("Size of the Moon's disc relative to the vanilla one. Eclipse geometry scales with it.", (AcceptableValueBase)new AcceptableValueRange<float>(0.25f, 2f), Array.Empty<object>()));
			brightnessSetting = ((BaseUnityPlugin)this).Config.Bind<float>("2 - Moon", "Brightness", 1f, new ConfigDescription("Brightness of the Moon. At 1 a full moon at mean distance is as bright as the vanilla moon.", (AcceptableValueBase)new AcceptableValueRange<float>(0.1f, 2f), Array.Empty<object>()));
			eclipsesSetting = ((BaseUnityPlugin)this).Config.Bind<bool>("3 - Eclipses", "Enabled", true, "Solar and lunar eclipses, decided by geometry alone: new or full moon, near a node, with the apparent sizes and the Moon's distance saying whether an eclipse is partial, total or annular. Nothing is random.");
			solarTotalitySetting = ((BaseUnityPlugin)this).Config.Bind<float>("3 - Eclipses", "SolarTotalityDuration", 15f, new ConfigDescription("Seconds of near-maximum effect in a solar eclipse. Valheim's accelerated day makes raw totality last only a few seconds. The default keeps the rendered Moon, corona and landscape dimming together for about 15 seconds, without changing the world clock or the eclipse calendar. 0 keeps the raw timing.", (AcceptableValueBase)new AcceptableValueRange<float>(0f, 60f), Array.Empty<object>()));
			eclipseLightingSetting = ((BaseUnityPlugin)this).Config.Bind<bool>("3 - Eclipses", "SolarEclipseLighting", true, "Dims light, sky and fog during a solar eclipse, in proportion to how much of the Sun is covered.");
			coronaSetting = ((BaseUnityPlugin)this).Config.Bind<bool>("3 - Eclipses", "SolarCorona", true, "Shows the solar corona around the Moon during totality.");
			moonlightSetting = ((BaseUnityPlugin)this).Config.Bind<bool>("4 - Moonlight", "Enabled", true, "Makes the night light, the glint on the water and the night fog follow the Moon's phase, height and eclipses. Vanilla has no moonlight of its own: it flips the Sun's light at night and keeps it equally bright every night. Stealth still reads the vanilla values, so this stays purely visual.");
			moonlightFollowsMoonSetting = ((BaseUnityPlugin)this).Config.Bind<bool>("4 - Moonlight", "ShadowsFollowTheMoon", true, "Night shadows and the glint on the water come from where the Moon is. With no Moon up, the light comes from overhead, like skyglow, and leaves no glint.");
			nightLightSetting = ((BaseUnityPlugin)this).Config.Bind<float>("4 - Moonlight", "NightBrightnessWithoutMoon", 0.55f, new ConfigDescription("How bright a moonless night is, as a fraction of a vanilla night (which is as bright as a full moon). Lower means darker new-moon nights.", (AcceptableValueBase)new AcceptableValueRange<float>(0f, 1f), Array.Empty<object>()));
			nightAmbientSetting = ((BaseUnityPlugin)this).Config.Bind<float>("4 - Moonlight", "NightAmbientWithoutMoon", 0.8f, new ConfigDescription("Ambient light on a moonless night, as a fraction of the vanilla one.", (AcceptableValueBase)new AcceptableValueRange<float>(0f, 1f), Array.Empty<object>()));
			nightFogSetting = ((BaseUnityPlugin)this).Config.Bind<float>("4 - Moonlight", "NightFogWithoutMoon", 0.85f, new ConfigDescription("Glow of the night fog with no Moon, as a fraction of the vanilla one.", (AcceptableValueBase)new AcceptableValueRange<float>(0f, 1f), Array.Empty<object>()));
			cycleLengthSetting = ((BaseUnityPlugin)this).Config.Bind<float>("5 - Advanced", "CycleLengthDays", 29.53059f, new ConfigDescription("Length of a synodic month in world days. The sidereal, draconic and anomalistic months scale with it, so the real ratios between them survive and eclipse seasons keep working. A shorter month makes everything, eclipses included, come round faster.", (AcceptableValueBase)new AcceptableValueRange<float>(8f, 120f), Array.Empty<object>()));
			epochOffsetSetting = ((BaseUnityPlugin)this).Config.Bind<double>("5 - Advanced", "EpochOffsetDays", 5829.9055, "Where world day 0 sits on the real lunar calendar, counted in days from the mean new moon of 6 January 2000. The default makes the first night of day 1 almost exactly full Moon and puts the first visible total solar eclipse near noon on day 76. Only the starting date changes; periods and eclipse geometry stay the same.");
			inclinationSetting = ((BaseUnityPlugin)this).Config.Bind<float>("5 - Advanced", "OrbitalInclinationDeg", 5.145f, new ConfigDescription("Tilt of the Moon's orbit. 5.145 is the real value. Lower values make eclipses more frequent, which is a gameplay choice rather than an astronomical one.", (AcceptableValueBase)new AcceptableValueRange<float>(0.5f, 10f), Array.Empty<object>()));
			ellipticalOrbitSetting = ((BaseUnityPlugin)this).Config.Bind<bool>("5 - Advanced", "EllipticalOrbit", true, "Kepler's orbit: the Moon runs faster near perigee, which shifts the phases slightly.");
			distanceVariationSetting = ((BaseUnityPlugin)this).Config.Bind<bool>("5 - Advanced", "DistanceVariation", true, "Apparent size changes with distance: bigger at perigee, smaller at apogee, which is what decides between a total and an annular eclipse.");
			orbitalInclinationSetting = ((BaseUnityPlugin)this).Config.Bind<bool>("5 - Advanced", "OrbitalInclination", true, "Lunar latitude from the orbital tilt and the draconic month. This is what creates eclipse seasons; without it eclipses would happen every month.");
			librationSetting = ((BaseUnityPlugin)this).Config.Bind<bool>("5 - Advanced", "Libration", true, "The Moon's wobble: over a month it shows up to about 7 degrees past its mean edge, and the maria drift towards and away from the limb.");
			earthshineSetting = ((BaseUnityPlugin)this).Config.Bind<bool>("5 - Advanced", "EarthshineVariation", true, "Earthshine, strong on a thin crescent and nearly gone near full moon.");
			atmosphericTintSetting = ((BaseUnityPlugin)this).Config.Bind<bool>("5 - Advanced", "AtmosphericTint", true, "Makes the Moon dimmer and more orange near the horizon, from atmospheric extinction. This is not an eclipse.");
			moonlightGammaSetting = ((BaseUnityPlugin)this).Config.Bind<float>("5 - Advanced", "MoonlightGamma", 1f, new ConfigDescription("Perceptual compression of the moonlight. 1 is photometric, where a quarter moon gives about 9% of a full moon; 0.5 gives about 30%.", (AcceptableValueBase)new AcceptableValueRange<float>(0.2f, 1f), Array.Empty<object>()));
			solarDiscScaleSetting = ((BaseUnityPlugin)this).Config.Bind<float>("5 - Advanced", "SolarDiscScale", 1f, new ConfigDescription("Radius of the Sun's disc used for eclipses, relative to the size that matches the game's Moon. The vanilla Sun is a glow without a defined edge, so this may need a nudge.", (AcceptableValueBase)new AcceptableValueRange<float>(0.5f, 2f), Array.Empty<object>()));
			moonSurfaceLongitudeSetting = ((BaseUnityPlugin)this).Config.Bind<float>("5 - Advanced", "MoonSurfaceLongitudeOffset", 0f, new ConfigDescription("Rotates the Moon surface map in longitude, in case a replacement map is not centred on the near side.", (AcceptableValueBase)new AcceptableValueRange<float>(-180f, 180f), Array.Empty<object>()));
			terminatorSoftnessSetting = ((BaseUnityPlugin)this).Config.Bind<float>("5 - Advanced", "TerminatorSoftness", 0.06f, new ConfigDescription("Width of the line between the lit and dark sides.", (AcceptableValueBase)new AcceptableValueRange<float>(0.001f, 0.25f), Array.Empty<object>()));
			earthshineBrightnessSetting = ((BaseUnityPlugin)this).Config.Bind<float>("5 - Advanced", "EarthshineBrightness", 0.03f, new ConfigDescription("Brightness of the earthshine on the dark side.", (AcceptableValueBase)new AcceptableValueRange<float>(0f, 0.2f), Array.Empty<object>()));
			bloodMoonBrightnessSetting = ((BaseUnityPlugin)this).Config.Bind<float>("5 - Advanced", "BloodMoonBrightness", 1f, new ConfigDescription("Brightness of the Moon inside the umbra during a total lunar eclipse. Around 1 matches a typical Danjon 2 to 3 eclipse.", (AcceptableValueBase)new AcceptableValueRange<float>(0.2f, 3f), Array.Empty<object>()));
			daytimeOpacitySetting = ((BaseUnityPlugin)this).Config.Bind<float>("5 - Advanced", "DaytimeOpacity", 0.8f, new ConfigDescription("How solid the Moon looks in a bright sky, where the blue of the day sits in front of it.", (AcceptableValueBase)new AcceptableValueRange<float>(0.2f, 1f), Array.Empty<object>()));
			blueTintSetting = ((BaseUnityPlugin)this).Config.Bind<float>("5 - Advanced", "BlueTint", 0f, new ConfigDescription("How much of the vanilla moon's blue to keep. 0 is the neutral, slightly warm grey of the real Moon.", (AcceptableValueBase)new AcceptableValueRange<float>(0f, 1f), Array.Empty<object>()));
			textureSizeSetting = ((BaseUnityPlugin)this).Config.Bind<int>("5 - Advanced", "TextureSize", 256, new ConfigDescription("Resolution of the Moon's generated textures.", (AcceptableValueBase)new AcceptableValueList<int>(new int[4] { 128, 192, 256, 512 }), Array.Empty<object>()));
		}

		private void ReloadSettings(bool recreateTextures)
		{
			PluginSettings settings = Settings;
			settings.Enabled = enabledSetting.Value;
			settings.AstronomicalPosition = moonPathSetting.Value == MoonPathMode.Astronomical;
			settings.MoonSurfaceMode = moonSurfaceSetting.Value;
			settings.MoonSurfaceRelief = moonSurfaceReliefSetting.Value;
			settings.MoonSurfaceLongitudeOffset = moonSurfaceLongitudeSetting.Value;
			settings.MoonSizeScale = moonSizeSetting.Value;
			settings.Brightness = brightnessSetting.Value;
			settings.Eclipses = eclipsesSetting.Value;
			settings.SolarTotalityVisualSeconds = solarTotalitySetting.Value;
			settings.SolarEclipseLighting = eclipseLightingSetting.Value;
			settings.SolarCorona = coronaSetting.Value;
			settings.SolarDiscScale = solarDiscScaleSetting.Value;
			settings.Moonlight = moonlightSetting.Value;
			settings.MoonlightFollowsMoon = moonlightFollowsMoonSetting.Value;
			settings.NightLightWithoutMoon = nightLightSetting.Value;
			settings.NightAmbientWithoutMoon = nightAmbientSetting.Value;
			settings.NightFogWithoutMoon = nightFogSetting.Value;
			settings.MoonlightGamma = moonlightGammaSetting.Value;
			settings.Libration = librationSetting.Value;
			settings.EarthshineVariation = earthshineSetting.Value;
			settings.AtmosphericTint = (atmosphericTintSetting.Value ? 0.35f : 0f);
			settings.ShadowSoftness = terminatorSoftnessSetting.Value;
			settings.DarkSideBrightness = earthshineBrightnessSetting.Value;
			settings.TotalityBrightness = bloodMoonBrightnessSetting.Value;
			settings.DaytimeOpacity = daytimeOpacitySetting.Value;
			settings.VanillaTintAmount = blueTintSetting.Value;
			settings.WaxingOnRight = true;
			settings.TextureSize = textureSizeSetting.Value;
			lunarSettings = new LunarSettings
			{
				SynodicPeriodDays = Math.Max(1.0, cycleLengthSetting.Value),
				InclinationDeg = inclinationSetting.Value,
				EllipticalOrbit = ellipticalOrbitSetting.Value,
				DistanceVariation = distanceVariationSetting.Value,
				OrbitalInclination = orbitalInclinationSetting.Value
			};
			snapshotFrame = -1;
			if (recreateTextures && skyRenderer != null)
			{
				skyRenderer.Dispose();
				skyRenderer = null;
				rendererFailed = false;
			}
			skyRenderer?.Invalidate();
			if (!settings.Enabled)
			{
				RestoreVisuals();
			}
		}

		private static bool TryGetWorldTimeDays(out double days)
		{
			days = 0.0;
			if ((Object)(object)ZNet.instance == (Object)null || (Object)(object)EnvMan.instance == (Object)null || EnvMan.instance.m_dayLengthSec <= 0)
			{
				return false;
			}
			days = ZNet.instance.GetTimeSeconds() / (double)EnvMan.instance.m_dayLengthSec;
			return true;
		}

		private double ToAstro(double worldDays)
		{
			return worldDays + epochOffsetSetting.Value;
		}

		private double ToWorld(double astroDays)
		{
			return astroDays - epochOffsetSetting.Value;
		}

		internal MoonSnapshot GetSnapshot(bool refresh)
		{
			EnvMan instance = EnvMan.instance;
			if ((Object)(object)instance == (Object)null || !TryGetWorldTimeDays(out var days))
			{
				return default(MoonSnapshot);
			}
			float dayFraction = instance.GetDayFraction();
			if (!refresh && snapshotFrame == Time.frameCount && Mathf.Approximately(dayFraction, snapshotDayFraction))
			{
				return snapshot;
			}
			double num = ToAstro(days);
			LunarState state = LunarModel.Calculate(num, lunarSettings);
			float sunAngle = instance.GetCurrentEnvironment()?.m_sunAngle ?? 60f;
			double num2 = state.SolarSeparationDeg;
			if (Settings.SolarTotalityVisualSeconds > 0f && state.SolarObscuration01 > 0.0)
			{
				double num3 = 1.0 / Math.Max(1.0, instance.m_dayLengthSec);
				LunarState lunarState = LunarModel.Calculate(num - num3 * 0.5, lunarSettings);
				double magnitudePerSecond = Math.Abs(LunarModel.Calculate(num + num3 * 0.5, lunarSettings).ObserverOffsetE - lunarState.ObserverOffsetE) / (2.0 * state.SunAngularRadiusDeg);
				num2 = EclipseVisuals.VisualSeparation(state, magnitudePerSecond, Settings.SolarTotalityVisualSeconds);
			}
			snapshot = SkyGeometry.Build(state, sunAngle, dayFraction, vanillaSky.VanillaMoonRadiusDeg, vanillaSky.FogHeightMin, vanillaSky.FogHeightMax, Settings, num2);
			snapshot.VisualSolarObscuration01 = EclipseVisuals.ObscurationAtSeparation(state, num2);
			snapshotFrame = Time.frameCount;
			snapshotDayFraction = dayFraction;
			return snapshot;
		}

		private void LateUpdate()
		{
			//IL_0231: Unknown result type (might be due to invalid IL or missing references)
			if (!Active || (Object)(object)EnvMan.instance == (Object)null || (Object)(object)ZNet.instance == (Object)null)
			{
				if (visualsApplied)
				{
					RestoreVisuals();
				}
				if ((Object)(object)EnvMan.instance == (Object)null)
				{
					suspended = false;
				}
				return;
			}
			Material skybox = RenderSettings.skybox;
			int num = (((Object)(object)skybox != (Object)null) ? ((Object)skybox).GetInstanceID() : 0);
			if (num != lastSkyId)
			{
				vanillaSky.RestoreAll();
				lastSkyId = num;
			}
			bool flag = vanillaSky.Observe(skybox);
			MoonSnapshot snap = GetSnapshot(refresh: false);
			if (!snap.Valid)
			{
				return;
			}
			Camera val = MainCamera();
			if (skyRenderer == null && !rendererFailed && (Object)(object)val != (Object)null)
			{
				if (!surfaceLoaded)
				{
					surfaceLoaded = true;
					lunarSurface = LunarSurface.Load(Path.GetDirectoryName(((BaseUnityPlugin)this).Info.Location), 2048);
					if (lunarSurface != null)
					{
						((BaseUnityPlugin)this).Logger.LogInfo((object)("Lunar maps loaded: " + lunarSurface.Description));
					}
				}
				if (SkyMoonRenderer.TryCreate(Settings.TextureSize, out skyRenderer, out rendererError))
				{
					skyRenderer.SetSurfaceMaps(lunarSurface);
					((BaseUnityPlugin)this).Logger.LogInfo((object)$"Positional moon active ({Settings.TextureSize}px); sky: {vanillaSky.Description}.");
				}
				else
				{
					rendererFailed = true;
					((BaseUnityPlugin)this).Logger.LogWarning((object)("Positional moon unavailable (" + rendererError + "); falling back to the phase on the vanilla moon."));
				}
			}
			visualsApplied = true;
			if (skyRenderer != null && flag)
			{
				vanillaSky.RestoreTexture();
				if (Settings.AstronomicalPosition)
				{
					vanillaSky.HideMoon(skybox, hide: true);
				}
				else
				{
					vanillaSky.SetDarkDisc(skybox, snap.MoonRadiusDisplayDeg * ((float)Math.PI / 180f) * 0.985f);
				}
				int cloudLayer = (((Object)(object)EnvMan.instance.m_clouds != (Object)null) ? ((Component)EnvMan.instance.m_clouds).gameObject.layer : 0);
				skyRenderer.Render(snap, val, MoonTint(), Settings, cloudLayer);
				float factor = 1f;
				if (Settings.Eclipses && Settings.SolarEclipseLighting && snap.VisualSolarObscuration01 > 0.0)
				{
					factor = Mathf.Max(0.12f, Mathf.Pow(1f - (float)snap.VisualSolarObscuration01, 0.5f));
				}
				vanillaSky.SetExposureFactor(skybox, factor);
			}
			else
			{
				skyRenderer?.SetVisible(visible: false);
				if (flag)
				{
					vanillaSky.HideMoon(skybox, hide: false);
					vanillaSky.ApplyFallbackPhase(skybox, snap.State, Settings);
				}
			}
		}

		private void Update()
		{
			//IL_004d: Unknown result type (might be due to invalid IL or missing references)
			ReloadWatchedConfig();
			if (!((Object)(object)EnvMan.instance == (Object)null) && Settings.Enabled && !Console.IsVisible() && (!((Object)(object)Chat.instance != (Object)null) || !Chat.instance.HasFocus()) && !TextInput.IsVisible() && ZInput.GetKeyDown(toggleKeySetting.Value, false))
			{
				ToggleSuspended(null);
			}
		}

		private void ToggleSuspended(Terminal context)
		{
			suspended = !suspended;
			snapshotFrame = -1;
			if (suspended)
			{
				RestoreVisuals();
			}
			string text = (suspended ? "Moon Phases: OFF (vanilla sky)" : "Moon Phases: ON");
			MessageHud instance = MessageHud.instance;
			if (instance != null)
			{
				instance.ShowMessage((MessageType)2, text, 0, (Sprite)null, false, true);
			}
			if (context != null)
			{
				context.AddString(text);
			}
		}

		internal static Camera MainCamera()
		{
			Camera val = Camera.main;
			if ((Object)(object)val == (Object)null && (Object)(object)GameCamera.instance != (Object)null)
			{
				val = ((Component)GameCamera.instance).GetComponent<Camera>();
			}
			return val;
		}

		private Color MoonTint()
		{
			//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)
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_005c: 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_0071: 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_0088: 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_00a3: 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_00b9: Unknown result type (might be due to invalid IL or missing references)
			Color vanillaMoonColor = vanillaSky.VanillaMoonColor;
			Color linear = ((Color)(ref vanillaMoonColor)).linear;
			float num = Mathf.Max(0.0001f, 0.2126f * linear.r + 0.7152f * linear.g + 0.0722f * linear.b);
			Color val = Color.Lerp(new Color(1f, 0.975f, 0.93f), linear / num, Settings.VanillaTintAmount);
			float num2 = Mathf.Max(0.0001f, 0.2126f * val.r + 0.7152f * val.g + 0.0722f * val.b);
			val *= num / num2;
			val.a = 1f;
			return val;
		}

		private void RestoreVisuals()
		{
			vanillaSky.RestoreAll();
			skyRenderer?.SetVisible(visible: false);
			visualsApplied = false;
		}

		private void OnDestroy()
		{
			//IL_006d: 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_007d: Expected O, but got Unknown
			//IL_007d: Expected O, but got Unknown
			configWatcher?.Dispose();
			configWatcher = null;
			((BaseUnityPlugin)this).Config.SettingChanged -= OnConfigSettingChanged;
			Harmony val = harmony;
			if (val != null)
			{
				val.UnpatchSelf();
			}
			RestoreVisuals();
			skyRenderer?.Dispose();
			skyRenderer = null;
			vanillaSky.Dispose();
			if ((Object)Instance == (Object)this)
			{
				Instance = null;
			}
		}

		private void RegisterCommands()
		{
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: Expected O, but got Unknown
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			//IL_0075: Expected O, but got Unknown
			//IL_0070: Unknown result type (might be due to invalid IL or missing references)
			//IL_0062: Unknown result type (might be due to invalid IL or missing references)
			//IL_0067: Unknown result type (might be due to invalid IL or missing references)
			//IL_006d: Expected O, but got Unknown
			//IL_00a5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d7: Expected O, but got Unknown
			//IL_00d2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cf: Expected O, but got Unknown
			//IL_0118: Unknown result type (might be due to invalid IL or missing references)
			//IL_014a: Expected O, but got Unknown
			//IL_0145: 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_013c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0142: Expected O, but got Unknown
			new ConsoleCommand("moonphase", "shows tonight's moon: phase, height, distance and the next eclipse", new ConsoleEvent(HandleMoonPhase), false, false, false, false, true, false, (ConsoleOptionsFetcher)null, false, false, false);
			if (!CommandTaken("moonpath"))
			{
				ConsoleEvent val = HandleMoonPath;
				object obj = <>c.<>9__90_0;
				if (obj == null)
				{
					ConsoleOptionsFetcher val2 = () => new List<string> { "astronomical", "vanilla" };
					<>c.<>9__90_0 = val2;
					obj = (object)val2;
				}
				new ConsoleCommand("moonpath", "moonpath [astronomical|vanilla] - show or change the Moon's path", val, false, false, false, false, true, false, (ConsoleOptionsFetcher)obj, false, false, false);
			}
			else
			{
				((BaseUnityPlugin)this).Logger.LogWarning((object)"Another mod already provides 'moonpath'; not replacing it.");
			}
			if (!CommandTaken("moonsurface"))
			{
				ConsoleEvent val3 = HandleMoonSurface;
				object obj2 = <>c.<>9__90_1;
				if (obj2 == null)
				{
					ConsoleOptionsFetcher val4 = () => new List<string> { "realistic", "procedural" };
					<>c.<>9__90_1 = val4;
					obj2 = (object)val4;
				}
				new ConsoleCommand("moonsurface", "moonsurface [realistic|procedural] - show or change the Moon's surface", val3, false, false, false, false, true, false, (ConsoleOptionsFetcher)obj2, false, false, false);
			}
			else
			{
				((BaseUnityPlugin)this).Logger.LogWarning((object)"Another mod already provides 'moonsurface'; not replacing it.");
			}
			if (CommandTaken("setday"))
			{
				((BaseUnityPlugin)this).Logger.LogWarning((object)"Another mod already provides 'setday'; not replacing it.");
				return;
			}
			ConsoleEvent val5 = delegate(ConsoleEventArgs args)
			{
				SetWorldDay(args.Context, (args.Length >= 2) ? args[1].Trim() : string.Empty, (args.Length >= 3) ? args[2].Trim().ToLowerInvariant() : "dawn");
			};
			object obj3 = <>c.<>9__90_3;
			if (obj3 == null)
			{
				ConsoleOptionsFetcher val6 = () => new List<string> { "dawn", "noon", "dusk", "midnight" };
				<>c.<>9__90_3 = val6;
				obj3 = (object)val6;
			}
			new ConsoleCommand("setday", "setday <day> [dawn|noon|dusk|midnight|HH:MM] - moves the world clock (singleplayer or host only)", val5, false, false, false, false, true, false, (ConsoleOptionsFetcher)obj3, false, false, false);
		}

		private static bool CommandTaken(string name)
		{
			try
			{
				return AccessTools.Field(typeof(Terminal), "commands")?.GetValue(null) is IDictionary dictionary && dictionary.Contains(name);
			}
			catch (Exception)
			{
				return false;
			}
		}

		private void HandleMoonPhase(ConsoleEventArgs args)
		{
			Terminal context = args.Context;
			if (!TryGetWorldTimeDays(out var days))
			{
				if (context != null)
				{
					context.AddString("Moon Phases: join a world first.");
				}
			}
			else
			{
				WriteStatus(context, days);
			}
		}

		private void HandleMoonPath(ConsoleEventArgs args)
		{
			Terminal context = args.Context;
			if (args.Length == 1)
			{
				if (context != null)
				{
					context.AddString($"Moon path: {moonPathSetting.Value}. Usage: moonpath <astronomical|vanilla>");
				}
				return;
			}
			if (args.Length != 2 || !Enum.TryParse<MoonPathMode>(args[1], ignoreCase: true, out var result) || (result != MoonPathMode.Astronomical && result != MoonPathMode.Vanilla))
			{
				if (context != null)
				{
					context.AddString("Usage: moonpath <astronomical|vanilla>");
				}
				return;
			}
			moonPathSetting.Value = result;
			((BaseUnityPlugin)this).Config.Save();
			if (context != null)
			{
				context.AddString($"Moon path: {result} (saved to config).");
			}
		}

		private void HandleMoonSurface(ConsoleEventArgs args)
		{
			Terminal context = args.Context;
			if (args.Length == 1)
			{
				if (context != null)
				{
					context.AddString($"Moon surface: {moonSurfaceSetting.Value}. Usage: moonsurface <realistic|procedural>");
				}
				return;
			}
			if (args.Length != 2 || !Enum.TryParse<MoonSurfaceMode>(args[1], ignoreCase: true, out var result) || (result != MoonSurfaceMode.Realistic && result != MoonSurfaceMode.Procedural))
			{
				if (context != null)
				{
					context.AddString("Usage: moonsurface <realistic|procedural>");
				}
				return;
			}
			moonSurfaceSetting.Value = result;
			((BaseUnityPlugin)this).Config.Save();
			if (context != null)
			{
				context.AddString($"Moon surface: {result} (saved to config).");
			}
		}

		private void SetWorldDay(Terminal context, string dayText, string moment)
		{
			if ((Object)(object)EnvMan.instance == (Object)null)
			{
				if (context != null)
				{
					context.AddString("Moon Phases: join a world first.");
				}
				return;
			}
			if (!int.TryParse(dayText, out var result) || result < 0)
			{
				if (context != null)
				{
					context.AddString("Usage: setday <day> [dawn|noon|dusk|midnight|HH:MM]   e.g. setday 70 11:55");
				}
				return;
			}
			double num = EnvMan.instance.m_dayLengthSec;
			double num2 = 10.0 / num;
			double num3;
			string text;
			switch (moment)
			{
			case "dawn":
			case "morning":
			case "day":
				num3 = 0.15 - num2;
				text = "10 s before sunrise";
				break;
			case "noon":
			case "midday":
				num3 = 0.5 - num2;
				text = "10 s before noon";
				break;
			case "dusk":
			case "sunset":
			case "night":
				num3 = 0.85 - num2;
				text = "10 s before sunset";
				break;
			case "midnight":
				num3 = 1.0 - num2;
				text = "10 s before midnight";
				break;
			default:
			{
				if (!TryParseHour(moment, out var hour))
				{
					if (context != null)
					{
						context.AddString("Unknown moment. Use dawn, noon, dusk, midnight or HH:MM.");
					}
					return;
				}
				num3 = RawFromClock(hour / 24f);
				text = $"at {hour:00.##}h";
				break;
			}
			}
			if (JumpWorldTo(context, (double)result + num3) && context != null)
			{
				context.AddString($"World at day {result}, {text} (clock {ClockText((double)result + num3)}). {DescribePhase(LunarModel.Calculate(ToAstro((double)result + num3), lunarSettings))}.");
			}
		}

		private bool JumpWorldTo(Terminal context, double targetWorldDays)
		{
			ZNet instance = ZNet.instance;
			EnvMan instance2 = EnvMan.instance;
			if ((Object)(object)instance == (Object)null || (Object)(object)instance2 == (Object)null)
			{
				if (context != null)
				{
					context.AddString("Moon Phases: join a world first.");
				}
				return false;
			}
			if (!instance.IsServer())
			{
				if (context != null)
				{
					context.AddString("Moon Phases: the world clock belongs to the server, so this only works in singleplayer or as the host.");
				}
				return false;
			}
			double timeSeconds = instance.GetTimeSeconds();
			double num = Math.Max(0.0, targetWorldDays) * (double)instance2.m_dayLengthSec;
			instance.SetNetTime(num);
			SceneLighting.SetSmoothDayFraction(instance2, GameDayFraction(Math.Max(0.0, targetWorldDays)));
			snapshotFrame = -1;
			if (num < timeSeconds - 1.0 && context != null)
			{
				context.AddString("Careful: time went backwards. Fermenters, kilns and crops count on the world clock and may take longer.");
			}
			return true;
		}

		private void WriteStatus(Terminal context, double world)
		{
			MoonSnapshot moonSnapshot = GetSnapshot(refresh: true);
			if (!moonSnapshot.Valid)
			{
				if (context != null)
				{
					context.AddString("Moon Phases: no state yet.");
				}
				return;
			}
			LunarState state = moonSnapshot.State;
			if (context != null)
			{
				context.AddString($"{DescribePhase(state)} - day {Math.Floor(world)}.");
			}
			if (context != null)
			{
				context.AddString($"Moon {moonSnapshot.MoonAltitudeDeg:0}° above the horizon, {state.MoonDistanceKm:0} km away, disc {state.MoonAngularRadiusDeg / LunarModel.MeanMoonAngularRadiusDeg * 100.0 - 100.0:+0.0;-0.0}% of mean, moonlight {moonSnapshot.Moonlight01 * 100f:0}%.");
			}
			if (state.SolarEclipse != EclipseKind.None && context != null)
			{
				context.AddString($"Solar eclipse, {LunarModel.KindName(state.SolarEclipse)}: {moonSnapshot.VisualSolarObscuration01 * 100.0:0.0}% of the Sun covered.");
			}
			if (state.LunarEclipse != EclipseKind.None && context != null)
			{
				context.AddString($"Lunar eclipse, {LunarModel.KindName(state.LunarEclipse)}: umbra over {state.UmbralCoverage01 * 100.0:0}% of the disc.");
			}
			if (!Settings.Eclipses)
			{
				return;
			}
			foreach (EclipseEvent item in LunarModel.FindEclipses(ToAstro(world), 200, lunarSettings))
			{
				double num = ToWorld(item.MaximumDays);
				if (IsNightAt(num) != item.IsSolar)
				{
					if (context != null)
					{
						context.AddString(string.Format("Next eclipse: {0}, {1}, on day {2} around {3}.", item.IsSolar ? "solar" : "lunar", LunarModel.KindName(item.Kind), Math.Floor(num), ClockText(num)));
					}
					break;
				}
			}
		}

		private static bool TryParseHour(string text, out float hour)
		{
			hour = 0f;
			string[] array = text.Split(new char[1] { ':' });
			if (!float.TryParse(array[0].Replace(',', '.'), NumberStyles.Float, CultureInfo.InvariantCulture, out var result))
			{
				return false;
			}
			float result2 = 0f;
			if (array.Length > 1 && !float.TryParse(array[1], NumberStyles.Float, CultureInfo.InvariantCulture, out result2))
			{
				return false;
			}
			hour = result + result2 / 60f;
			if (hour >= 0f)
			{
				return hour <= 24f;
			}
			return false;
		}

		private static double RawFromClock(float clock)
		{
			if (clock >= 0.25f && clock <= 0.75f)
			{
				return 0.15 + ((double)clock - 0.25) / 0.5 * 0.7;
			}
			if (!(clock < 0.25f))
			{
				return 0.85 + ((double)clock - 0.75) / 0.25 * 0.15;
			}
			return (double)clock / 0.25 * 0.15;
		}

		private static float GameDayFraction(double world)
		{
			float num = (float)(world - Math.Floor(world));
			if (num >= 0.15f && num <= 0.85f)
			{
				return 0.25f + (num - 0.15f) / 0.7f * 0.5f;
			}
			if (!(num < 0.5f))
			{
				return 0.75f + (num - 0.85f) / 0.15f * 0.25f;
			}
			return num / 0.15f * 0.25f;
		}

		private static bool IsNightAt(double world)
		{
			float num = GameDayFraction(world);
			if (!(num < 0.25f))
			{
				return num > 0.75f;
			}
			return true;
		}

		private static string ClockText(double world)
		{
			float num = GameDayFraction(world) * 24f;
			int num2 = Mathf.FloorToInt(num);
			int num3 = Mathf.FloorToInt((num - (float)num2) * 60f);
			return $"{num2:00}:{num3:00}";
		}

		private static string DescribePhase(LunarState state)
		{
			int num = (int)Math.Round(state.ElongationDeg / 45.0) % 8;
			return string.Format("{0}, {1:0}% lit and {2}", PhaseNames[num], state.IlluminatedFraction * 100.0, state.IsWaxing ? "waxing" : "waning");
		}
	}
	internal sealed class PluginSettings
	{
		public bool Enabled;

		public bool AstronomicalPosition;

		public bool Eclipses;

		public bool SolarEclipseLighting;

		public bool SolarCorona;

		public bool EarthshineVariation;

		public bool Libration;

		public float AtmosphericTint;

		public bool Moonlight;

		public bool MoonlightFollowsMoon;

		public bool WaxingOnRight;

		public float ShadowSoftness;

		public float DarkSideBrightness;

		public float Brightness;

		public float MoonSizeScale;

		public float DaytimeOpacity;

		public float TotalityBrightness;

		public float VanillaTintAmount;

		public float NightLightWithoutMoon;

		public float NightAmbientWithoutMoon;

		public float NightFogWithoutMoon;

		public float MoonlightGamma;

		public float SolarDiscScale;

		public float SolarTotalityVisualSeconds;

		public MoonSurfaceMode MoonSurfaceMode;

		public float MoonSurfaceLongitudeOffset;

		public float MoonSurfaceRelief;

		public int TextureSize;
	}
	internal static class SceneLighting
	{
		private static readonly int SunDirId = Shader.PropertyToID("_SunDir");

		private static readonly int SunColorId = Shader.PropertyToID("_SunColor");

		private static readonly int AmbientColorId = Shader.PropertyToID("_AmbientColor");

		private static bool modified;

		private static Light modifiedLight;

		private static float vanillaIntensity;

		private static Color vanillaColor;

		private static Color moddedColor;

		private static Quaternion vanillaRotation;

		private static Color vanillaAmbient;

		private static float moddedIntensity;

		private static Quaternion moddedRotation;

		private static Color moddedAmbient;

		private static readonly FieldRef<EnvMan, float> SmoothDayFraction = AccessTools.FieldRefAccess<EnvMan, float>("m_smoothDayFraction");

		public static bool Installed { get; private set; }

		public static string Status { get; private set; } = "not installed";

		public static float LastSolarFactor { get; private set; } = 1f;

		public static float LastLunarFactor { get; private set; } = 1f;

		public static void Install(Harmony harmony)
		{
			//IL_0061: Unknown result type (might be due to invalid IL or missing references)
			//IL_0076: Unknown result type (might be due to invalid IL or missing references)
			//IL_0083: Expected O, but got Unknown
			//IL_0083: Expected O, but got Unknown
			//IL_0097: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a4: Expected O, but got Unknown
			try
			{
				MethodInfo methodInfo = AccessTools.Method(typeof(EnvMan), "SetEnv", (Type[])null, (Type[])null);
				MethodInfo methodInfo2 = AccessTools.Method(typeof(StealthSystem), "GetLightLevel", (Type[])null, (Type[])null);
				if (methodInfo == null || methodInfo2 == null)
				{
					Status = "EnvMan.SetEnv or StealthSystem.GetLightLevel not found";
					return;
				}
				harmony.Patch((MethodBase)methodInfo2, new HarmonyMethod(typeof(SceneLighting), "StealthPrefix", (Type[])null), new HarmonyMethod(typeof(SceneLighting), "StealthPostfix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
				harmony.Patch((MethodBase)methodInfo, (HarmonyMethod)null, new HarmonyMethod(typeof(SceneLighting), "SetEnvPostfix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
				Installed = true;
				Status = "active";
			}
			catch (Exception ex)
			{
				Installed = false;
				Status = "failed: " + ex.Message;
				Plugin.Log.LogWarning((object)("Moonlight disabled; the patch failed: " + ex));
			}
		}

		internal static void SetSmoothDayFraction(EnvMan env, float fraction)
		{
			if ((Object)(object)env != (Object)null)
			{
				SmoothDayFraction.Invoke(env) = fraction;
			}
		}

		private static void SetEnvPostfix(EnvMan __instance, EnvSetup env, float dayInt, float nightInt, float morningInt, float eveningInt)
		{
			ApplyLighting(__instance, env, dayInt, nightInt, morningInt, eveningInt);
		}

		private static void ApplyLighting(EnvMan __instance, EnvSetup env, float dayInt, float nightInt, float morningInt, float eveningInt)
		{
			//IL_003a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0045: Expected O, but got Unknown
			//IL_0094: Unknown result type (might be due to invalid IL or missing references)
			//IL_0099: 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_00a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ae: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_02e6: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ed: Unknown result type (might be due to invalid IL or missing references)
			//IL_02f2: Unknown result type (might be due to invalid IL or missing references)
			//IL_023d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0243: Unknown result type (might be due to invalid IL or missing references)
			//IL_0248: Unknown result type (might be due to invalid IL or missing references)
			//IL_024d: 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_0257: Unknown result type (might be due to invalid IL or missing references)
			//IL_026d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0278: Unknown result type (might be due to invalid IL or missing references)
			//IL_0282: Unknown result type (might be due to invalid IL or missing references)
			//IL_0287: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c1: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e3: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f4: Unknown result type (might be due to invalid IL or missing references)
			//IL_0204: Unknown result type (might be due to invalid IL or missing references)
			//IL_0209: 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_0349: Unknown result type (might be due to invalid IL or missing references)
			//IL_0350: Unknown result type (might be due to invalid IL or missing references)
			//IL_0355: Unknown result type (might be due to invalid