Decompiled source of DayNightCycle v1.0.0

BepInEx/plugins/HowToFish.DayNight/HowToFish.DayNight.dll

Decompiled 2 hours ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using FishNet;
using FishNet.Managing.Timing;
using HarmonyLib;
using HowToFish.DayNight.Patches;
using Microsoft.CodeAnalysis;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[assembly: AssemblyCompany("HowToFish.DayNight")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("HowToFish.DayNight")]
[assembly: AssemblyTitle("How to Fish - Day/Night Cycle")]
[assembly: AssemblyVersion("1.0.0.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace HowToFish.DayNight
{
	internal struct CycleState
	{
		public float Elevation;

		public float Daylight;

		public float Horizon;

		public Vector3 SunDirection;

		public static CycleState Daytime => new CycleState
		{
			Elevation = 1f,
			Daylight = 1f,
			Horizon = 0f,
			SunDirection = Vector3.up
		};
	}
	public enum DayPhase
	{
		Night,
		Dawn,
		Day,
		Dusk
	}
	public static class DayNightAPI
	{
		public static float TimeOfDay { get; internal set; } = 0.3f;

		public static DayPhase Phase { get; internal set; } = DayPhase.Day;

		public static int DayNumber { get; internal set; } = 1;

		public static float DaylightFactor { get; internal set; } = 1f;

		public static bool IsNight => Phase == DayPhase.Night;

		public static bool IsRunning { get; internal set; }

		public static bool IsNetworkSynced => DayNightDriver.Active?.DrivenByNetwork ?? false;

		public static event Action<DayPhase> PhaseChanged;

		public static event Action<int> NightFell;

		public static event Action<int> DayBroke;

		public static void SetTimeOfDay(float t)
		{
			DayNightDriver active = DayNightDriver.Active;
			if ((Object)(object)active != (Object)null)
			{
				active.ShiftTimeTo(t);
			}
			else
			{
				TimeOfDay = Mathf.Repeat(t, 1f);
			}
		}

		public static string Clock()
		{
			int num = Mathf.FloorToInt(Mathf.Repeat(TimeOfDay, 1f) * 1440f);
			return $"{num / 60:00}:{num % 60:00}";
		}

		internal static void RaisePhaseChanged(DayPhase previous, DayPhase current)
		{
			Invoke(DayNightAPI.PhaseChanged, current, "PhaseChanged");
			if (current == DayPhase.Night && previous != DayPhase.Night)
			{
				Invoke(DayNightAPI.NightFell, DayNumber, "NightFell");
			}
			else if (current == DayPhase.Day && previous != DayPhase.Day)
			{
				Invoke(DayNightAPI.DayBroke, DayNumber, "DayBroke");
			}
		}

		private static void Invoke<T>(Action<T> handlers, T arg, string label)
		{
			if (handlers == null)
			{
				return;
			}
			Delegate[] invocationList = handlers.GetInvocationList();
			foreach (Delegate obj in invocationList)
			{
				try
				{
					((Action<T>)obj)(arg);
				}
				catch (Exception arg2)
				{
					Plugin.Log.LogError((object)$"{label} subscriber threw: {arg2}");
				}
			}
		}
	}
	internal sealed class DayNightDriver : MonoBehaviour
	{
		private readonly LightingRig _rig = new LightingRig();

		private readonly SkyRig _sky = new SkyRig();

		private ShaderManager _bound;

		private bool _wasEnabled = true;

		private double _offset;

		private float _localTime;

		internal static DayNightDriver Active { get; private set; }

		internal SkyRig Sky => _sky;

		public bool DrivenByNetwork { get; private set; }

		private void Awake()
		{
			Active = this;
			_localTime = Mathf.Repeat(Plugin.Cfg.StartTimeOfDay.Value, 1f);
			DayNightAPI.TimeOfDay = _localTime;
		}

		private void LateUpdate()
		{
			ModConfig cfg = Plugin.Cfg;
			if (!cfg.Enabled.Value)
			{
				if (_wasEnabled)
				{
					_rig.Restore();
					_rig.Reset();
					_sky.Restore();
					_sky.Reset();
					_bound = null;
					DayNightAPI.IsRunning = false;
					_wasEnabled = false;
				}
				return;
			}
			_wasEnabled = true;
			ShaderManager instance = LightingRig.Instance;
			if ((Object)(object)instance == (Object)null)
			{
				if ((Object)(object)_bound != (Object)null)
				{
					_rig.Reset();
					_bound = null;
					DayNightAPI.IsRunning = false;
				}
				return;
			}
			if (instance != _bound)
			{
				if (!_rig.Bind(instance))
				{
					return;
				}
				_bound = instance;
				DayNightAPI.IsRunning = true;
				if (!_sky.Bind())
				{
					Plugin.Log.LogWarning((object)"no sky material found, the skybox will stay vanilla");
				}
			}
			Advance(cfg);
			CycleState state = _rig.Apply(DayNightAPI.TimeOfDay, cfg);
			DayNightAPI.DaylightFactor = state.Daylight;
			if (cfg.DriveSky.Value)
			{
				_sky.Apply(in state, cfg);
			}
			UpdatePhase();
		}

		private void Advance(ModConfig cfg)
		{
			if (cfg.FreezeTime.Value)
			{
				return;
			}
			float num = Mathf.Max(1f, cfg.DayLengthSeconds.Value);
			if (cfg.SyncToNetworkTick.Value && NetworkClock.TryGetSeconds(out var seconds))
			{
				if (!DrivenByNetwork)
				{
					DrivenByNetwork = true;
					Plugin.Log.LogInfo((object)"clock driven by FishNet server tick");
				}
				double num2 = (double)cfg.StartTimeOfDay.Value + seconds / (double)num + _offset;
				DayNightAPI.TimeOfDay = (float)(num2 - Math.Floor(num2));
				DayNightAPI.DayNumber = 1 + (int)Math.Floor(num2);
				return;
			}
			if (DrivenByNetwork)
			{
				DrivenByNetwork = false;
				_localTime = DayNightAPI.TimeOfDay;
				Plugin.Log.LogInfo((object)"no TimeManager, clock fell back to local time");
			}
			float num3 = Mathf.Repeat(_localTime + Time.deltaTime / num, 1f);
			if (num3 < _localTime)
			{
				DayNightAPI.DayNumber++;
			}
			_localTime = num3;
			DayNightAPI.TimeOfDay = num3;
		}

		public void ShiftTimeTo(float target)
		{
			target = Mathf.Repeat(target, 1f);
			if (DrivenByNetwork)
			{
				_offset += target - DayNightAPI.TimeOfDay;
			}
			else
			{
				_localTime = target;
			}
			DayNightAPI.TimeOfDay = target;
		}

		public void ClearShift()
		{
			_offset = 0.0;
		}

		private static void UpdatePhase()
		{
			float daylightFactor = DayNightAPI.DaylightFactor;
			bool flag = DayNightAPI.TimeOfDay < 0.5f;
			DayPhase dayPhase = ((daylightFactor >= 0.85f) ? DayPhase.Day : ((!(daylightFactor <= 0.15f)) ? (flag ? DayPhase.Dawn : DayPhase.Dusk) : DayPhase.Night));
			if (dayPhase != DayNightAPI.Phase)
			{
				DayPhase phase = DayNightAPI.Phase;
				DayNightAPI.Phase = dayPhase;
				Plugin.Log.LogInfo((object)$"phase {phase} -> {dayPhase} at {DayNightAPI.Clock()} (day {DayNightAPI.DayNumber})");
				DayNightAPI.RaisePhaseChanged(phase, dayPhase);
			}
		}

		private void OnDestroy()
		{
			_rig.Restore();
			_sky.Restore();
			DayNightAPI.IsRunning = false;
			if (Active == this)
			{
				Active = null;
			}
		}
	}
	internal sealed class LightingRig
	{
		private static readonly FieldInfo F_Instance = AccessTools.Field(typeof(ShaderManager), "_instance");

		private static readonly FieldInfo F_MainLight = AccessTools.Field(typeof(ShaderManager), "_mainLight");

		private static readonly FieldInfo F_MainLightOrg = AccessTools.Field(typeof(ShaderManager), "_mainLightOrgRot");

		private static readonly FieldInfo F_SunsetRot = AccessTools.Field(typeof(ShaderManager), "_sunsetRot");

		private static readonly FieldInfo F_DefaultFogCol = AccessTools.Field(typeof(ShaderManager), "_defaultFogColor");

		private static readonly FieldInfo F_DefaultFogDen = AccessTools.Field(typeof(ShaderManager), "_defaultFogDensity");

		private static readonly FieldInfo F_SunsetColor = AccessTools.Field(typeof(ShaderManager), "_sunsetColor");

		private Transform _sun;

		private Light _sunLight;

		private Vector3 _noonEuler;

		private Vector3 _sunsetEuler;

		private Color _dayFogColor;

		private float _dayFogDensity;

		private Color _sunsetColor;

		private Color _daySunColor = Color.white;

		private float _daySunIntensity = 1f;

		private float _dayAmbient = 1f;

		private float _dayReflection = 1f;

		public static ShaderManager Instance
		{
			get
			{
				object? obj = F_Instance?.GetValue(null);
				ShaderManager val = (ShaderManager)((obj is ShaderManager) ? obj : null);
				if (!((Object)(object)val == (Object)null))
				{
					return val;
				}
				return null;
			}
		}

		public bool IsBound { get; private set; }

		public bool Bind(ShaderManager sm)
		{
			//IL_0073: Unknown result type (might be due to invalid IL or missing references)
			//IL_0078: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ab: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ea: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fb: Unknown result type (might be due to invalid IL or missing references)
			//IL_0100: Unknown result type (might be due to invalid IL or missing references)
			//IL_0131: Unknown result type (might be due to invalid IL or missing references)
			//IL_0136: Unknown result type (might be due to invalid IL or missing references)
			//IL_013b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0168: Unknown result type (might be due to invalid IL or missing references)
			//IL_0173: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ce: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d3: Unknown result type (might be due to invalid IL or missing references)
			Reset();
			if ((Object)(object)sm == (Object)null)
			{
				return false;
			}
			ref Transform sun = ref _sun;
			object? obj = F_MainLight?.GetValue(sm);
			sun = (Transform)((obj is Transform) ? obj : null);
			if ((Object)(object)_sun == (Object)null)
			{
				Plugin.Log.LogWarning((object)"ShaderManager._mainLight is null, lighting not bound yet");
				return false;
			}
			_sunLight = ((Component)_sun).GetComponent<Light>();
			if ((Object)(object)_sunLight != (Object)null)
			{
				_daySunColor = _sunLight.color;
				_daySunIntensity = _sunLight.intensity;
			}
			else
			{
				Plugin.Log.LogWarning((object)"no Light component on _mainLight, only rotation will be driven");
			}
			_noonEuler = Read<Vector3>(F_MainLightOrg, sm, Vector3.zero);
			if (_noonEuler == Vector3.zero)
			{
				_noonEuler = _sun.eulerAngles;
			}
			_sunsetEuler = Read<Vector3>(F_SunsetRot, sm, _noonEuler);
			_dayFogColor = Read<Color>(F_DefaultFogCol, sm, RenderSettings.fogColor);
			_dayFogDensity = Read(F_DefaultFogDen, sm, RenderSettings.fogDensity);
			_sunsetColor = Read<Color>(F_SunsetColor, sm, new Color(1f, 0.6f, 0.35f));
			_dayAmbient = RenderSettings.ambientIntensity;
			_dayReflection = RenderSettings.reflectionIntensity;
			IsBound = true;
			Plugin.Log.LogInfo((object)($"lighting bound. noon={_noonEuler} sunset={_sunsetEuler} " + $"fog={_dayFogDensity:F4} sun={_daySunIntensity:F2}"));
			return true;
		}

		public void Reset()
		{
			IsBound = false;
			_sun = null;
			_sunLight = null;
		}

		public void Restore()
		{
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0059: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			if (IsBound)
			{
				if ((Object)(object)_sun != (Object)null)
				{
					_sun.eulerAngles = _noonEuler;
				}
				if ((Object)(object)_sunLight != (Object)null)
				{
					_sunLight.color = _daySunColor;
					_sunLight.intensity = _daySunIntensity;
				}
				RenderSettings.fogColor = _dayFogColor;
				RenderSettings.fogDensity = _dayFogDensity;
				RenderSettings.ambientIntensity = _dayAmbient;
				RenderSettings.reflectionIntensity = _dayReflection;
			}
		}

		public CycleState Apply(float timeOfDay, ModConfig cfg)
		{
			//IL_00c5: Unknown result type (might be due to invalid IL or missing references)
			//IL_010b: 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_0119: Unknown result type (might be due to invalid IL or missing references)
			//IL_011e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0127: Unknown result type (might be due to invalid IL or missing references)
			//IL_012c: Unknown result type (might be due to invalid IL or missing references)
			//IL_012f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0229: Unknown result type (might be due to invalid IL or missing references)
			//IL_022e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0233: Unknown result type (might be due to invalid IL or missing references)
			//IL_0149: Unknown result type (might be due to invalid IL or missing references)
			//IL_014f: Invalid comparison between Unknown and I4
			//IL_0152: Unknown result type (might be due to invalid IL or missing references)
			//IL_0157: Unknown result type (might be due to invalid IL or missing references)
			//IL_0159: Unknown result type (might be due to invalid IL or missing references)
			//IL_015c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0166: Unknown result type (might be due to invalid IL or missing references)
			//IL_016b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0191: Unknown result type (might be due to invalid IL or missing references)
			//IL_0193: Unknown result type (might be due to invalid IL or missing references)
			//IL_019c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0175: Unknown result type (might be due to invalid IL or missing references)
			//IL_0178: Unknown result type (might be due to invalid IL or missing references)
			//IL_018a: Unknown result type (might be due to invalid IL or missing references)
			if (!IsBound || (Object)(object)_sun == (Object)null)
			{
				return CycleState.Daytime;
			}
			float num = Mathf.Sin((timeOfDay - 0.25f) * 2f * (float)Math.PI);
			float num2 = Mathf.SmoothStep(0f, 1f, Mathf.InverseLerp(-0.15f, 0.25f, num));
			float num3 = Mathf.Clamp01(1f - Mathf.Abs(num) * 3f);
			float num4 = _noonEuler.x * num;
			float num5 = Mathf.LerpAngle(_noonEuler.y - cfg.SunYawSweep.Value, _noonEuler.y + cfg.SunYawSweep.Value, timeOfDay);
			_sun.eulerAngles = new Vector3(num4, num5, _noonEuler.z);
			if ((Object)(object)_sunLight != (Object)null)
			{
				float num6 = _daySunIntensity * cfg.NightSunIntensity.Value;
				_sunLight.intensity = Mathf.Lerp(num6, _daySunIntensity, num2);
				Color val = Color.Lerp(_daySunColor, _sunsetColor, num3 * num2);
				_sunLight.color = Color.Lerp(cfg.MoonlightColor, val, num2);
			}
			if (cfg.DriveFog.Value && (int)FogStateTracker.Current != 1)
			{
				Color nightFogColor = cfg.NightFogColor;
				Color val2 = Color.Lerp(nightFogColor, _sunsetColor, 0.45f);
				RenderSettings.fogColor = ((num2 < 0.5f) ? Color.Lerp(nightFogColor, val2, num2 * 2f) : Color.Lerp(val2, _dayFogColor, (num2 - 0.5f) * 2f));
				RenderSettings.fogDensity = Mathf.Lerp(_dayFogDensity * cfg.NightFogDensityMultiplier.Value, _dayFogDensity, num2);
			}
			RenderSettings.ambientIntensity = Mathf.Lerp(cfg.NightAmbientIntensity.Value, _dayAmbient, num2);
			RenderSettings.reflectionIntensity = Mathf.Lerp(cfg.NightReflectionIntensity.Value, _dayReflection, num2);
			return new CycleState
			{
				Elevation = num,
				Daylight = num2,
				Horizon = num3,
				SunDirection = -_sun.forward
			};
		}

		private static T Read<T>(FieldInfo field, object target, T fallback)
		{
			if (field == null)
			{
				return fallback;
			}
			object value = field.GetValue(target);
			if (value is T)
			{
				return (T)value;
			}
			return fallback;
		}
	}
	internal sealed class ModConfig
	{
		public readonly ConfigEntry<bool> Enabled;

		public readonly ConfigEntry<float> DayLengthSeconds;

		public readonly ConfigEntry<float> StartTimeOfDay;

		public readonly ConfigEntry<bool> FreezeTime;

		public readonly ConfigEntry<bool> SyncToNetworkTick;

		public readonly ConfigEntry<float> SunYawSweep;

		public readonly ConfigEntry<float> NightSunIntensity;

		public readonly ConfigEntry<string> MoonlightColorHex;

		public readonly ConfigEntry<bool> DriveSky;

		public readonly ConfigEntry<string> SkyNightTopColorHex;

		public readonly ConfigEntry<string> SkyNightBottomColorHex;

		public readonly ConfigEntry<float> SunsetBandStrength;

		public readonly ConfigEntry<float> MoonBrightness;

		public readonly ConfigEntry<bool> DriveFog;

		public readonly ConfigEntry<string> NightFogColorHex;

		public readonly ConfigEntry<float> NightFogDensityMultiplier;

		public readonly ConfigEntry<float> NightAmbientIntensity;

		public readonly ConfigEntry<float> NightReflectionIntensity;

		public Color MoonlightColor => ParseHex(MoonlightColorHex.Value, new Color(0.36f, 0.48f, 0.72f));

		public Color NightFogColor => ParseHex(NightFogColorHex.Value, new Color(0.04f, 0.07f, 0.13f));

		public Color SkyNightTopColor => ParseHex(SkyNightTopColorHex.Value, new Color(0.03f, 0.05f, 0.1f));

		public Color SkyNightBottomColor => ParseHex(SkyNightBottomColorHex.Value, new Color(0.07f, 0.1f, 0.18f));

		public ModConfig(ConfigFile f)
		{
			//IL_004c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0056: Expected O, but got Unknown
			//IL_0085: Unknown result type (might be due to invalid IL or missing references)
			//IL_008f: Expected O, but got Unknown
			//IL_00f6: Unknown result type (might be due to invalid IL or missing references)
			//IL_0100: Expected O, but got Unknown
			//IL_012f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0139: Expected O, but got Unknown
			//IL_01e4: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ee: Expected O, but got Unknown
			//IL_021d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0227: Expected O, but got Unknown
			//IL_0292: Unknown result type (might be due to invalid IL or missing references)
			//IL_029c: Expected O, but got Unknown
			//IL_02cb: Unknown result type (might be due to invalid IL or missing references)
			//IL_02d5: Expected O, but got Unknown
			//IL_0304: Unknown result type (might be due to invalid IL or missing references)
			//IL_030e: Expected O, but got Unknown
			Enabled = f.Bind<bool>("01 - General", "Enabled", true, "Toggle the cycle. When off, the game returns to its original lighting.");
			DayLengthSeconds = f.Bind<float>("01 - General", "DayLengthSeconds", 1200f, new ConfigDescription("Length of one full cycle (day + night) in real seconds.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(30f, 14400f), Array.Empty<object>()));
			StartTimeOfDay = f.Bind<float>("01 - General", "StartTimeOfDay", 0.3f, new ConfigDescription("Starting time. 0 = midnight, 0.25 = dawn, 0.5 = noon, 0.75 = dusk.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1f), Array.Empty<object>()));
			FreezeTime = f.Bind<bool>("01 - General", "FreezeTime", false, "Hold the clock at the current time. Useful for testing the night look.");
			SyncToNetworkTick = f.Bind<bool>("01 - General", "SyncToNetworkTick", true, "Derive the time from the FishNet server tick so every player in the lobby sees the same sky. Requires all players to run this mod with matching DayLengthSeconds and StartTimeOfDay. Turn off to run a purely local clock.");
			SunYawSweep = f.Bind<float>("02 - Sun", "SunYawSweep", 60f, new ConfigDescription("Degrees of azimuth the sun sweeps across a full day, which rotates shadows.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 180f), Array.Empty<object>()));
			NightSunIntensity = f.Bind<float>("02 - Sun", "NightSunIntensity", 0.08f, new ConfigDescription("Directional light intensity at deepest night, as a fraction of the original daytime value.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1f), Array.Empty<object>()));
			MoonlightColorHex = f.Bind<string>("02 - Sun", "MoonlightColorHex", "#5C7BB8", "Directional light colour at night. Format #RRGGBB.");
			DriveSky = f.Bind<bool>("03 - Sky", "DriveSky", true, "Whether the mod retunes the skybox material. The skybox shader blends its own gradient from the sun direction, but its night colors were never authored: the night top is a copy of the day top and the night horizon is burnt orange, which is why vanilla night looks like a sunset. Turn off to leave the sky untouched.");
			SkyNightTopColorHex = f.Bind<string>("03 - Sky", "SkyNightTopColorHex", "#070C1A", "Replaces the skybox _TopNightColor, the zenith the shader blends toward at night. Format #RRGGBB.");
			SkyNightBottomColorHex = f.Bind<string>("03 - Sky", "SkyNightBottomColorHex", "#111A2E", "Replaces the skybox _BottomNightColor, the horizon the shader blends toward at night. Format #RRGGBB.");
			SunsetBandStrength = f.Bind<float>("03 - Sky", "SunsetBandStrength", 1f, new ConfigDescription("How much of the original warm sunrise and sunset band to keep at the horizon. 1 keeps it as authored, 0 removes it entirely.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1f), Array.Empty<object>()));
			MoonBrightness = f.Bind<float>("03 - Sky", "MoonBrightness", 1f, new ConfigDescription("Multiplier on the skybox moon at night.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 4f), Array.Empty<object>()));
			DriveFog = f.Bind<bool>("03 - Ambient", "DriveFog", true, "Whether the mod drives fog. Turn off if it fights another mod. The game underwater fog always wins regardless.");
			NightFogColorHex = f.Bind<string>("03 - Ambient", "NightFogColorHex", "#0B1220", "Fog colour at deepest night. Format #RRGGBB.");
			NightFogDensityMultiplier = f.Bind<float>("03 - Ambient", "NightFogDensityMultiplier", 1.8f, new ConfigDescription("Night fog density relative to the game default density.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.1f, 10f), Array.Empty<object>()));
			NightAmbientIntensity = f.Bind<float>("03 - Ambient", "NightAmbientIntensity", 0.15f, new ConfigDescription("RenderSettings.ambientIntensity at deepest night.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 2f), Array.Empty<object>()));
			NightReflectionIntensity = f.Bind<float>("03 - Ambient", "NightReflectionIntensity", 0.2f, new ConfigDescription("RenderSettings.reflectionIntensity at deepest night.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 2f), Array.Empty<object>()));
		}

		private static Color ParseHex(string hex, Color fallback)
		{
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			Color result = default(Color);
			if (!ColorUtility.TryParseHtmlString(hex, ref result))
			{
				return fallback;
			}
			return result;
		}
	}
	internal static class NetworkClock
	{
		public static bool TryGetSeconds(out double seconds)
		{
			seconds = 0.0;
			TimeManager timeManager = InstanceFinder.TimeManager;
			if ((Object)(object)timeManager == (Object)null)
			{
				return false;
			}
			seconds = timeManager.TicksToTime(timeManager.Tick);
			return true;
		}
	}
	[BepInPlugin("com.zpaulin.howtofish.daynight", "Day/Night Cycle", "1.0.0")]
	[BepInProcess("How to Fish.exe")]
	public sealed class Plugin : BaseUnityPlugin
	{
		private Harmony _harmony;

		private GameObject _host;

		internal static Plugin Instance { get; private set; }

		internal static ManualLogSource Log { get; private set; }

		internal static ModConfig Cfg { get; private set; }

		private void Awake()
		{
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: Expected O, but got Unknown
			//IL_0051: Unknown result type (might be due to invalid IL or missing references)
			//IL_0056: Unknown result type (might be due to invalid IL or missing references)
			//IL_0063: Expected O, but got Unknown
			Instance = this;
			Log = ((BaseUnityPlugin)this).Logger;
			Cfg = new ModConfig(((BaseUnityPlugin)this).Config);
			_harmony = new Harmony("com.zpaulin.howtofish.daynight");
			_harmony.PatchAll(typeof(Plugin).Assembly);
			_host = new GameObject("HowToFish.DayNight.Driver")
			{
				hideFlags = (HideFlags)61
			};
			Object.DontDestroyOnLoad((Object)(object)_host);
			_host.AddComponent<DayNightDriver>();
			Log.LogInfo((object)"Day/Night Cycle v1.0.0 loaded");
		}

		private void OnDestroy()
		{
			if ((Object)(object)_host != (Object)null)
			{
				Object.Destroy((Object)(object)_host);
			}
			Harmony harmony = _harmony;
			if (harmony != null)
			{
				harmony.UnpatchSelf();
			}
		}
	}
	public static class PluginInfo
	{
		public const string Guid = "com.zpaulin.howtofish.daynight";

		public const string Name = "Day/Night Cycle";

		public const string Version = "1.0.0";
	}
	internal sealed class SkyRig
	{
		private static readonly int TopNightColor = Shader.PropertyToID("_TopNightColor");

		private static readonly int BottomNightColor = Shader.PropertyToID("_BottomNightColor");

		private static readonly int BottomSunriseCol = Shader.PropertyToID("_BottomSunriseColor");

		private static readonly int MoonIntensity = Shader.PropertyToID("_MoonIntensity");

		private static readonly int[] TrackedColors = new int[3] { TopNightColor, BottomNightColor, BottomSunriseCol };

		private static readonly int[] TrackedFloats = new int[1] { MoonIntensity };

		private Material _sky;

		private readonly Dictionary<int, Color> _origColors = new Dictionary<int, Color>();

		private readonly Dictionary<int, float> _origFloats = new Dictionary<int, float>();

		public bool IsBound { get; private set; }

		public bool Bind()
		{
			//IL_0051: Unknown result type (might be due to invalid IL or missing references)
			Restore();
			Reset();
			_sky = FindSkyMaterial();
			if ((Object)(object)_sky == (Object)null)
			{
				return false;
			}
			int[] trackedColors = TrackedColors;
			foreach (int num in trackedColors)
			{
				if (_sky.HasProperty(num))
				{
					_origColors[num] = _sky.GetColor(num);
				}
			}
			trackedColors = TrackedFloats;
			foreach (int num2 in trackedColors)
			{
				if (_sky.HasProperty(num2))
				{
					_origFloats[num2] = _sky.GetFloat(num2);
				}
			}
			IsBound = true;
			ManualLogSource log = Plugin.Log;
			string[] obj = new string[6]
			{
				"sky bound to \"",
				((Object)_sky).name,
				"\" shader \"",
				null,
				null,
				null
			};
			Shader shader = _sky.shader;
			obj[3] = ((shader != null) ? ((Object)shader).name : null);
			obj[4] = "\", ";
			obj[5] = $"{_origColors.Count} colors and {_origFloats.Count} floats captured";
			log.LogInfo((object)string.Concat(obj));
			return true;
		}

		public void Reset()
		{
			IsBound = false;
			_sky = null;
			_origColors.Clear();
			_origFloats.Clear();
		}

		public void Restore()
		{
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)_sky == (Object)null)
			{
				return;
			}
			foreach (KeyValuePair<int, Color> origColor in _origColors)
			{
				_sky.SetColor(origColor.Key, origColor.Value);
			}
			foreach (KeyValuePair<int, float> origFloat in _origFloats)
			{
				_sky.SetFloat(origFloat.Key, origFloat.Value);
			}
		}

		public void Apply(in CycleState state, ModConfig cfg)
		{
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_005d: Unknown result type (might be due to invalid IL or missing references)
			//IL_00aa: Unknown result type (might be due to invalid IL or missing references)
			//IL_00af: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b1: Unknown result type (might be due to invalid IL or missing references)
			if (IsBound && !((Object)(object)_sky == (Object)null))
			{
				if (_sky.HasProperty(TopNightColor))
				{
					_sky.SetColor(TopNightColor, cfg.SkyNightTopColor);
				}
				if (_sky.HasProperty(BottomNightColor))
				{
					_sky.SetColor(BottomNightColor, cfg.SkyNightBottomColor);
				}
				if (_sky.HasProperty(BottomSunriseCol) && _origColors.TryGetValue(BottomSunriseCol, out var value))
				{
					float num = Mathf.Clamp01(cfg.SunsetBandStrength.Value);
					_sky.SetColor(BottomSunriseCol, Color.Lerp(cfg.SkyNightBottomColor, value, num));
				}
				if (_sky.HasProperty(MoonIntensity) && _origFloats.TryGetValue(MoonIntensity, out var value2))
				{
					_sky.SetFloat(MoonIntensity, value2 * cfg.MoonBrightness.Value);
				}
			}
		}

		private static Material FindSkyMaterial()
		{
			Material skybox = RenderSettings.skybox;
			if ((Object)(object)skybox != (Object)null && LooksLikeSky(skybox))
			{
				return skybox;
			}
			Renderer[] array = Object.FindObjectsByType<Renderer>((FindObjectsInactive)0);
			for (int i = 0; i < array.Length; i++)
			{
				Material sharedMaterial = array[i].sharedMaterial;
				if ((Object)(object)sharedMaterial != (Object)null && LooksLikeSky(sharedMaterial))
				{
					return sharedMaterial;
				}
			}
			return skybox;
		}

		private static bool LooksLikeSky(Material m)
		{
			if ((Object)(object)m == (Object)null)
			{
				return false;
			}
			if (m.HasProperty(TopNightColor) || m.HasProperty(BottomNightColor))
			{
				return true;
			}
			return (((Object)(object)m.shader != (Object)null) ? ((Object)m.shader).name : string.Empty).IndexOf("Skybox", StringComparison.OrdinalIgnoreCase) >= 0;
		}
	}
}
namespace HowToFish.DayNight.Patches
{
	[HarmonyPatch(typeof(DazedCommands), "IsServerCommand")]
	internal static class DazedCommandsPatch
	{
		private static bool Prefix(string __0, ref bool __result)
		{
			if (!ModCommands.TryHandle(__0))
			{
				return true;
			}
			__result = true;
			return false;
		}
	}
	internal static class ModCommands
	{
		private const string Root = "dn";

		public static bool TryHandle(string raw)
		{
			if (string.IsNullOrEmpty(raw))
			{
				return false;
			}
			string text = raw.Trim();
			if (text.StartsWith("/"))
			{
				text = text.Substring(1);
			}
			string[] array = text.Split(new char[1] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
			if (array.Length == 0)
			{
				return false;
			}
			if (!array[0].Equals("dn", StringComparison.OrdinalIgnoreCase))
			{
				return false;
			}
			string text2 = ((array.Length > 1) ? array[1].ToLowerInvariant() : "status");
			ModConfig cfg = Plugin.Cfg;
			switch (text2)
			{
			case "status":
				Report();
				return true;
			case "off":
			case "on":
				cfg.Enabled.Value = text2 == "on";
				Say("cycle " + text2);
				return true;
			case "day":
				DayNightAPI.SetTimeOfDay(0.5f);
				Say("time set to noon");
				return true;
			case "night":
				DayNightAPI.SetTimeOfDay(0f);
				Say("time set to midnight");
				return true;
			case "dawn":
				DayNightAPI.SetTimeOfDay(0.25f);
				Say("time set to dawn");
				return true;
			case "dusk":
				DayNightAPI.SetTimeOfDay(0.75f);
				Say("time set to dusk");
				return true;
			case "freeze":
				cfg.FreezeTime.Value = !cfg.FreezeTime.Value;
				Say(cfg.FreezeTime.Value ? "clock frozen" : "clock resumed");
				return true;
			case "resync":
				DayNightDriver.Active?.ClearShift();
				Say("local time shift cleared, back in sync with the lobby");
				return true;
			case "sky":
				cfg.DriveSky.Value = !cfg.DriveSky.Value;
				if (!cfg.DriveSky.Value)
				{
					DayNightDriver.Active?.Sky.Restore();
				}
				Say("sky driving " + (cfg.DriveSky.Value ? "on" : "off"));
				return true;
			case "time":
			{
				if (array.Length > 2 && TryParseTime(array[2], out var normalized))
				{
					DayNightAPI.SetTimeOfDay(normalized);
					Say("time set to " + DayNightAPI.Clock());
				}
				else
				{
					Say("usage: /dn time <0..1 | HH:MM>");
				}
				return true;
			}
			case "length":
			{
				if (array.Length > 2 && float.TryParse(array[2], out var result))
				{
					cfg.DayLengthSeconds.Value = Mathf.Clamp(result, 30f, 14400f);
					Say($"cycle length set to {cfg.DayLengthSeconds.Value:F0}s");
				}
				else
				{
					Say("usage: /dn length <seconds>");
				}
				return true;
			}
			default:
				Say("commands: status, on, off, day, night, dawn, dusk, freeze, resync, sky, time <v>, length <s>");
				return true;
			}
		}

		private static bool TryParseTime(string value, out float normalized)
		{
			normalized = 0f;
			if (value.Contains(":"))
			{
				string[] array = value.Split(new char[1] { ':' });
				if (array.Length == 2 && int.TryParse(array[0], out var result) && int.TryParse(array[1], out var result2))
				{
					normalized = Mathf.Repeat(((float)result * 60f + (float)result2) / 1440f, 1f);
					return true;
				}
				return false;
			}
			if (float.TryParse(value, out var result3))
			{
				normalized = Mathf.Repeat(result3, 1f);
				return true;
			}
			return false;
		}

		private static void Report()
		{
			Say($"{DayNightAPI.Clock()} | phase {DayNightAPI.Phase} | day {DayNightAPI.DayNumber} | " + $"light {DayNightAPI.DaylightFactor:F2} | running {DayNightAPI.IsRunning} | " + "source " + (DayNightAPI.IsNetworkSynced ? "server tick" : "local"));
		}

		private static void Say(string message)
		{
			Plugin.Log.LogMessage((object)("[dn] " + message));
		}
	}
	[HarmonyPatch(typeof(ShaderManager), "SetFog")]
	internal static class FogStateTracker
	{
		public static FogState Current { get; private set; }

		private static void Postfix(FogState __0)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			Current = __0;
		}
	}
}