Decompiled source of BetterSleepBruh v2.1.2

plugins/BetterSleepBruh.dll

Decompiled a month ago
using System;
using System.Collections;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Net.Http;
using System.Reflection;
using System.Reflection.Emit;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading;
using System.Threading.Tasks;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using BepInEx.Logging;
using BetterSleepBruh.Components;
using BetterSleepBruh.Configuration;
using BetterSleepBruh.Patches;
using HarmonyLib;
using JetBrains.Annotations;
using Jotunn.Entities;
using Jotunn.Managers;
using Jotunn.Utils;
using Microsoft.CodeAnalysis;
using TMPro;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.Events;
using UnityEngine.InputSystem;
using UnityEngine.InputSystem.Controls;
using UnityEngine.Networking;
using UnityEngine.UI;
using Valheim.SettingsGui;
using Vapok.Common.Abstractions;
using Vapok.Common.Managers;
using Vapok.Common.Managers.Configuration;
using Vapok.Common.Managers.Creature;
using Vapok.Common.Managers.LocalizationManager;
using Vapok.Common.Managers.Location;
using Vapok.Common.Managers.PieceManager;
using Vapok.Common.Managers.Skill;
using Vapok.Common.Managers.Splash;
using Vapok.Common.Managers.StatusEffects;
using Vapok.Common.Managers.Telemetry;
using Vapok.Common.Shared;
using Vapok.Common.Tools;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyTitle("BetterSleepBruh")]
[assembly: AssemblyDescription("A Valheim Mod that Sleeps Like Enshrouded!")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("Vapok Gaming")]
[assembly: AssemblyProduct("BetterSleepBruh")]
[assembly: AssemblyCopyright("Copyright ©  2025")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("997CB563-FCC7-44B7-8F71-069747D27CC5")]
[assembly: AssemblyFileVersion("2.1.2.0")]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("2.1.2.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 BetterSleepBruh
{
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInPlugin("vapok.mods.BetterSleepBruh", "BetterSleepBruh", "2.1.2")]
	[SynchronizationMode(/*Could not decode attribute arguments.*/)]
	public class BetterSleepBruh : BaseUnityPlugin, IPluginInfo
	{
		public class Waiting
		{
			public event EventHandler StatusChanged;

			public void ValheimIsAwake(bool awakeFlag)
			{
				if (awakeFlag)
				{
					this.StatusChanged?.Invoke(this, EventArgs.Empty);
				}
			}
		}

		private const string _pluginId = "vapok.mods.BetterSleepBruh";

		private const string _displayName = "BetterSleepBruh";

		private const string _version = "2.1.2";

		private SleepHudView _sleepHud;

		private int _sleepHudBuildAttempts;

		private bool _zNetHasStopped;

		public static bool ValheimAwake;

		public static Waiting Waiter;

		private static BetterSleepBruh _instance;

		private static ConfigSyncBase _config;

		private static ILogIt _log;

		private Harmony _harmony;

		public string PluginId => "vapok.mods.BetterSleepBruh";

		public string DisplayName => "BetterSleepBruh";

		public string Version => "2.1.2";

		public BaseUnityPlugin Instance => (BaseUnityPlugin)(object)_instance;

		public static BetterSleepBruh ModInstance => _instance;

		public static ILogIt Log => _log;

		[UsedImplicitly]
		private void Awake()
		{
			//IL_0066: Unknown result type (might be due to invalid IL or missing references)
			//IL_0070: Expected O, but got Unknown
			_instance = this;
			Waiter = new Waiting();
			CustomLocalization localization = LocalizationManager.Instance.GetLocalization();
			LogManager.Init(PluginId, out _log);
			Localizer.Init(localization);
			_config = new ConfigRegistry(_instance);
			Localizer.Waiter.StatusChanged += InitializeModule;
			_harmony = new Harmony(((BaseUnityPlugin)this).Info.Metadata.GUID);
			_harmony.PatchAll(Assembly.GetExecutingAssembly());
			ModSplashManager.Register(new ModSplashDossier(_instance)
			{
				Tagline = "Sleep mechanics inspired by Enshrouded allowing fast time progression without requiring all players in bed.",
				ShowOnStartup = ConfigSyncBase.ShowSplashOnStartup
			});
		}

		private void Start()
		{
			ConfigRegistry.Waiter.ConfigurationComplete(configDone: true);
			ResetSession();
		}

		public void ResetSession()
		{
			_zNetHasStopped = false;
			_sleepHudBuildAttempts = 0;
			_sleepHud = null;
			((MonoBehaviour)this).CancelInvoke("WaitForGame");
			((MonoBehaviour)this).CancelInvoke("WaitForZNet");
			((MonoBehaviour)this).CancelInvoke("TryBuildSleepHud");
			((MonoBehaviour)this).InvokeRepeating("WaitForGame", 0.5f, 0.5f);
			((MonoBehaviour)this).InvokeRepeating("WaitForZNet", 0.5f, 0.5f);
		}

		private void WaitForGame()
		{
			if (!((Object)(object)Game.instance == (Object)null))
			{
				((MonoBehaviour)this).CancelInvoke("WaitForGame");
				((MonoBehaviour)this).InvokeRepeating("TryBuildSleepHud", 0f, 0.25f);
			}
		}

		private void WaitForZNet()
		{
			if (!((Object)(object)ZNet.instance == (Object)null) && !_zNetHasStopped)
			{
				((MonoBehaviour)this).CancelInvoke("WaitForZNet");
				if (ZNet.instance.IsServer())
				{
					((Component)Game.instance).gameObject.AddComponent<SleepTracker>();
				}
			}
		}

		private void TryBuildSleepHud()
		{
			Log.Debug("Waiting for GuiBuild");
			if ((Object)(object)_sleepHud != (Object)null)
			{
				((MonoBehaviour)this).CancelInvoke("TryBuildSleepHud");
				return;
			}
			Log.Debug("[GuiBuild] Checking for Server...");
			if (GUIManager.IsHeadless() || ((Object)(object)ZNet.instance != (Object)null && ZNet.instance.IsDedicated()))
			{
				((MonoBehaviour)this).CancelInvoke("TryBuildSleepHud");
				return;
			}
			Log.Debug($"[GuiBuild] Checking for previous ZNetShutdown {_zNetHasStopped}...");
			if (_zNetHasStopped)
			{
				return;
			}
			Log.Debug("[GuiBuild] Checking for Player...");
			if ((Object)(object)Player.m_localPlayer == (Object)null)
			{
				return;
			}
			Log.Debug("[GuiBuild] Checking Attempts...");
			if (_sleepHudBuildAttempts++ > 120)
			{
				((MonoBehaviour)this).CancelInvoke("TryBuildSleepHud");
				Log.Warning("[GuiBuild] Gave up building sleep HUD: minimap hierarchy not found in time.");
				return;
			}
			Log.Debug("[GuiBuild] Building GUI");
			BuildSleepGui();
			if ((Object)(object)_sleepHud != (Object)null)
			{
				((MonoBehaviour)this).CancelInvoke("TryBuildSleepHud");
			}
			Log.Debug($"[GuiBuild] SleepHud is built: {(Object)(object)_sleepHud != (Object)null}");
		}

		private void BuildSleepGui()
		{
			GameObject val = GameObject.Find("_GameMain");
			if ((Object)(object)val == (Object)null)
			{
				Log.Debug("[GuiBuild] Can't Find _GameMain");
				return;
			}
			Transform val2 = val.transform.Find("LoadingGUI/PixelFix/IngameGui/HUD/hudroot");
			if ((Object)(object)val2 == (Object)null)
			{
				Log.Debug("[GuiBuild] Can't Find HUD");
				return;
			}
			Transform val3 = val2.Find("MiniMap/small");
			if ((Object)(object)val3 == (Object)null)
			{
				Log.Debug("[GuiBuild] Can't Find Minimap");
				return;
			}
			_sleepHud = SleepHudView.TryCreate(val3);
			if ((Object)(object)_sleepHud != (Object)null)
			{
				bool active = (Object)(object)EnvMan.instance != (Object)null && EnvManPatches.IsInSleepWindow(EnvMan.instance);
				((Component)_sleepHud).gameObject.SetActive(active);
			}
			else
			{
				Log.Warning("[GuiBuild] Can't Build SleepHud");
			}
		}

		private void Update()
		{
			if (!((Object)(object)ZNet.instance == (Object)null))
			{
				bool haveStopped = ZNet.instance.HaveStopped;
				if (haveStopped && !_zNetHasStopped)
				{
					_zNetHasStopped = true;
					_sleepHud = null;
					((MonoBehaviour)this).CancelInvoke("WaitForGame");
					((MonoBehaviour)this).CancelInvoke("WaitForZNet");
					((MonoBehaviour)this).CancelInvoke("TryBuildSleepHud");
				}
				else if (!haveStopped && _zNetHasStopped)
				{
					ResetSession();
				}
				else if (Object.op_Implicit((Object)(object)Player.m_localPlayer) && Object.op_Implicit((Object)(object)ZNetScene.instance) && Object.op_Implicit((Object)(object)Game.instance) && (Object)(object)_sleepHud == (Object)null && !((MonoBehaviour)this).IsInvoking("TryBuildSleepHud"))
				{
					_sleepHudBuildAttempts = 0;
					((MonoBehaviour)this).InvokeRepeating("TryBuildSleepHud", 0f, 0.25f);
				}
			}
		}

		public void InitializeModule(object send, EventArgs args)
		{
			if (!ValheimAwake)
			{
				ValheimAwake = true;
			}
		}

		private void OnDestroy()
		{
			_instance = null;
		}
	}
}
namespace BetterSleepBruh.Patches
{
	internal static class CookingStationPatches
	{
		[HarmonyPatch(typeof(CookingStation), "GetDeltaTime")]
		private static class GetDeltaTimePatch
		{
			private static void Postfix(ref float __result)
			{
				if (ConfigRegistry.ProtectCookingTimers != null && ConfigRegistry.ProtectCookingTimers.Value && SleepTracker.CurrentExtraRate > 0.0)
				{
					__result /= (float)(1.0 + SleepTracker.CurrentExtraRate);
				}
			}
		}
	}
	internal static class EnvManPatches
	{
		[HarmonyPatch(typeof(EnvMan), "CalculateCanSleep")]
		private static class CalculateCanSleepPatch
		{
			private static bool Prefix(EnvMan __instance, ref bool __result)
			{
				if (ConfigRegistry.UseVanilleSleep != null && ConfigRegistry.UseVanilleSleep.Value)
				{
					return true;
				}
				if (!IsInSleepWindow(__instance))
				{
					__result = false;
					return false;
				}
				Player localPlayer = Player.m_localPlayer;
				if ((Object)(object)localPlayer != (Object)null && (Object)(object)ZNet.instance != (Object)null && ZNet.instance.GetTimeSeconds() <= localPlayer.m_wakeupTime + __instance.m_sleepCooldownSeconds)
				{
					__result = false;
					return false;
				}
				__result = true;
				return false;
			}
		}

		public static bool IsInSleepWindow(EnvMan envMan)
		{
			if ((Object)(object)envMan == (Object)null || envMan.IsTimeSkipping())
			{
				return false;
			}
			float dayFraction = envMan.GetDayFraction();
			float num = ((ConfigRegistry.SleepStart != null) ? ConfigRegistry.SleepStart.Value : 0.5f);
			if (num < 0.25f)
			{
				if (dayFraction < 0.25f)
				{
					return dayFraction >= num;
				}
				return false;
			}
			if (!(dayFraction >= num))
			{
				return dayFraction < 0.25f;
			}
			return true;
		}
	}
	public class FejdStartupPatches
	{
		[HarmonyPatch(typeof(FejdStartup), "Awake")]
		[HarmonyAfter(new string[] { "vapok.common.LocalizationManager", "org.bepinex.helpers.LocalizationManager" })]
		[HarmonyBefore(new string[] { "vapok.common.ItemManager", "org.bepinex.helpers.ItemManager" })]
		public static class FejdStartupAwakePatch
		{
			private static void Prefix()
			{
				BetterSleepBruh.Waiter.ValheimIsAwake(awakeFlag: true);
				BetterSleepBruh.ModInstance?.ResetSession();
			}
		}
	}
	internal static class FermenterPatches
	{
		[HarmonyPatch(typeof(Fermenter), "GetFermentationTime")]
		private static class GetFermentationTimePatch
		{
			private static void Prefix(Fermenter __instance)
			{
				if (ConfigRegistry.ProtectMeadTimers == null || !ConfigRegistry.ProtectMeadTimers.Value)
				{
					return;
				}
				ZNetView nview = __instance.m_nview;
				if ((Object)(object)nview == (Object)null || !nview.IsValid() || !nview.IsOwner())
				{
					return;
				}
				ZDO zDO = nview.GetZDO();
				if (zDO == null)
				{
					return;
				}
				long num = zDO.GetLong(ZDOVars.s_startTime, 0L);
				if (num == 0L)
				{
					return;
				}
				long num2 = (long)(SleepTracker.TotalPartialSleepBoostSeconds * 10000000.0);
				long num3 = zDO.GetLong(_lastBoostCheckKey, -1L);
				if (num3 < 0)
				{
					if (nview.IsOwner())
					{
						zDO.Set(_lastBoostCheckKey, num2);
					}
					return;
				}
				long num4 = num2 - num3;
				if (num4 > 0)
				{
					if (nview.IsOwner())
					{
						long num5 = num + num4;
						zDO.Set(ZDOVars.s_startTime, num5);
						zDO.Set(_lastBoostCheckKey, num2);
					}
				}
				else if (num3 > num2 && nview.IsOwner())
				{
					zDO.Set(_lastBoostCheckKey, num2);
				}
			}
		}

		private static readonly int _lastBoostCheckKey = StringExtensionMethods.GetStableHashCode("BSB_FermenterBoostChecked");
	}
	internal static class GamePatches
	{
		[HarmonyPatch(typeof(Game), "UpdateSleeping")]
		private static class UpdateSleepingPatch
		{
			private static bool Prefix(Game __instance)
			{
				if (ConfigRegistry.UseVanilleSleep != null && ConfigRegistry.UseVanilleSleep.Value)
				{
					return true;
				}
				if ((Object)(object)__instance == (Object)null || (Object)(object)ZNet.instance == (Object)null || !ZNet.instance.IsServer() || (Object)(object)EnvMan.instance == (Object)null)
				{
					return false;
				}
				if (__instance.m_sleeping)
				{
					if (!EnvMan.instance.IsTimeSkipping())
					{
						__instance.m_sleeping = false;
						if (ZRoutedRpc.instance != null)
						{
							ZRoutedRpc.instance.InvokeRoutedRPC(0L, "SleepStop", Array.Empty<object>());
						}
					}
					return false;
				}
				if (EnvMan.instance.IsTimeSkipping() || !EnvManPatches.IsInSleepWindow(EnvMan.instance))
				{
					return false;
				}
				if (SleepTracker.AllPlayersSleeping)
				{
					__instance.m_sleeping = true;
					if (ZRoutedRpc.instance != null)
					{
						ZRoutedRpc.instance.InvokeRoutedRPC(0L, "SleepStart", Array.Empty<object>());
					}
					try
					{
						EnvMan.instance.SkipToMorning();
					}
					catch (Exception ex)
					{
						BetterSleepBruh.Log.Warning("Error while skipping to morning: " + ex.Message);
					}
				}
				return false;
			}
		}
	}
	internal static class PickablePatches
	{
		[HarmonyPatch(typeof(Pickable), "ShouldRespawn")]
		private static class ShouldRespawnPatch
		{
			private static void Prefix(Pickable __instance)
			{
				ApplyBoostShift(__instance);
			}
		}

		[HarmonyPatch(typeof(Pickable), "SetPicked")]
		private static class SetPickedPatch
		{
			private static void Postfix(Pickable __instance, bool picked)
			{
				if (!picked || ConfigRegistry.ProtectPickableTimers == null || !ConfigRegistry.ProtectPickableTimers.Value || (Object)(object)__instance == (Object)null || __instance.m_respawnTimeMinutes <= 0f)
				{
					return;
				}
				ZNetView val = _nviewRef.Invoke(__instance);
				if ((Object)(object)val == (Object)null)
				{
					val = ((Component)__instance).GetComponent<ZNetView>();
				}
				if (!((Object)(object)val == (Object)null) && val.IsValid() && val.IsOwner())
				{
					ZDO zDO = val.GetZDO();
					if (zDO != null)
					{
						long num = (long)(SleepTracker.TotalPartialSleepBoostSeconds * 10000000.0);
						zDO.Set(_lastBoostCheckKey, num);
					}
				}
			}
		}

		[HarmonyPatch(typeof(Pickable), "GetHoverText")]
		private static class GetHoverTextPatch
		{
			private static void Prefix(Pickable __instance)
			{
				ApplyBoostShift(__instance);
			}
		}

		private static readonly int _lastBoostCheckKey = StringExtensionMethods.GetStableHashCode("BSB_PickableBoostChecked");

		private static readonly FieldRef<Pickable, ZNetView> _nviewRef = AccessTools.FieldRefAccess<Pickable, ZNetView>("m_nview");

		private static void ApplyBoostShift(Pickable pickable)
		{
			if (ConfigRegistry.ProtectPickableTimers == null || !ConfigRegistry.ProtectPickableTimers.Value || (Object)(object)pickable == (Object)null || pickable.m_respawnTimeMinutes <= 0f || !pickable.GetPicked())
			{
				return;
			}
			ZNetView val = _nviewRef.Invoke(pickable);
			if ((Object)(object)val == (Object)null)
			{
				val = ((Component)pickable).GetComponent<ZNetView>();
			}
			if ((Object)(object)val == (Object)null || !val.IsValid() || !val.IsOwner())
			{
				return;
			}
			ZDO zDO = val.GetZDO();
			if (zDO == null)
			{
				return;
			}
			long num = (long)(SleepTracker.TotalPartialSleepBoostSeconds * 10000000.0);
			long num2 = zDO.GetLong(_lastBoostCheckKey, -1L);
			if (num2 < 0)
			{
				zDO.Set(_lastBoostCheckKey, num);
				return;
			}
			long num3 = num - num2;
			if (num3 > 0)
			{
				long num4 = zDO.GetLong(ZDOVars.s_pickedTime, 0L);
				if (num4 > 0)
				{
					long num5 = num4 + num3;
					zDO.Set(ZDOVars.s_pickedTime, num5);
				}
				zDO.Set(_lastBoostCheckKey, num);
			}
			else if (num2 > num)
			{
				zDO.Set(_lastBoostCheckKey, num);
			}
		}
	}
	internal static class PlantPatches
	{
		[HarmonyPatch(typeof(Plant), "TimeSincePlanted")]
		private static class TimeSincePlantedPatch
		{
			private static void Prefix(Plant __instance)
			{
				if (ConfigRegistry.ProtectCropTimers == null || !ConfigRegistry.ProtectCropTimers.Value)
				{
					return;
				}
				ZNetView nview = __instance.m_nview;
				if ((Object)(object)nview == (Object)null || !nview.IsValid() || !nview.IsOwner())
				{
					return;
				}
				ZDO zDO = nview.GetZDO();
				if (zDO == null)
				{
					return;
				}
				long num = (long)(SleepTracker.TotalPartialSleepBoostSeconds * 10000000.0);
				long num2 = zDO.GetLong(_lastBoostCheckKey, -1L);
				if (num2 < 0)
				{
					if (nview.IsOwner())
					{
						zDO.Set(_lastBoostCheckKey, num);
					}
					return;
				}
				long num3 = num - num2;
				if (num3 > 0)
				{
					if (nview.IsOwner())
					{
						long num4 = zDO.GetLong(ZDOVars.s_plantTime, 0L);
						if (num4 > 0)
						{
							long num5 = num4 + num3;
							zDO.Set(ZDOVars.s_plantTime, num5);
						}
						zDO.Set(_lastBoostCheckKey, num);
					}
				}
				else if (num2 > num && nview.IsOwner())
				{
					zDO.Set(_lastBoostCheckKey, num);
				}
			}
		}

		private static readonly int _lastBoostCheckKey = StringExtensionMethods.GetStableHashCode("BSB_LastBoostChecked");
	}
	internal static class PlayerPatches
	{
		[HarmonyPatch(typeof(Player), "AttachStart")]
		private static class AttachStartPatch
		{
			private static void Postfix(Player __instance, bool isBed)
			{
				if (isBed && !((Object)(object)ZNet.instance == (Object)null))
				{
					if ((Object)(object)SleepTracker.Instance != (Object)null && ZNet.instance.IsServer())
					{
						SleepTracker.Instance.OnBedOccupancyChanged();
					}
					else if ((Object)(object)__instance == (Object)(object)Player.m_localPlayer && ZRoutedRpc.instance != null)
					{
						ZRoutedRpc.instance.InvokeRoutedRPC(ZRoutedRpc.instance.GetServerPeerID(), "NotifyBedOccupancyChanged", Array.Empty<object>());
					}
				}
			}
		}

		[HarmonyPatch(typeof(Player), "AttachStop")]
		private static class AttachStopPatch
		{
			private static void Prefix(Player __instance, out bool __state)
			{
				__state = ((Character)__instance).InBed();
			}

			private static void Postfix(Player __instance, bool __state)
			{
				if (__state && !((Object)(object)ZNet.instance == (Object)null))
				{
					if ((Object)(object)SleepTracker.Instance != (Object)null && ZNet.instance.IsServer())
					{
						SleepTracker.Instance.OnBedOccupancyChanged();
					}
					else if ((Object)(object)__instance == (Object)(object)Player.m_localPlayer && ZRoutedRpc.instance != null)
					{
						ZRoutedRpc.instance.InvokeRoutedRPC(ZRoutedRpc.instance.GetServerPeerID(), "NotifyBedOccupancyChanged", Array.Empty<object>());
					}
				}
			}
		}
	}
	internal static class ShipPatches
	{
		[HarmonyPatch(typeof(Ship), "UpdateWaterForce")]
		private static class UpdateWaterForcePatch
		{
			private static bool Prefix(Ship __instance, float depth, float time)
			{
				if (SleepTracker.CurrentExtraRate <= 0.0)
				{
					return true;
				}
				bool num = ConfigRegistry.PreventBoatSleepImpactDamage != null && ConfigRegistry.PreventBoatSleepImpactDamage.Value;
				bool flag = ConfigRegistry.SuppressBoatImpactScreenShake != null && ConfigRegistry.SuppressBoatImpactScreenShake.Value;
				if (num || flag)
				{
					__instance.m_lastDepth = depth;
					__instance.m_lastUpdateWaterForceTime = time;
					return false;
				}
				return true;
			}
		}
	}
	internal static class SmelterPatches
	{
		[HarmonyPatch(typeof(Smelter), "GetDeltaTime")]
		private static class GetDeltaTimePatch
		{
			private static void Postfix(ref double __result)
			{
				if (ConfigRegistry.ProtectSmelterTimers != null && ConfigRegistry.ProtectSmelterTimers.Value && SleepTracker.CurrentExtraRate > 0.0)
				{
					__result /= 1.0 + SleepTracker.CurrentExtraRate;
				}
			}
		}
	}
	internal static class WaterVolumePatches
	{
		[HarmonyPatch(typeof(WaterVolume), "UpdateWaterTime")]
		private static class UpdateWaterTimePatch
		{
			private static bool Prefix(float dt)
			{
				if (ConfigRegistry.DecoupleWaterWaveSpeed == null || !ConfigRegistry.DecoupleWaterWaveSpeed.Value)
				{
					return true;
				}
				if (SleepTracker.CurrentExtraRate <= 0.0)
				{
					return true;
				}
				WaterVolume.s_wrappedDayTimeSeconds = (WaterVolume.s_wrappedDayTimeSeconds + dt) % 86400f;
				WaterVolume.s_waterTime += dt;
				return false;
			}
		}

		[HarmonyPatch(typeof(WaterVolume), "GetWaterSurface")]
		private static class GetWaterSurfacePatch
		{
			private static void Prefix(ref float waveFactor)
			{
				if (ConfigRegistry.CalmOceanDuringSleep != null && ConfigRegistry.CalmOceanDuringSleep.Value)
				{
					float num = ((!(SleepTracker.CurrentExtraRate > 0.0)) ? 1f : ((ConfigRegistry.OceanCalmMultiplier != null) ? ConfigRegistry.OceanCalmMultiplier.Value : 0.5f));
					int frameCount = Time.frameCount;
					if (_lastCalmFrame != frameCount)
					{
						_lastCalmFrame = frameCount;
						_currentCalmFactor = Mathf.MoveTowards(_currentCalmFactor, num, Time.deltaTime * 0.5f);
					}
					waveFactor *= _currentCalmFactor;
				}
			}
		}

		private static float _currentCalmFactor = 1f;

		private static int _lastCalmFrame = -1;
	}
	internal static class ZNetPatches
	{
		[HarmonyPatch(typeof(ZNet), "UpdateNetTime")]
		private static class UpdateNetTime
		{
			private static void Postfix(ZNet __instance, float dt)
			{
				if (!__instance.IsServer() || __instance.GetNrOfPlayers() <= 0 || (Object)(object)SleepTracker.Instance == (Object)null || !SleepTracker.Instance.Enabled)
				{
					return;
				}
				double currentExtraRate = SleepTracker.CurrentExtraRate;
				if (currentExtraRate <= 0.0)
				{
					_timeSyncTimer = 0f;
					return;
				}
				double timeSeconds = __instance.GetTimeSeconds();
				double nextMorningCapSeconds = SleepTracker.GetNextMorningCapSeconds();
				if (double.IsPositiveInfinity(nextMorningCapSeconds))
				{
					__instance.SetNetTime(timeSeconds + (double)dt * currentExtraRate);
					SyncNetTimeToPeers(__instance, dt);
					return;
				}
				if (timeSeconds >= nextMorningCapSeconds)
				{
					__instance.SetNetTime(nextMorningCapSeconds);
					_timeSyncTimer = 0f;
					return;
				}
				double num = nextMorningCapSeconds - timeSeconds;
				double num2 = currentExtraRate;
				float num3 = ((ConfigRegistry.BoostFadeRealSecondsBeforeMorning != null) ? ConfigRegistry.BoostFadeRealSecondsBeforeMorning.Value : 2f);
				if (num3 > 0f)
				{
					double num4 = 1.0 + currentExtraRate;
					double num5 = (double)num3 * num4;
					if (num < num5)
					{
						num2 = currentExtraRate * (num / num5);
					}
				}
				double num6 = Math.Min((double)dt * num2, num);
				__instance.SetNetTime(timeSeconds + num6);
				if (num6 > 0.0)
				{
					SleepTracker.TotalPartialSleepBoostSeconds += num6;
					SyncNetTimeToPeers(__instance, dt);
				}
			}

			private static void SyncNetTimeToPeers(ZNet znet, float dt)
			{
				if (znet.m_peers == null || znet.m_peers.Count == 0)
				{
					return;
				}
				_timeSyncTimer += dt;
				if (_timeSyncTimer < 0.25f)
				{
					return;
				}
				_timeSyncTimer = 0f;
				double timeSeconds = znet.GetTimeSeconds();
				for (int i = 0; i < znet.m_peers.Count; i++)
				{
					ZNetPeer val = znet.m_peers[i];
					if (val != null && val.IsReady() && val.m_rpc != null)
					{
						val.m_rpc.Invoke("NetTime", new object[1] { timeSeconds });
					}
				}
				if (ZRoutedRpc.instance != null)
				{
					ZRoutedRpc.instance.InvokeRoutedRPC(0L, "BSB_SyncSleepBoostTotal", new object[1] { SleepTracker.TotalPartialSleepBoostSeconds });
				}
			}
		}

		[HarmonyPatch(typeof(ZNet), "SaveWorld")]
		private static class SaveWorldPatch
		{
			private static void Postfix()
			{
				SleepTracker.SaveData();
			}
		}

		private static float _timeSyncTimer;

		private const float TimeSyncInterval = 0.25f;
	}
}
namespace BetterSleepBruh.Configuration
{
	public class ConfigRegistry : ConfigSyncBase
	{
		public static Waiting Waiter;

		public static ConfigEntry<bool> UseVanilleSleep;

		public static ConfigEntry<bool> TestingMode;

		public static ConfigEntry<int> TestingMaxPlayers;

		public static ConfigEntry<int> TestingSleepingPlayers;

		public static ConfigEntry<float> SleepStart;

		public static ConfigEntry<float> BonusMultiplier;

		public static ConfigEntry<float> BonusIncrementScale;

		public static ConfigEntry<float> BoostFadeRealSecondsBeforeMorning;

		public static ConfigEntry<bool> ProtectCookingTimers;

		public static ConfigEntry<bool> ProtectSmelterTimers;

		public static ConfigEntry<bool> ProtectCropTimers;

		public static ConfigEntry<bool> ProtectMeadTimers;

		public static ConfigEntry<bool> ProtectPickableTimers;

		public static ConfigEntry<bool> DecoupleWaterWaveSpeed;

		public static ConfigEntry<bool> CalmOceanDuringSleep;

		public static ConfigEntry<float> OceanCalmMultiplier;

		public static ConfigEntry<bool> PreventBoatSleepImpactDamage;

		public static ConfigEntry<bool> SuppressBoatImpactScreenShake;

		public static bool IsPlayerCountTestingActive
		{
			get
			{
				if (TestingMode != null)
				{
					return TestingMode.Value;
				}
				return false;
			}
		}

		public ConfigRegistry(IPluginInfo mod, bool enableLockedConfigs = false)
			: base(mod, enableLockedConfigs)
		{
			Waiter = new Waiting();
			InitializeConfigurationSettings();
		}

		public sealed override void InitializeConfigurationSettings()
		{
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_003a: Expected O, but got Unknown
			//IL_003a: Unknown result type (might be due to invalid IL or missing references)
			//IL_004a: Expected O, but got Unknown
			//IL_0075: Unknown result type (might be due to invalid IL or missing references)
			//IL_007a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0086: Unknown result type (might be due to invalid IL or missing references)
			//IL_008e: Expected O, but got Unknown
			//IL_008e: Unknown result type (might be due to invalid IL or missing references)
			//IL_009e: Expected O, but got Unknown
			//IL_00c9: 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_00da: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e2: Expected O, but got Unknown
			//IL_00e2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f2: Expected O, but got Unknown
			//IL_011d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0122: Unknown result type (might be due to invalid IL or missing references)
			//IL_012e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0136: Expected O, but got Unknown
			//IL_0136: Unknown result type (might be due to invalid IL or missing references)
			//IL_0146: Expected O, but got Unknown
			//IL_0171: Unknown result type (might be due to invalid IL or missing references)
			//IL_0176: Unknown result type (might be due to invalid IL or missing references)
			//IL_0182: Unknown result type (might be due to invalid IL or missing references)
			//IL_018a: Expected O, but got Unknown
			//IL_018a: Unknown result type (might be due to invalid IL or missing references)
			//IL_019a: Expected O, but got Unknown
			//IL_01b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c4: Unknown result type (might be due to invalid IL or missing references)
			//IL_01cc: Expected O, but got Unknown
			//IL_01cc: Unknown result type (might be due to invalid IL or missing references)
			//IL_01dc: Expected O, but got Unknown
			//IL_01fd: Unknown result type (might be due to invalid IL or missing references)
			//IL_0202: Unknown result type (might be due to invalid IL or missing references)
			//IL_020e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0216: Expected O, but got Unknown
			//IL_0216: Unknown result type (might be due to invalid IL or missing references)
			//IL_0226: Expected O, but got Unknown
			//IL_0246: Unknown result type (might be due to invalid IL or missing references)
			//IL_024b: 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_025f: Expected O, but got Unknown
			//IL_025f: Unknown result type (might be due to invalid IL or missing references)
			//IL_026f: Expected O, but got Unknown
			//IL_0288: Unknown result type (might be due to invalid IL or missing references)
			//IL_028d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0299: Unknown result type (might be due to invalid IL or missing references)
			//IL_02a1: Expected O, but got Unknown
			//IL_02a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_02b1: Expected O, but got Unknown
			//IL_02ca: Unknown result type (might be due to invalid IL or missing references)
			//IL_02cf: Unknown result type (might be due to invalid IL or missing references)
			//IL_02db: Unknown result type (might be due to invalid IL or missing references)
			//IL_02e3: Expected O, but got Unknown
			//IL_02e3: Unknown result type (might be due to invalid IL or missing references)
			//IL_02f3: Expected O, but got Unknown
			//IL_030c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0311: Unknown result type (might be due to invalid IL or missing references)
			//IL_031d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0325: Expected O, but got Unknown
			//IL_0325: Unknown result type (might be due to invalid IL or missing references)
			//IL_0335: Expected O, but got Unknown
			//IL_034e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0353: Unknown result type (might be due to invalid IL or missing references)
			//IL_035f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0367: Expected O, but got Unknown
			//IL_0367: Unknown result type (might be due to invalid IL or missing references)
			//IL_0377: Expected O, but got Unknown
			//IL_0390: Unknown result type (might be due to invalid IL or missing references)
			//IL_0395: Unknown result type (might be due to invalid IL or missing references)
			//IL_03a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_03a9: Expected O, but got Unknown
			//IL_03a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_03b9: Expected O, but got Unknown
			//IL_03d2: Unknown result type (might be due to invalid IL or missing references)
			//IL_03d7: Unknown result type (might be due to invalid IL or missing references)
			//IL_03e3: Unknown result type (might be due to invalid IL or missing references)
			//IL_03eb: Expected O, but got Unknown
			//IL_03eb: Unknown result type (might be due to invalid IL or missing references)
			//IL_03fb: Expected O, but got Unknown
			//IL_0414: Unknown result type (might be due to invalid IL or missing references)
			//IL_0419: Unknown result type (might be due to invalid IL or missing references)
			//IL_0425: Unknown result type (might be due to invalid IL or missing references)
			//IL_042d: Expected O, but got Unknown
			//IL_042d: Unknown result type (might be due to invalid IL or missing references)
			//IL_043d: Expected O, but got Unknown
			//IL_0468: Unknown result type (might be due to invalid IL or missing references)
			//IL_046d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0479: Unknown result type (might be due to invalid IL or missing references)
			//IL_0481: Expected O, but got Unknown
			//IL_0481: Unknown result type (might be due to invalid IL or missing references)
			//IL_0491: Expected O, but got Unknown
			//IL_04aa: Unknown result type (might be due to invalid IL or missing references)
			//IL_04af: Unknown result type (might be due to invalid IL or missing references)
			//IL_04bb: Unknown result type (might be due to invalid IL or missing references)
			//IL_04c3: Expected O, but got Unknown
			//IL_04c3: Unknown result type (might be due to invalid IL or missing references)
			//IL_04d3: Expected O, but got Unknown
			//IL_04ec: Unknown result type (might be due to invalid IL or missing references)
			//IL_04f1: Unknown result type (might be due to invalid IL or missing references)
			//IL_04fd: Unknown result type (might be due to invalid IL or missing references)
			//IL_0505: Expected O, but got Unknown
			//IL_0505: Unknown result type (might be due to invalid IL or missing references)
			//IL_0515: Expected O, but got Unknown
			if (ConfigSyncBase._config != null)
			{
				ConfigSyncBase.SyncedConfig("Server Settings", "Use Vanilla Sleep Start", value: false, new ConfigDescription("Default is false/disabled; Set to True/Enabled to resume Vanilla Sleep Start", (AcceptableValueBase)null, new object[1] { (object)new ConfigurationManagerAttributes
				{
					Order = 1,
					IsAdminOnly = true
				} }), ref UseVanilleSleep);
				ConfigSyncBase.SyncedConfig("Server Settings", "Sleep Start", 0.5f, new ConfigDescription("Day Fraction to allow sleep to begin. Default is 0.5, or Noon. Only applies when Vanilla Sleep Start is disabled/false.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 0.99f), new object[1] { (object)new ConfigurationManagerAttributes
				{
					Order = 2,
					IsAdminOnly = true
				} }), ref SleepStart);
				ConfigSyncBase.SyncedConfig("Server Settings", "Bonus Multiplier", 0.6f, new ConfigDescription("Scales the bonus increment (added on top of normal time): extra rate = this × sleep fraction × 10. At 1.0 and all-but-one in bed, extra rate is 10 (time advances 11× vs vanilla dt alone).", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1f), new object[1] { (object)new ConfigurationManagerAttributes
				{
					Order = 3,
					IsAdminOnly = true
				} }), ref BonusMultiplier);
				ConfigSyncBase.SyncedConfig("Server Settings", "Bonus Increment Scale", 20f, new ConfigDescription("Scales the bonus increment (added on top of normal time): extra rate = this × sleep fraction × 10. At 1.0 and all-but-one in bed, extra rate is 10 (time advances 11× vs vanilla dt alone).", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 30f), new object[1] { (object)new ConfigurationManagerAttributes
				{
					Order = 4,
					IsAdminOnly = true
				} }), ref BonusIncrementScale);
				ConfigSyncBase.SyncedConfig("Server Settings", "Boost Fade (Real Seconds)", 3f, new ConfigDescription("Partial boost linearly ramps to zero over this many real-time seconds before the next morning. Uses net rate (1 + extra) so higher boost = longer game-time taper. 0 = no taper (hard cut only at morning).", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 30f), new object[1] { (object)new ConfigurationManagerAttributes
				{
					Order = 5,
					IsAdminOnly = true
				} }), ref BoostFadeRealSecondsBeforeMorning);
				ConfigSyncBase.SyncedConfig("Testing Mode", "Enable Testing Mode", value: false, new ConfigDescription("When enabled, Fake Total Players and Simulate Players In Bed are added on top of real player counts for boost math and HUD (server + RPC).", (AcceptableValueBase)null, new object[1] { (object)new ConfigurationManagerAttributes
				{
					Order = 4,
					IsAdminOnly = true
				} }), ref TestingMode);
				ConfigSyncBase.SyncedConfig("Testing Mode", "Fake Total Players", 10, new ConfigDescription("Count of fake connected players to add to the server while Testing Mode is on.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 80), new object[1] { (object)new ConfigurationManagerAttributes
				{
					Order = 5,
					IsAdminOnly = true
				} }), ref TestingMaxPlayers);
				ConfigSyncBase.SyncedConfig("Testing Mode", "Simulate Players In Bed", 1, new ConfigDescription("Count of fake players in bed to add while Testing Mode is on (clamped to Fake Total Players).", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 80), new object[1] { (object)new ConfigurationManagerAttributes
				{
					Order = 6,
					IsAdminOnly = true
				} }), ref TestingSleepingPlayers);
				ConfigSyncBase.SyncedConfig("Station Timers", "Protect Cooking Timers", value: true, new ConfigDescription("If enabled, food on cooking stations and in ovens will not cook or burn faster during partial sleep.", (AcceptableValueBase)null, new object[1] { (object)new ConfigurationManagerAttributes
				{
					Order = 1,
					IsAdminOnly = true
				} }), ref ProtectCookingTimers);
				ConfigSyncBase.SyncedConfig("Station Timers", "Protect Smelter Timers", value: true, new ConfigDescription("If enabled, smelters, blast furnaces, and kilns process at normal speed during partial sleep.", (AcceptableValueBase)null, new object[1] { (object)new ConfigurationManagerAttributes
				{
					Order = 2,
					IsAdminOnly = true
				} }), ref ProtectSmelterTimers);
				ConfigSyncBase.SyncedConfig("Station Timers", "Protect Crop Timers", value: true, new ConfigDescription("If enabled, crops and planted saplings grow at normal speed during partial sleep.", (AcceptableValueBase)null, new object[1] { (object)new ConfigurationManagerAttributes
				{
					Order = 3,
					IsAdminOnly = true
				} }), ref ProtectCropTimers);
				ConfigSyncBase.SyncedConfig("Station Timers", "Protect Mead Timers", value: true, new ConfigDescription("If enabled, fermenters and mead barrels ferment at normal speed during partial sleep.", (AcceptableValueBase)null, new object[1] { (object)new ConfigurationManagerAttributes
				{
					Order = 4,
					IsAdminOnly = true
				} }), ref ProtectMeadTimers);
				ConfigSyncBase.SyncedConfig("Station Timers", "Protect Pickable Timers", value: true, new ConfigDescription("If enabled, berry bushes and wild pickables respawn at normal speed during partial sleep.", (AcceptableValueBase)null, new object[1] { (object)new ConfigurationManagerAttributes
				{
					Order = 5,
					IsAdminOnly = true
				} }), ref ProtectPickableTimers);
				ConfigSyncBase.SyncedConfig("Ocean & Boat Physics", "Decouple Water Wave Speed", value: true, new ConfigDescription("If enabled, ocean wave simulation moves at normal real-time speed while time is accelerated, preventing violent wave physics.", (AcceptableValueBase)null, new object[1] { (object)new ConfigurationManagerAttributes
				{
					Order = 1,
					IsAdminOnly = true
				} }), ref DecoupleWaterWaveSpeed);
				ConfigSyncBase.SyncedConfig("Ocean & Boat Physics", "Calm Ocean During Sleep", value: true, new ConfigDescription("If enabled, ocean waves are calmed and smoothed while night is accelerated.", (AcceptableValueBase)null, new object[1] { (object)new ConfigurationManagerAttributes
				{
					Order = 2,
					IsAdminOnly = true
				} }), ref CalmOceanDuringSleep);
				ConfigSyncBase.SyncedConfig("Ocean & Boat Physics", "Ocean Calm Multiplier", 0.5f, new ConfigDescription("Wave height multiplier applied when ocean calming is active (0.0 = completely flat, 1.0 = normal storm waves).", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1f), new object[1] { (object)new ConfigurationManagerAttributes
				{
					Order = 3,
					IsAdminOnly = true
				} }), ref OceanCalmMultiplier);
				ConfigSyncBase.SyncedConfig("Ocean & Boat Physics", "Prevent Boat Sleep Impact Damage", value: true, new ConfigDescription("Prevents boats from taking spurious water impact damage from waves during accelerated sleep.", (AcceptableValueBase)null, new object[1] { (object)new ConfigurationManagerAttributes
				{
					Order = 4,
					IsAdminOnly = true
				} }), ref PreventBoatSleepImpactDamage);
				ConfigSyncBase.SyncedConfig("Ocean & Boat Physics", "Suppress Boat Impact Screen Shake", value: true, new ConfigDescription("Prevents camera screen shake caused by high-velocity wave wakes during accelerated sleep.", (AcceptableValueBase)null, new object[1] { (object)new ConfigurationManagerAttributes
				{
					Order = 5,
					IsAdminOnly = true
				} }), ref SuppressBoatImpactScreenShake);
			}
		}

		public static int GetEffectiveTotalPlayersForMod(int realTotalPlayers)
		{
			int num = Math.Max(0, realTotalPlayers);
			if (TestingMode != null && TestingMode.Value && TestingMaxPlayers != null)
			{
				num += Math.Max(0, TestingMaxPlayers.Value);
			}
			return num;
		}

		public static int GetEffectiveSleepingPlayersForMod(int realSleepingCount, int effectivePlayerCount)
		{
			int num = Math.Max(0, realSleepingCount);
			if (TestingMode != null && TestingMode.Value && TestingSleepingPlayers != null)
			{
				int max = ((TestingMaxPlayers != null) ? Math.Max(0, TestingMaxPlayers.Value) : 0);
				int num2 = ClampInt(TestingSleepingPlayers.Value, 0, max);
				num += num2;
			}
			return ClampInt(num, 0, effectivePlayerCount);
		}

		private static int ClampInt(int value, int min, int max)
		{
			if (value < min)
			{
				return min;
			}
			if (value <= max)
			{
				return value;
			}
			return max;
		}
	}
	public class Waiting
	{
		public event EventHandler StatusChanged;

		public void ConfigurationComplete(bool configDone)
		{
			if (configDone)
			{
				this.StatusChanged?.Invoke(this, EventArgs.Empty);
			}
		}
	}
}
namespace BetterSleepBruh.Components
{
	public sealed class SleepHudView : MonoBehaviour
	{
		private const int MaxPillowSegments = 5;

		private RectTransform _segmentsRoot;

		private Image[] _segments = Array.Empty<Image>();

		private TextMeshProUGUI _boostTmp;

		private TextMeshProUGUI _ratioTmp;

		private TMP_FontAsset _hudFont;

		private int _lastTotal = -1;

		private int _lastRefreshedTotal = -1;

		private int _lastRefreshedSleeping = -1;

		private bool _compactLayout;

		private GameObject _bedIconGo;

		private GameObject _arrowChaserGo;

		private Image[] _arrowImages;

		private bool _isBoosting;

		private float _boostFraction;

		private float _arrowTimer;

		private const float ArrowMinStepDuration = 0.08f;

		private const float ArrowMaxStepDuration = 0.35f;

		private static readonly Color BgMidnight = new Color(0f, 0f, 0f, 0.39f);

		private static readonly Color PillowAwakeTint = new Color(0.32f, 0.32f, 0.34f, 1f);

		private static readonly Color ArrowDimTint = new Color(0.35f, 0.28f, 0.2f, 0.45f);

		private static readonly Color32 MoonBeige = new Color32((byte)235, (byte)225, (byte)190, byte.MaxValue);

		private static readonly Color32 BoostYellow = new Color32(byte.MaxValue, (byte)183, (byte)91, byte.MaxValue);

		private const float StripHeightPx = 40f;

		private bool _rpcsRegistered;

		private static readonly string[] HudFontResourcePaths = new string[2] { "Fonts & Materials/LiberationSans SDF", "Fonts & Materials/LiberationSans SDF TMP" };

		private static Sprite _whiteSprite;

		private static Sprite _moonCrescentSprite;

		private static Sprite _bedFilledSprite;

		private static Sprite _resolvedMoonIcon;

		private static Sprite _resolvedBedIcon;

		private static Sprite _resolvedPillowSprite;

		private const string EmbeddedMoonName = "sleephud_moon.png";

		private const string EmbeddedBedName = "sleephud_bed.png";

		private const string EmbeddedPillowName = "sleephud_pillow.png";

		private static Sprite _chevronSprite;

		private void Awake()
		{
			BetterSleepBruh.Log.Debug("SleepHudView Is Awoken");
			RegisterRpcs();
		}

		private void Start()
		{
			BetterSleepBruh.Log.Debug("[CLIENT] SleepHudView Is Starting");
			RegisterRpcs();
			RequestOrSyncInitialState();
		}

		private void RegisterRpcs()
		{
			if (!_rpcsRegistered && ZRoutedRpc.instance != null)
			{
				BetterSleepBruh.Log.Debug("[CLIENT] Registering SleepHudView RPCs");
				ZRoutedRpc.instance.Register<int, int, double>("RPC_SleepingPlayerInfo", (Action<long, int, int, double>)RPC_SleepingPlayerInfo);
				ZRoutedRpc.instance.Register("RPC_StartSleep", (Action<long>)RPC_StartSleep);
				ZRoutedRpc.instance.Register("RPC_StopSleep", (Action<long>)RPC_StopSleep);
				ZRoutedRpc.instance.Register<double>("BSB_SyncSleepBoostTotal", (Action<long, double>)RPC_SyncSleepBoostTotal);
				_rpcsRegistered = true;
			}
		}

		private void OnEnable()
		{
			RequestOrSyncInitialState();
		}

		private void OnDisable()
		{
			_isBoosting = false;
			_arrowTimer = 0f;
		}

		private void Update()
		{
			//IL_0060: 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_006c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0086: Unknown result type (might be due to invalid IL or missing references)
			//IL_008d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0092: Unknown result type (might be due to invalid IL or missing references)
			//IL_00af: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a8: Unknown result type (might be due to invalid IL or missing references)
			if (_isBoosting && _arrowImages != null && _arrowImages.Length >= 3)
			{
				float num = Mathf.Lerp(0.35f, 0.08f, _boostFraction);
				_arrowTimer += Time.deltaTime;
				int num2 = (int)(_arrowTimer / num) % 4;
				((Graphic)_arrowImages[0]).color = ((num2 >= 0 && num2 <= 2) ? Color32.op_Implicit(BoostYellow) : ArrowDimTint);
				((Graphic)_arrowImages[1]).color = ((num2 >= 1 && num2 <= 2) ? Color32.op_Implicit(BoostYellow) : ArrowDimTint);
				((Graphic)_arrowImages[2]).color = ((num2 == 2) ? Color32.op_Implicit(BoostYellow) : ArrowDimTint);
			}
		}

		private void RequestOrSyncInitialState()
		{
			if ((Object)(object)SleepTracker.Instance != (Object)null)
			{
				if (SleepTracker.Instance.CanSleep)
				{
					((Component)this).gameObject.SetActive(true);
					Refresh(SleepTracker.CurrentPlayerCount, SleepTracker.CurrentSleepingCount);
				}
				else
				{
					((Component)this).gameObject.SetActive(false);
				}
			}
			else if (ZRoutedRpc.instance != null)
			{
				ZRoutedRpc.instance.InvokeRoutedRPC(ZRoutedRpc.instance.GetServerPeerID(), "RPC_RequestSleepingPlayerInfo", Array.Empty<object>());
			}
		}

		private void RPC_SyncSleepBoostTotal(long sender, double totalBoost)
		{
			SleepTracker.TotalPartialSleepBoostSeconds = totalBoost;
		}

		private void RPC_SleepingPlayerInfo(long sender, int totalPlayers, int playersSleeping, double sleepBoost)
		{
			SleepTracker.CurrentExtraRate = sleepBoost;
			if (!((Object)(object)Player.m_localPlayer == (Object)null))
			{
				if (ConfigRegistry.IsPlayerCountTestingActive)
				{
					BetterSleepBruh.Log.Debug($"[BetterSleepBruh TESTING] HUD total={totalPlayers} sleeping={playersSleeping} extraRate={sleepBoost}");
				}
				else
				{
					BetterSleepBruh.Log.Debug($"[CLIENT] Total Players: {totalPlayers}");
					BetterSleepBruh.Log.Debug($"[CLIENT] Players Sleeping: {playersSleeping}");
					BetterSleepBruh.Log.Debug($"[CLIENT] Sleep Boost (extra rate × dt): {sleepBoost}");
				}
				if (!((Component)this).gameObject.activeSelf && ((Object)(object)EnvMan.instance == (Object)null || EnvManPatches.IsInSleepWindow(EnvMan.instance)))
				{
					((Component)this).gameObject.SetActive(true);
				}
				Refresh(totalPlayers, playersSleeping);
			}
		}

		private void RPC_StartSleep(long sender)
		{
			if (!((Object)(object)Player.m_localPlayer == (Object)null))
			{
				BetterSleepBruh.Log.Debug("[CLIENT] Start Sleep");
				((Component)this).gameObject.SetActive(true);
			}
		}

		private void RPC_StopSleep(long sender)
		{
			SleepTracker.CurrentExtraRate = 0.0;
			if ((Object)(object)Player.m_localPlayer == (Object)null)
			{
				return;
			}
			BetterSleepBruh.Log.Debug("[CLIENT] Stop Sleep");
			_isBoosting = false;
			if ((Object)(object)_arrowChaserGo != (Object)null && _arrowChaserGo.activeSelf)
			{
				_arrowChaserGo.SetActive(false);
			}
			if ((Object)(object)_bedIconGo != (Object)null && !_bedIconGo.activeSelf)
			{
				_bedIconGo.SetActive(true);
			}
			if ((Object)(object)EnvMan.instance == (Object)null || !EnvMan.instance.IsTimeSkipping())
			{
				Player localPlayer = Player.m_localPlayer;
				if ((Object)(object)localPlayer != (Object)null)
				{
					localPlayer.SetSleeping(false);
					if (((Character)localPlayer).InBed())
					{
						((Character)localPlayer).AttachStop();
					}
					localPlayer.m_wakeupTime = (((Object)(object)ZNet.instance != (Object)null) ? ZNet.instance.GetTimeSeconds() : 0.0);
				}
			}
			((Component)this).gameObject.SetActive(false);
		}

		public static SleepHudView TryCreate(Transform mapGeometryTransform, float gapBelowMinimap = 1f)
		{
			//IL_007b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0082: Expected O, but got Unknown
			//IL_0098: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ad: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f9: 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)
			if ((Object)(object)mapGeometryTransform == (Object)null)
			{
				return null;
			}
			RectTransform val = (RectTransform)(object)((mapGeometryTransform is RectTransform) ? mapGeometryTransform : null);
			if ((Object)(object)val == (Object)null)
			{
				return null;
			}
			Transform val2 = ((Transform)val).Find("BetterSleepBruh_SleepHud");
			if ((Object)(object)val2 != (Object)null)
			{
				Object.Destroy((Object)(object)((Component)val2).gameObject);
			}
			Sprite sprite = BaseWhiteSprite();
			float num = 40f;
			GameObject val3 = new GameObject("BetterSleepBruh_SleepHud", new Type[3]
			{
				typeof(RectTransform),
				typeof(Image),
				typeof(SleepHudView)
			});
			RectTransform component = val3.GetComponent<RectTransform>();
			((Transform)component).SetParent((Transform)(object)val, false);
			((Transform)component).SetAsLastSibling();
			((Transform)component).localScale = Vector3.one;
			component.anchorMin = new Vector2(0f, 0f);
			component.anchorMax = new Vector2(1f, 0f);
			component.pivot = new Vector2(0.5f, 1f);
			component.sizeDelta = new Vector2(0f, num);
			component.anchoredPosition = new Vector2(0f, 0f - gapBelowMinimap);
			Image component2 = val3.GetComponent<Image>();
			component2.sprite = sprite;
			component2.type = (Type)0;
			((Graphic)component2).color = BgMidnight;
			((Graphic)component2).raycastTarget = false;
			val3.AddComponent<RectMask2D>();
			TMP_FontAsset val4 = ResolveTmpFont((Transform)(object)val);
			if ((Object)(object)val4 == (Object)null)
			{
				BetterSleepBruh.Log.Warning("[SleepHud] No TMP font; not creating sleep HUD.");
				Object.Destroy((Object)(object)val3);
				return null;
			}
			SleepHudView component3 = val3.GetComponent<SleepHudView>();
			component3.BuildContent(val3.GetComponent<RectTransform>(), val4);
			return component3;
		}

		public void Refresh(int totalPlayers, int playersSleeping)
		{
			//IL_004f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d1: 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)
			if ((Object)(object)_segmentsRoot == (Object)null)
			{
				return;
			}
			totalPlayers = Mathf.Max(0, totalPlayers);
			playersSleeping = Mathf.Clamp(playersSleeping, 0, totalPlayers);
			EnsureSegments(totalPlayers);
			if (_compactLayout)
			{
				if (_segments.Length == 1)
				{
					((Graphic)_segments[0]).color = ((playersSleeping > 0) ? Color.white : PillowAwakeTint);
				}
				if ((Object)(object)_ratioTmp != (Object)null)
				{
					string text = $"{playersSleeping}/{totalPlayers}";
					if (((TMP_Text)_ratioTmp).text != text)
					{
						((TMP_Text)_ratioTmp).text = text;
					}
				}
			}
			else if (totalPlayers != _lastRefreshedTotal || playersSleeping != _lastRefreshedSleeping)
			{
				for (int i = 0; i < _segments.Length; i++)
				{
					((Graphic)_segments[i]).color = ((i < playersSleeping) ? Color.white : PillowAwakeTint);
				}
			}
			_lastRefreshedTotal = totalPlayers;
			_lastRefreshedSleeping = playersSleeping;
			double bonusLabelPercent = GetBonusLabelPercent(totalPlayers, playersSleeping);
			double num = ((ConfigRegistry.BonusMultiplier != null) ? ((double)ConfigRegistry.BonusMultiplier.Value * 100.0) : 60.0);
			bool flag = (_isBoosting = totalPlayers > 1 && playersSleeping > 0 && playersSleeping < totalPlayers && bonusLabelPercent > 0.0001);
			_boostFraction = ((flag && num > 0.0) ? Mathf.Clamp01((float)(bonusLabelPercent / num)) : 0f);
			if ((Object)(object)_bedIconGo != (Object)null && (Object)(object)_arrowChaserGo != (Object)null)
			{
				if (flag)
				{
					if (!_arrowChaserGo.activeSelf)
					{
						_arrowChaserGo.SetActive(true);
					}
					if (_bedIconGo.activeSelf)
					{
						_bedIconGo.SetActive(false);
					}
				}
				else
				{
					if (_arrowChaserGo.activeSelf)
					{
						_arrowChaserGo.SetActive(false);
					}
					if (!_bedIconGo.activeSelf)
					{
						_bedIconGo.SetActive(true);
					}
				}
			}
			if (!((Object)(object)_boostTmp == (Object)null))
			{
				string text2 = ((bonusLabelPercent <= 0.0001) ? "+0%" : $"+{bonusLabelPercent:F0}%");
				if (((TMP_Text)_boostTmp).text != text2)
				{
					((TMP_Text)_boostTmp).text = text2;
				}
			}
		}

		private static double GetBonusLabelPercent(int playerCount, int playersSleeping)
		{
			if (playerCount <= 1 || playersSleeping <= 0)
			{
				return 0.0;
			}
			double num = (double)ConfigRegistry.BonusMultiplier.Value * 100.0;
			if (playersSleeping >= playerCount - 1)
			{
				return num;
			}
			return (double)playersSleeping / (double)playerCount * num;
		}

		private void BuildContent(RectTransform rootRt, TMP_FontAsset font)
		{
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_0037: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: Expected O, but got Unknown
			//IL_0055: Unknown result type (might be due to invalid IL or missing references)
			//IL_005f: Expected O, but got Unknown
			//IL_009c: Unknown result type (might be due to invalid IL or missing references)
			//IL_00df: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e4: 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_00f0: Expected O, but got Unknown
			//IL_00f8: Unknown result type (might be due to invalid IL or missing references)
			//IL_0125: 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)
			//IL_014b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0155: Expected O, but got Unknown
			//IL_01b5: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ba: Unknown result type (might be due to invalid IL or missing references)
			_hudFont = font;
			GameObject val = new GameObject("Row", new Type[2]
			{
				typeof(RectTransform),
				typeof(HorizontalLayoutGroup)
			});
			RectTransform val2 = (RectTransform)val.transform;
			((Transform)val2).SetParent((Transform)(object)rootRt, false);
			StretchFull(val2);
			HorizontalLayoutGroup component = val.GetComponent<HorizontalLayoutGroup>();
			((LayoutGroup)component).padding = new RectOffset(4, 4, 3, 3);
			((HorizontalOrVerticalLayoutGroup)component).spacing = 4f;
			((LayoutGroup)component).childAlignment = (TextAnchor)3;
			((HorizontalOrVerticalLayoutGroup)component).childControlWidth = true;
			((HorizontalOrVerticalLayoutGroup)component).childControlHeight = true;
			((HorizontalOrVerticalLayoutGroup)component).childForceExpandWidth = false;
			((HorizontalOrVerticalLayoutGroup)component).childForceExpandHeight = true;
			CreateIconInRow((Transform)(object)val2, "Moon", GetMoonIconSprite(), 28f, Color.white);
			CreateBedSlot((Transform)(object)val2);
			GameObject val3 = new GameObject("BarHost", new Type[3]
			{
				typeof(RectTransform),
				typeof(HorizontalLayoutGroup),
				typeof(Image)
			});
			RectTransform val4 = (RectTransform)val3.transform;
			((Transform)val4).SetParent((Transform)(object)val2, false);
			Image component2 = val3.GetComponent<Image>();
			component2.sprite = BaseWhiteSprite();
			component2.type = (Type)0;
			((Graphic)component2).color = new Color(0f, 0f, 0f, 0.25f);
			((Graphic)component2).raycastTarget = false;
			HorizontalLayoutGroup component3 = val3.GetComponent<HorizontalLayoutGroup>();
			((HorizontalOrVerticalLayoutGroup)component3).spacing = 3f;
			((LayoutGroup)component3).padding = new RectOffset(4, 4, 4, 4);
			((LayoutGroup)component3).childAlignment = (TextAnchor)4;
			((HorizontalOrVerticalLayoutGroup)component3).childControlWidth = true;
			((HorizontalOrVerticalLayoutGroup)component3).childControlHeight = true;
			((HorizontalOrVerticalLayoutGroup)component3).childForceExpandWidth = true;
			((HorizontalOrVerticalLayoutGroup)component3).childForceExpandHeight = true;
			LayoutElement obj = val3.AddComponent<LayoutElement>();
			obj.flexibleWidth = 1f;
			obj.minWidth = 48f;
			obj.preferredHeight = 26f;
			_segmentsRoot = val4;
			_boostTmp = CreateTmpInRow((Transform)(object)val2, "Boost", font, 40f, 14f, Color32.op_Implicit(BoostYellow), "0%", (TextAlignmentOptions)4100);
			SleepTracker.GetSleepOccupancyCounts(out var playerCount, out var playersSleeping);
			if (playerCount <= 0)
			{
				playerCount = 1;
			}
			Refresh(playerCount, playersSleeping);
		}

		private void EnsureSegments(int total)
		{
			//IL_00cc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d3: Expected O, but got Unknown
			//IL_0148: Unknown result type (might be due to invalid IL or missing references)
			//IL_014d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0153: Unknown result type (might be due to invalid IL or missing references)
			//IL_0158: Unknown result type (might be due to invalid IL or missing references)
			//IL_016b: Expected O, but got Unknown
			//IL_018c: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d4: Unknown result type (might be due to invalid IL or missing references)
			//IL_01db: Expected O, but got Unknown
			//IL_0256: Unknown result type (might be due to invalid IL or missing references)
			//IL_025d: Expected O, but got Unknown
			//IL_0264: Unknown result type (might be due to invalid IL or missing references)
			//IL_0269: Unknown result type (might be due to invalid IL or missing references)
			//IL_027c: Expected O, but got Unknown
			//IL_02b0: Unknown result type (might be due to invalid IL or missing references)
			//IL_02b5: Unknown result type (might be due to invalid IL or missing references)
			//IL_0309: Unknown result type (might be due to invalid IL or missing references)
			//IL_0366: Unknown result type (might be due to invalid IL or missing references)
			//IL_036b: Unknown result type (might be due to invalid IL or missing references)
			//IL_037d: Unknown result type (might be due to invalid IL or missing references)
			//IL_039f: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)_segmentsRoot == (Object)null)
			{
				return;
			}
			bool flag = total > 5;
			int num = (flag ? 1 : total);
			if (total == _lastTotal && _compactLayout == flag && _segments.Length == num)
			{
				return;
			}
			_lastTotal = total;
			_compactLayout = flag;
			_ratioTmp = null;
			for (int num2 = ((Transform)_segmentsRoot).childCount - 1; num2 >= 0; num2--)
			{
				Transform child = ((Transform)_segmentsRoot).GetChild(num2);
				if ((Object)(object)child != (Object)null)
				{
					Object.Destroy((Object)(object)((Component)child).gameObject);
				}
			}
			if (total <= 0)
			{
				_segments = Array.Empty<Image>();
				return;
			}
			Sprite pillowSegmentSprite = GetPillowSegmentSprite();
			if (flag)
			{
				GameObject val = new GameObject("PillowCompact", new Type[2]
				{
					typeof(RectTransform),
					typeof(LayoutElement)
				});
				val.transform.SetParent((Transform)(object)_segmentsRoot, false);
				LayoutElement component = val.GetComponent<LayoutElement>();
				component.flexibleWidth = 0f;
				component.minWidth = 28f;
				component.preferredWidth = 40f;
				component.preferredHeight = 22f;
				component.flexibleHeight = 1f;
				GameObject val2 = new GameObject("Seg_0", new Type[2]
				{
					typeof(RectTransform),
					typeof(Image)
				});
				RectTransform val3 = (RectTransform)val2.transform;
				((Transform)val3).SetParent(val.transform, false);
				StretchFull(val3);
				Image component2 = val2.GetComponent<Image>();
				component2.sprite = pillowSegmentSprite;
				component2.type = (Type)0;
				component2.preserveAspect = true;
				((Graphic)component2).color = PillowAwakeTint;
				((Graphic)component2).raycastTarget = false;
				_segments = (Image[])(object)new Image[1] { component2 };
				GameObject val4 = new GameObject("Ratio", new Type[2]
				{
					typeof(RectTransform),
					typeof(LayoutElement)
				});
				val4.transform.SetParent((Transform)(object)_segmentsRoot, false);
				LayoutElement component3 = val4.GetComponent<LayoutElement>();
				component3.flexibleWidth = 1f;
				component3.minWidth = 52f;
				component3.preferredHeight = 22f;
				component3.flexibleHeight = 1f;
				if ((Object)(object)_hudFont != (Object)null)
				{
					GameObject val5 = new GameObject("Label", new Type[2]
					{
						typeof(RectTransform),
						typeof(TextMeshProUGUI)
					});
					RectTransform val6 = (RectTransform)val5.transform;
					((Transform)val6).SetParent(val4.transform, false);
					StretchFull(val6);
					_ratioTmp = val5.GetComponent<TextMeshProUGUI>();
					ApplyFont(_ratioTmp, _hudFont);
					((TMP_Text)_ratioTmp).fontSize = 14f;
					((Graphic)_ratioTmp).color = Color32.op_Implicit(BoostYellow);
					((TMP_Text)_ratioTmp).text = "0/0";
					((TMP_Text)_ratioTmp).alignment = (TextAlignmentOptions)4097;
					((TMP_Text)_ratioTmp).textWrappingMode = (TextWrappingModes)0;
					((TMP_Text)_ratioTmp).overflowMode = (TextOverflowModes)0;
					((Graphic)_ratioTmp).raycastTarget = false;
					((TMP_Text)_ratioTmp).margin = Vector4.zero;
				}
			}
			else
			{
				_segments = (Image[])(object)new Image[total];
				for (int i = 0; i < total; i++)
				{
					GameObject val7 = new GameObject($"Seg_{i}", new Type[3]
					{
						typeof(RectTransform),
						typeof(Image),
						typeof(LayoutElement)
					});
					val7.transform.SetParent((Transform)(object)_segmentsRoot, false);
					Image component4 = val7.GetComponent<Image>();
					component4.sprite = pillowSegmentSprite;
					component4.type = (Type)0;
					component4.preserveAspect = true;
					((Graphic)component4).color = PillowAwakeTint;
					((Graphic)component4).raycastTarget = false;
					LayoutElement component5 = val7.GetComponent<LayoutElement>();
					component5.flexibleWidth = 1f;
					component5.preferredHeight = 22f;
					component5.minWidth = 8f;
					_segments[i] = component4;
				}
			}
		}

		private static void StretchFull(RectTransform rt)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: 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)
			rt.anchorMin = Vector2.zero;
			rt.anchorMax = Vector2.one;
			rt.offsetMin = Vector2.zero;
			rt.offsetMax = Vector2.zero;
		}

		private void CreateBedSlot(Transform rowParent)
		{
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_002f: Expected O, but got Unknown
			//IL_00a2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ac: Expected O, but got Unknown
			//IL_00b7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c9: Expected O, but got Unknown
			//IL_00e7: Unknown result type (might be due to invalid IL or missing references)
			//IL_0124: Unknown result type (might be due to invalid IL or missing references)
			//IL_012e: Expected O, but got Unknown
			//IL_0139: Unknown result type (might be due to invalid IL or missing references)
			//IL_013f: Expected O, but got Unknown
			//IL_015d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0167: Expected O, but got Unknown
			//IL_01df: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e4: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ea: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ef: Unknown result type (might be due to invalid IL or missing references)
			//IL_0201: Unknown result type (might be due to invalid IL or missing references)
			//IL_0224: Unknown result type (might be due to invalid IL or missing references)
			float num = 28f;
			GameObject val = new GameObject("BedSlot", new Type[1] { typeof(RectTransform) });
			RectTransform val2 = (RectTransform)val.transform;
			((Transform)val2).SetParent(rowParent, false);
			ConfigureRowItemStretch(val2, num);
			LayoutElement obj = val.AddComponent<LayoutElement>();
			obj.preferredWidth = num;
			obj.minWidth = num;
			obj.flexibleWidth = 0f;
			obj.minHeight = -1f;
			obj.preferredHeight = -1f;
			obj.flexibleHeight = 1f;
			_bedIconGo = new GameObject("BedIcon", new Type[2]
			{
				typeof(RectTransform),
				typeof(Image)
			});
			RectTransform val3 = (RectTransform)_bedIconGo.transform;
			((Transform)val3).SetParent((Transform)(object)val2, false);
			StretchFull(val3);
			Image component = _bedIconGo.GetComponent<Image>();
			component.sprite = GetBedIconSprite();
			component.type = (Type)0;
			((Graphic)component).color = Color.white;
			component.preserveAspect = true;
			((Graphic)component).raycastTarget = false;
			_arrowChaserGo = new GameObject("ArrowChaser", new Type[2]
			{
				typeof(RectTransform),
				typeof(HorizontalLayoutGroup)
			});
			RectTransform val4 = (RectTransform)_arrowChaserGo.transform;
			((Transform)val4).SetParent((Transform)(object)val2, false);
			StretchFull(val4);
			HorizontalLayoutGroup component2 = _arrowChaserGo.GetComponent<HorizontalLayoutGroup>();
			((LayoutGroup)component2).padding = new RectOffset(0, 0, 0, 0);
			((HorizontalOrVerticalLayoutGroup)component2).spacing = 1f;
			((LayoutGroup)component2).childAlignment = (TextAnchor)4;
			((HorizontalOrVerticalLayoutGroup)component2).childControlWidth = false;
			((HorizontalOrVerticalLayoutGroup)component2).childControlHeight = false;
			((HorizontalOrVerticalLayoutGroup)component2).childForceExpandWidth = false;
			((HorizontalOrVerticalLayoutGroup)component2).childForceExpandHeight = false;
			Sprite chevronSprite = GetChevronSprite();
			_arrowImages = (Image[])(object)new Image[3];
			for (int i = 0; i < 3; i++)
			{
				GameObject val5 = new GameObject($"Arrow_{i}", new Type[2]
				{
					typeof(RectTransform),
					typeof(Image)
				});
				RectTransform val6 = (RectTransform)val5.transform;
				((Transform)val6).SetParent((Transform)(object)val4, false);
				val6.sizeDelta = new Vector2(8f, 14f);
				Image component3 = val5.GetComponent<Image>();
				component3.sprite = chevronSprite;
				component3.type = (Type)0;
				((Graphic)component3).color = ArrowDimTint;
				component3.preserveAspect = true;
				((Graphic)component3).raycastTarget = false;
				_arrowImages[i] = component3;
			}
			_arrowChaserGo.SetActive(false);
			_bedIconGo.SetActive(true);
		}

		private static void CreateIconInRow(Transform rowParent, string name, Sprite sprite, float cellWidth, Color tint)
		{
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: 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_0025: Expected O, but got Unknown
			//IL_0097: Unknown result type (might be due to invalid IL or missing references)
			//IL_009c: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a2: 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_00b4: Expected O, but got Unknown
			//IL_00c8: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = new GameObject(name, new Type[1] { typeof(RectTransform) });
			RectTransform val2 = (RectTransform)val.transform;
			((Transform)val2).SetParent(rowParent, false);
			ConfigureRowItemStretch(val2, cellWidth);
			LayoutElement obj = val.AddComponent<LayoutElement>();
			obj.preferredWidth = cellWidth;
			obj.minWidth = cellWidth;
			obj.flexibleWidth = 0f;
			obj.minHeight = -1f;
			obj.preferredHeight = -1f;
			obj.flexibleHeight = 1f;
			GameObject val3 = new GameObject("Icon", new Type[2]
			{
				typeof(RectTransform),
				typeof(Image)
			});
			RectTransform val4 = (RectTransform)val3.transform;
			((Transform)val4).SetParent((Transform)(object)val2, false);
			StretchFull(val4);
			Image component = val3.GetComponent<Image>();
			component.sprite = sprite;
			component.type = (Type)0;
			((Graphic)component).color = tint;
			component.preserveAspect = true;
			((Graphic)component).raycastTarget = false;
		}

		private static TextMeshProUGUI CreateTmpInRow(Transform rowParent, string name, TMP_FontAsset font, float cellWidth, float fontSize, Color color, string text, TextAlignmentOptions alignment)
		{
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: 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_0025: Expected O, but got Unknown
			//IL_0093: Unknown result type (might be due to invalid IL or missing references)
			//IL_0098: Unknown result type (might be due to invalid IL or missing references)
			//IL_009e: 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_00b0: Expected O, but got Unknown
			//IL_00c5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f2: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = new GameObject(name, new Type[1] { typeof(RectTransform) });
			RectTransform val2 = (RectTransform)val.transform;
			((Transform)val2).SetParent(rowParent, false);
			ConfigureRowItemStretch(val2, cellWidth);
			LayoutElement obj = val.AddComponent<LayoutElement>();
			obj.preferredWidth = cellWidth;
			obj.minWidth = cellWidth;
			obj.flexibleWidth = 0f;
			obj.minHeight = -1f;
			obj.preferredHeight = -1f;
			obj.flexibleHeight = 1f;
			GameObject val3 = new GameObject(name, new Type[2]
			{
				typeof(RectTransform),
				typeof(TextMeshProUGUI)
			});
			RectTransform val4 = (RectTransform)val3.transform;
			((Transform)val4).SetParent((Transform)(object)val2, false);
			StretchFull(val4);
			TextMeshProUGUI component = val3.GetComponent<TextMeshProUGUI>();
			ApplyFont(component, font);
			((TMP_Text)component).fontSize = fontSize;
			((Graphic)component).color = color;
			((TMP_Text)component).text = text;
			((TMP_Text)component).alignment = alignment;
			((TMP_Text)component).textWrappingMode = (TextWrappingModes)0;
			((TMP_Text)component).overflowMode = (TextOverflowModes)0;
			((Graphic)component).raycastTarget = false;
			((TMP_Text)component).margin = Vector4.zero;
			return component;
		}

		private static void ConfigureRowItemStretch(RectTransform rt, float width)
		{
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_0046: Unknown result type (might be due to invalid IL or missing references)
			//IL_0051: Unknown result type (might be due to invalid IL or missing references)
			rt.anchorMin = new Vector2(0f, 0f);
			rt.anchorMax = new Vector2(0f, 1f);
			rt.pivot = new Vector2(0f, 0.5f);
			rt.sizeDelta = new Vector2(width, 0f);
			rt.anchoredPosition = Vector2.zero;
		}

		private static void ApplyFont(TextMeshProUGUI tmp, TMP_FontAsset font)
		{
			((TMP_Text)tmp).font = font;
			if ((Object)(object)font != (Object)null && (Object)(object)((TMP_Asset)font).material != (Object)null)
			{
				((TMP_Text)tmp).fontSharedMaterial = ((TMP_Asset)font).material;
			}
		}

		private static TMP_FontAsset ResolveTmpFont(Transform nearUi)
		{
			if ((Object)(object)TMP_Settings.instance != (Object)null && (Object)(object)TMP_Settings.defaultFontAsset != (Object)null)
			{
				return TMP_Settings.defaultFontAsset;
			}
			TMP_FontAsset val = null;
			for (int i = 0; i < HudFontResourcePaths.Length; i++)
			{
				TMP_FontAsset val2 = Resources.Load<TMP_FontAsset>(HudFontResourcePaths[i]);
				if ((Object)(object)val2 != (Object)null)
				{
					val = val2;
					break;
				}
			}
			if ((Object)(object)val == (Object)null)
			{
				Transform val3 = nearUi;
				while ((Object)(object)val3.parent != (Object)null)
				{
					val3 = val3.parent;
				}
				TextMeshProUGUI[] componentsInChildren = ((Component)val3).GetComponentsInChildren<TextMeshProUGUI>(true);
				for (int j = 0; j < componentsInChildren.Length; j++)
				{
					TMP_FontAsset font = ((TMP_Text)componentsInChildren[j]).font;
					if ((Object)(object)font != (Object)null)
					{
						val = font;
						break;
					}
				}
			}
			if ((Object)(object)val == (Object)null)
			{
				TMP_FontAsset[] array = Resources.FindObjectsOfTypeAll<TMP_FontAsset>();
				for (int k = 0; k < array.Length; k++)
				{
					if ((Object)(object)array[k] != (Object)null && (Object)(object)((TMP_Asset)array[k]).material != (Object)null)
					{
						val = array[k];
						break;
					}
				}
			}
			if ((Object)(object)val != (Object)null && (Object)(object)TMP_Settings.defaultFontAsset == (Object)null)
			{
				try
				{
					TMP_Settings.defaultFontAsset = val;
				}
				catch
				{
				}
			}
			return val;
		}

		private static Sprite GetMoonIconSprite()
		{
			if ((Object)(object)_resolvedMoonIcon != (Object)null)
			{
				return _resolvedMoonIcon;
			}
			_resolvedMoonIcon = TryLoadEmbeddedPngSprite("sleephud_moon.png") ?? GetMoonCrescentSprite();
			return _resolvedMoonIcon;
		}

		private static Sprite GetBedIconSprite()
		{
			if ((Object)(object)_resolvedBedIcon != (Object)null)
			{
				return _resolvedBedIcon;
			}
			_resolvedBedIcon = TryLoadEmbeddedPngSprite("sleephud_bed.png") ?? GetBedFilledSprite();
			return _resolvedBedIcon;
		}

		private static Sprite GetPillowSegmentSprite()
		{
			if ((Object)(object)_resolvedPillowSprite != (Object)null)
			{
				return _resolvedPillowSprite;
			}
			_resolvedPillowSprite = TryLoadEmbeddedPngSprite("sleephud_pillow.png") ?? BaseWhiteSprite();
			return _resolvedPillowSprite;
		}

		private static bool TryLoadPngIntoTexture(Texture2D tex, byte[] bytes)
		{
			try
			{
				Type type = Type.GetType("UnityEngine.ImageConversion, UnityEngine.ImageConversionModule");
				if (type == null)
				{
					return false;
				}
				MethodInfo method = type.GetMethod("LoadImage", BindingFlags.Static | BindingFlags.Public, null, new Type[2]
				{
					typeof(Texture2D),
					typeof(byte[])
				}, null);
				if (method == null)
				{
					return false;
				}
				return (bool)method.Invoke(null, new object[2] { tex, bytes });
			}
			catch
			{
				return false;
			}
		}

		private static Sprite TryLoadEmbeddedPngSprite(string manifestEndsWith)
		{
			//IL_0081: Unknown result type (might be due to invalid IL or missing references)
			//IL_0088: Expected O, but got Unknown
			//IL_00dc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00eb: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				Assembly executingAssembly = Assembly.GetExecutingAssembly();
				string text = null;
				string[] manifestResourceNames = executingAssembly.GetManifestResourceNames();
				foreach (string text2 in manifestResourceNames)
				{
					if (text2.EndsWith(manifestEndsWith, StringComparison.OrdinalIgnoreCase))
					{
						text = text2;
						break;
					}
				}
				if (text == null)
				{
					return null;
				}
				using Stream stream = executingAssembly.GetManifestResourceStream(text);
				if (stream == null)
				{
					return null;
				}
				int num = (int)stream.Length;
				byte[] array = new byte[num];
				if (stream.Read(array, 0, num) != num)
				{
					return null;
				}
				Texture2D val = new Texture2D(2, 2, (TextureFormat)4, false);
				if (!TryLoadPngIntoTexture(val, array))
				{
					return null;
				}
				((Texture)val).filterMode = (FilterMode)1;
				((Texture)val).wrapMode = (TextureWrapMode)1;
				BetterSleepBruh.Log.Debug("[SleepHud] Using embedded HUD icon: " + text);
				return Sprite.Create(val, new Rect(0f, 0f, (float)((Texture)val).width, (float)((Texture)val).height), new Vector2(0.5f, 0.5f), 100f);
			}
			catch (Exception ex)
			{
				BetterSleepBruh.Log.Warning("[SleepHud] Could not load embedded " + manifestEndsWith + ": " + ex.Message);
				return null;
			}
		}

		private static Sprite GetMoonCrescentSprite()
		{
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: Expected O, but got Unknown
			//IL_00f1: 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_00a5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ad: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a8: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)_moonCrescentSprite != (Object)null)
			{
				return _moonCrescentSprite;
			}
			Texture2D val = new Texture2D(32, 32, (TextureFormat)4, false);
			Color32 val2 = default(Color32);
			((Color32)(ref val2))..ctor((byte)0, (byte)0, (byte)0, (byte)0);
			float num = 15.5f;
			float num2 = 15.5f;
			float num3 = 14.08f;
			float num4 = 11.52f;
			float num5 = num + 4.48f;
			for (int i = 0; i < 32; i++)
			{
				for (int j = 0; j < 32; j++)
				{
					float num6 = (float)j - num;
					float num7 = (float)i - num2;
					bool flag = num6 * num6 + num7 * num7 <= num3 * num3;
					float num8 = (float)j - num5;
					float num9 = (float)i - num2;
					bool flag2 = num8 * num8 + num9 * num9 <= num4 * num4;
					val.SetPixel(j, i, Color32.op_Implicit((flag && !flag2) ? MoonBeige : val2));
				}
			}
			val.Apply();
			((Texture)val).filterMode = (FilterMode)0;
			_moonCrescentSprite = Sprite.Create(val, new Rect(0f, 0f, 32f, 32f), new Vector2(0.5f, 0.5f), 100f);
			return _moonCrescentSprite;
		}

		private static Sprite GetBedFilledSprite()
		{
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: Expected O, but got Unknown
			//IL_009b: 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_00c2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e8: Unknown result type (might be due to invalid IL or missing references)
			//IL_0114: Unknown result type (might be due to invalid IL or missing references)
			//IL_0123: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)_bedFilledSprite != (Object)null)
			{
				return _bedFilledSprite;
			}
			Texture2D val = new Texture2D(36, 24, (TextureFormat)4, false);
			for (int i = 0; i < 24; i++)
			{
				for (int j = 0; j < 36; j++)
				{
					val.SetPixel(j, i, Color32.op_Implicit(new Color32((byte)0, (byte)0, (byte)0, (byte)0)));
				}
			}
			Color32 c = default(Color32);
			((Color32)(ref c))..ctor((byte)((float)(int)MoonBeige.r * 0.72f), (byte)((float)(int)MoonBeige.g * 0.72f), (byte)((float)(int)MoonBeige.b * 0.72f), byte.MaxValue);
			FillRect(val, 36, 24, 3, 3, 22, 5, c);
			FillRect(val, 36, 24, 2, 7, 24, 11, MoonBeige);
			FillRect(val, 36, 24, 24, 5, 10, 15, MoonBeige);
			FillRect(val, 36, 24, 5, 9, 12, 5, new Color32(byte.MaxValue, byte.MaxValue, byte.MaxValue, (byte)90));
			val.Apply();
			((Texture)val).filterMode = (FilterMode)0;
			_bedFilledSprite = Sprite.Create(val, new Rect(0f, 0f, 36f, 24f), new Vector2(0.5f, 0.5f), 100f);
			return _bedFilledSprite;
		}

		private static void FillRect(Texture2D tex, int tw, int th, int x0, int y0, int rw, int rh, Color32 c)
		{
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			for (int i = y0; i < y0 + rh && i < th; i++)
			{
				for (int j = x0; j < x0 + rw && j < tw; j++)
				{
					tex.SetPixel(j, i, Color32.op_Implicit(c));
				}
			}
		}

		private static Sprite GetChevronSprite()
		{
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Expected O, but got Unknown
			//IL_00c0: 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_007f: 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_0080: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)_chevronSprite != (Object)null)
			{
				return _chevronSprite;
			}
			Texture2D val = new Texture2D(8, 14, (TextureFormat)4, false);
			Color32 val2 = default(Color32);
			((Color32)(ref val2))..ctor((byte)0, (byte)0, (byte)0, (byte)0);
			Color32 val3 = default(Color32);
			((Color32)(ref val3))..ctor(byte.MaxValue, byte.MaxValue, byte.MaxValue, byte.MaxValue);
			for (int i = 0; i < 14; i++)
			{
				int num = ((i > 6) ? (i - 7) : (6 - i));
				int num2 = 7 - num;
				for (int j = 0; j < 8; j++)
				{
					bool flag = j == num2 || j == num2 - 1;
					val.SetPixel(j, i, Color32.op_Implicit(flag ? val3 : val2));
				}
			}
			val.Apply();
			((Texture)val).filterMode = (FilterMode)0;
			_chevronSprite = Sprite.Create(val, new Rect(0f, 0f, 8f, 14f), new Vector2(0.5f, 0.5f), 100f);
			return _chevronSprite;
		}

		private static Sprite BaseWhiteSprite()
		{
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)_whiteSprite != (Object)null)
			{
				return _whiteSprite;
			}
			Texture2D whiteTexture = Texture2D.whiteTexture;
			_whiteSprite = Sprite.Create(whiteTexture, new Rect(0f, 0f, (float)((Texture)whiteTexture).width, (float)((Texture)whiteTexture).height), new Vector2(0.5f, 0.5f), 100f);
			return _whiteSprite;
		}
	}
	public class SleepTracker : MonoBehaviour
	{
		public bool Enabled = true;

		private bool _lastCanSleep;

		private int _lastBroadcastTotal = -1;

		private int _lastBroadcastSleeping = -1;

		private double _lastBroadcastExtraRate = -1.0;

		private float _lastRpcRecalcTime;

		private int _heartbeatCounter;

		public static SleepTracker Instance { get; private set; }

		public bool CanSleep { get; private set; }

		public static double CurrentExtraRate { get; internal set; }

		public static double TotalPartialSleepBoostSeconds { get; internal set; }

		public static int CurrentPlayerCount { get; private set; }

		public static int CurrentSleepingCount { get; private set; }

		public static bool AllPlayersSleeping
		{
			get
			{
				if (CurrentPlayerCount > 0)
				{
					return CurrentSleepingCount >= CurrentPlayerCount;
				}
				return false;
			}
		}

		public static double LastPartialSleepExtraRate => CurrentExtraRate;

		private static bool IsCharacterInBedForBoost(ZDO zdo)
		{
			if (zdo != null && zdo.IsValid())
			{
				return zdo.GetBool(ZDOVars.s_inBed, false);
			}
			return false;
		}

		public static void GetSleepOccupancyCounts(out int playerCount, out int playersSleeping)
		{
			playerCount = 0;
			playersSleeping = 0;
			ZNet instance = ZNet.instance;
			if ((Object)(object)instance == (Object)null)
			{
				return;
			}
			List<ZDO> allCharacterZDOS = instance.GetAllCharacterZDOS();
			int nrOfPlayers = instance.GetNrOfPlayers();
			int realTotalPlayers = Math.Max(allCharacterZDOS?.Count ?? 0, nrOfPlayers);
			playerCount = ConfigRegistry.GetEffectiveTotalPlayersForMod(realTotalPlayers);
			int num = 0;
			if (allCharacterZDOS != null)
			{
				for (int i = 0; i < allCharacterZDOS.Count; i++)
				{
					ZDO val = allCharacterZDOS[i];
					if (val != null && IsCharacterInBedForBoost(val))
					{
						num++;
					}
				}
			}
			playersSleeping = ConfigRegistry.GetEffectiveSleepingPlayersForMod(num, playerCount);
		}

		private static double ComputeExtraRateForPartialBoost(int playerCount, int playersSleeping)
		{
			if (playerCount <= 1)
			{
				return 0.0;
			}
			if (playersSleeping <= 0 || playersSleeping >= playerCount)
			{
				return 0.0;
			}
			double num = (double)playersSleeping / (double)(playerCount - 1);
			return (double)ConfigRegistry.BonusMultiplier.Value * num * (double)ConfigRegistry.BonusIncrementScale.Value;
		}

		public static double GetNextMorningCapSeconds()
		{
			if ((Object)(object)ZNet.instance == (Object)null || !ZNet.instance.IsServer() || (Object)(object)EnvMan.instance == (Object)null)
			{
				return double.PositiveInfinity;
			}
			EnvMan instance = EnvMan.instance;
			double timeSeconds = ZNet.instance.GetTimeSeconds();
			double num = instance.m_dayLengthSec;
			int day = instance.GetDay(timeSeconds - num * 0.150000005960464);
			return instance.GetMorningStartSec(day + 1);
		}

		public static double ComputePartialSleepBoost()
		{
			return CurrentExtraRate;
		}

		private void Awake()
		{
			if ((Object)(object)ZNet.instance == (Object)null || !ZNet.instance.IsServer())
			{
				Object.Destroy((Object)(object)this);
				return;
			}
			Instance = this;
			BetterSleepBruh.Log.Debug("[SERVER] SleepTracker Awakes.");
		}

		private void Start()
		{
			BetterSleepBruh.Log.Debug("[SERVER] SleepTracker Start.");
			if (ZNet.instance.IsServer())
			{
				_lastCanSleep = (Object)(object)EnvMan.instance != (Object)null && EnvManPatches.IsInSleepWindow(EnvMan.instance);
				if (ZRoutedRpc.instance != null)
				{
					ZRoutedRpc.instance.Register("NotifyBedOccupancyChanged", (Action<long>)NotifyBedOccupancyChanged);
					ZRoutedRpc.instance.Register("RPC_RequestSleepingPlayerInfo", (Action<long>)RPC_RequestSleepingPlayerInfo);
				}
				LoadData();
				((MonoBehaviour)this).InvokeRepeating("UpdateSleeping", 1f, 1f);
			}
		}

		private static string GetSaveFilePath()
		{
			if ((Object)(object)ZNet.instance == (Object)null)
			{
				return null;
			}
			string worldName = ZNet.instance.GetWorldName();
			if (string.IsNullOrEmpty(worldName))
			{
				return null;
			}
			return Path.Combine(Paths.ConfigPath, "BetterSleepBruh_Data_" + worldName + ".txt");
		}

		public static void SaveData()
		{
			string saveFilePath = GetSaveFilePath();
			if (string.IsNullOrEmpty(saveFilePath))
			{
				return;
			}
			try
			{
				File.WriteAllText(saveFilePath, TotalPartialSleepBoostSeconds.ToString(CultureInfo.InvariantCulture));
			}
			catch (Exception ex)
			{
				BetterSleepBruh.Log.Warning("Failed to save sleep boost data: " + ex.Message);
			}
		}

		public static void LoadData()
		{
			string saveFilePath = GetSaveFilePath();
			if (string.IsNullOrEmpty(saveFilePath) || !File.Exists(saveFilePath))
			{
				return;
			}
			try
			{
				if (double.TryParse(File.ReadAllText(saveFilePath), NumberStyles.Float, CultureInfo.InvariantCulture, out var result))
				{
					TotalPartialSleepBoostSeconds = result;
				}
			}
			catch (Exception ex)
			{
				BetterSleepBruh.Log.Warning("Failed to load sleep boost data: " + ex.Message);
			}
		}

		public void OnBedOccupancyChanged()
		{
			if (!((Object)(object)ZNet.instance == (Object)null) && ZNet.instance.IsServer() && Enabled)
			{
				RecalculateOccupancy();
			}
		}

		private void NotifyBedOccupancyChanged(long sender)
		{
			ZNet instance = ZNet.instance;
			if (!((Object)(object)instance == (Object)null) && instance.IsServer() && Enabled && (sender == ZNet.GetUID() || instance.GetPeer(sender) != null))
			{
				float time = Time.time;
				if (!(time - _lastRpcRecalcTime < 0.25f))
				{
					_lastRpcRecalcTime = time;
					BetterSleepBruh.Log.Debug($"[SERVER] NotifyBedOccupancyChanged Heard from {sender}");
					RecalculateOccupancy();
				}
			}
		}

		private void RPC_RequestSleepingPlayerInfo(long sender)
		{
			ZNet instance = ZNet.instance;
			if (!((Object)(object)instance == (Object)null) && instance.IsServer() && (sender == ZNet.GetUID() || instance.GetPeer(sender) != null) && ZRoutedRpc.instance != null)
			{
				if (CanSleep)
				{
					ZRoutedRpc.instance.InvokeRoutedRPC(sender, "RPC_StartSleep", Array.Empty<object>());
				}
				else
				{
					ZRoutedRpc.instance.InvokeRoutedRPC(sender, "RPC_StopSleep", Array.Empty<object>());
				}
				ZRoutedRpc.instance.InvokeRoutedRPC(sender, "RPC_SleepingPlayerInfo", new object[3] { CurrentPlayerCount, CurrentSleepingCount, CurrentExtraRate });
				ZRoutedRpc.instance.InvokeRoutedRPC(sender, "BSB_SyncSleepBoostTotal", new object[1] { TotalPartialSleepBoostSeconds });
			}
		}

		public void RecalculateOccupancy(bool forceBroadcast = false)
		{
			if ((Object)(object)ZNet.instance == (Object)null || !ZNet.instance.IsServer())
			{
				CurrentPlayerCount = 0;
				CurrentSleepingCount = 0;
				CurrentExtraRate = 0.0;
				return;
			}
			GetSleepOccupancyCounts(out var playerCount, out var playersSleeping);
			CurrentPlayerCount = playerCount;
			CurrentSleepingCount = playersSleeping;
			CurrentExtraRate = (((Object)(object)EnvMan.instance != (Object)null && EnvManPatches.IsInSleepWindow(EnvMan.instance)) ? ComputeExtraRateForPartialBoost(playerCount, playersSleeping) : 0.0);
			if (forceBroadcast || playerCount != _lastBroadcastTotal || playersSleeping != _lastBroadcastSleeping || Math.Abs(CurrentExtraRate - _lastBroadcastExtraRate) > 0.001)
			{
				BroadcastSleepingInfoNow();
			}
		}

		private void UpdateSleeping()
		{
			if ((Object)(object)ZNet.instance == (Object)null || !ZNet.instance.IsServer())
			{
				return;
			}
			CanSleep = (Object)(object)EnvMan.instance != (Object)null && EnvManPatches.IsInSleepWindow(EnvMan.instance);
			if (CanSleep)
			{
				_heartbeatCounter++;
				bool flag = _heartbeatCounter >= 3;
				if (flag)
				{
					_heartbeatCounter = 0;
				}
				RecalculateOccupancy(flag);
			}
			else
			{
				RecalculateOccupancy();
			}
			if (CanSleep && !_lastCanSleep)
			{
				if (ZRoutedRpc.instance != null)
				{
					ZRoutedRpc.instance.InvokeRoutedRPC(0L, "RPC_StartSleep", Array.Empty<object>());
				}
				RecalculateOccupancy(forceBroadcast: true);
			}
			if (!CanSleep && _lastCanSleep)
			{
				if (((Object)(object)EnvMan.instance == (Object)null || !EnvMan.instance.IsTimeSkipping()) && ZRoutedRpc.instance != null)
				{
					ZRoutedRpc.instance.InvokeRoutedRPC(0L, "RPC_StopSleep", Array.Empty<object>());
				}
				_lastBroadcastTotal = -1;
				_lastBroadcastSleeping = -1;
				_lastBroadcastExtraRate = -1.0;
				SaveData();
			}
			_lastCanSleep = CanSleep;
		}

		private void BroadcastSleepingInfoNow()
		{
			if (!((Object)(object)ZNet.instance == (Object)null) && ZNet.instance.IsServer())
			{
				_lastBroadcastTotal = CurrentPlayerCount;
				_lastBroadcastSleeping = CurrentSleepingCount;
				_lastBroadcastExtraRate = CurrentExtraRate;
				if (ConfigRegistry.IsPlayerCountTestingActive)
				{
					BetterSleepBruh.Log.Debug($"[BetterSleepBruh TESTING] broadcast total={CurrentPlayerCount} sleeping={CurrentSleepingCount} extraRate={CurrentExtraRate}");
				}
				else
				{
					BetterSleepBruh.Log.Debug($"[SERVER] Player Sleeping Info: Players on Server: {CurrentPlayerCount} Players Sleeping: {CurrentSleepingCount} Extra rate: {CurrentExtraRate}");
				}
				if (ZRoutedRpc.instance != null)
				{
					ZRoutedRpc.instance.InvokeRoutedRPC(0L, "RPC_SleepingPlayerInfo", new object[3] { CurrentPlayerCount, CurrentSleepingCount, CurrentExtraRate });
				}
			}
		}

		private void OnDestroy()
		{
			SaveData();
			if ((Object)(object)Instance == (Object)(object)this)
			{
				Instance = null;
			}
		}
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableAttribute : Attribute
	{
		public readonly byte[] NullableFlags;

		public NullableAttribute(byte P_0)
		{
			NullableFlags = new byte[1] { P_0 };
		}

		public NullableAttribute(byte[] P_0)
		{
			NullableFlags = P_0;
		}
	}
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableContextAttribute : Attribute
	{
		public readonly byte Flag;

		public NullableContextAttribute(byte P_0)
		{
			Flag = P_0;
		}
	}
}
namespace ItemManager
{
	[PublicAPI]
	internal enum CraftingTable
	{
		Disabled,
		Inventory,
		[InternalName("piece_workbench")]
		Workbench,
		[InternalName("piece_cauldron")]
		Cauldron,
		[InternalName("forge")]
		Forge,
		[InternalName("piece_artisanstation")]
		ArtisanTable,
		[InternalName("piece_stonecutter")]
		StoneCutter,
		[InternalName("piece_magetable")]
		MageTable,
		[InternalName("blackforge")]
		BlackForge,
		[InternalName("piece_preptable")]
		FoodPreparationTable,
		[InternalName("piece_MeadCauldron")]
		MeadKetill,
		Custom
	}
	[PublicAPI]
	internal enum ConversionPiece
	{
		Disabled,
		[InternalName("smelter")]
		Smelter,
		[InternalName("charcoal_kiln")]
		CharcoalKiln,
		[InternalName("blastfurnace")]
		BlastFurnace,
		[InternalName("windmill")]
		Windmill,
		[InternalName("piece_spinningwheel")]
		SpinningWheel,
		[InternalName("eitrrefinery")]
		EitrRefinery,
		Custom
	}
	internal class InternalName : Attribute
	{
		public readonly string internalName;

		public InternalName(string internalName)
		{
			this.internalName = internalName;
		}
	}
	[PublicAPI]
	internal class RequiredResourceList
	{
		public readonly List<Requirement> Requirements = new List<Requirement>();

		public bool Free;

		public void Add(string itemName, int amount, int quality = 0)
		{
			Requirements.Add(new Requirement
			{
				itemName = itemName,
				amount = amount,
				quality = quality
			});
		}

		public void Add(string itemName, ConfigEntry<int> amountConfig, int quality = 0)
		{
			Requirements.Add(new Requirement
			{
				itemName = itemName,
				amountConfig = amountConfig,
				quality = quality
			});
		}
	}
	[PublicAPI]
	internal class CraftingStationList
	{
		public readonly List<CraftingStationConfig> Stations = new List<CraftingStationConfig>();

		public void Add(CraftingTable table, int level)
		{
			Stations.Add(new CraftingStationConfig
			{
				Table = table,
				level = level
			});
		}

		public void Add(string customTable, int level)
		{
			Stations.Add(new CraftingStationConfig
			{
				Table = CraftingTable.Custom,
				level = level,
				custom = customTable
			});
		}
	}
	[PublicAPI]
	internal class ItemRecipe
	{
		public readonly RequiredResourceList RequiredItems = new RequiredResourceList();

		public readonly RequiredResourceList RequiredUpgradeItems = new RequiredResourceList();

		public readonly CraftingStationList Crafting = new CraftingStationList();

		public int CraftAmount = 1;

		public bool RequireOnlyOneIngredient;

		public float QualityResultAmountMultiplier = 1f;

		public ConfigEntryBase? RecipeIsActive;
	}
	[PublicAPI]
	internal class Trade
	{
		public Trader Trader;

		public uint Price;

		public uint Stack = 1u;

		public string? RequiredGlobalKey;
	}
	[PublicAPI]
	[Flags]
	internal enum Trader
	{
		None = 0,
		Haldor = 1,
		Hildir = 2
	}
	internal struct Requirement
	{
		public string itemName;

		public int amount;

		public ConfigEntry<int>? amountConfig;

		[Description("Set to a non-zero value to apply the requirement only for a specific quality")]
		public int quality;
	}
	internal struct CraftingStationConfig
	{
		public CraftingTable Table;

		public int level;

		public string? custom;
	}
	[Flags]
	internal enum Configurability
	{
		Disabled = 0,
		Recipe = 1,
		Stats = 2,
		Drop = 4,
		Trader = 8,
		Full = 0xF
	}
	[PublicAPI]
	internal class DropTargets
	{
		public readonly List<DropTarget> Drops = new List<DropTarget>();

		public void Add(string creatureName, float chance, int min = 1, int? max = null, bool levelMultiplier = true, bool dontScale = false)
		{
			Drops.Add(new DropTarget
			{
				creature = creatureName,
				chance = chance,
				min = min,
				max = (max ?? min),
				levelMultiplier = levelMultiplier,
				dontScale = dontScale
			});
		}
	}
	internal struct DropTarget
	{
		public string creature;

		public int min;

		public int max;

		public float chance;

		public bool levelMultiplier;

		public bool dontScale;
	}
	internal enum Toggle
	{
		On = 1,
		Off = 0
	}
	[PublicAPI]
	internal class Item
	{
		private class ItemConfig
		{
			public ConfigEntry<string>? craft;

			public ConfigEntry<string>? upgrade;

			public ConfigEntry<CraftingTable> table;

			public ConfigEntry<int> tableLevel;

			public ConfigEntry<string> customTable;

			public ConfigEntry<int>? maximumTableLevel;

			public ConfigEntry<Toggle> requireOneIngredient;

			public ConfigEntry<float> qualityResultAmountMultiplier;
		}

		private class TraderConfig
		{
			public ConfigEntry<Trader> trader;

			public ConfigEntry<uint> price;

			public ConfigEntry<uint> stack;

			public ConfigEntry<string> requiredGlobalKey;
		}

		private class RequirementQuality
		{
			public int quality;
		}

		private class ConfigurationManagerAttributes
		{
			[UsedImplicitly]
			public int? Order;

			[UsedImplicitly]
			public bool? Browsable;

			[UsedImplicitly]
			public string? Category;

			[UsedImplicitly]
			public Action<ConfigEntryBase>? CustomDrawer;

			[UsedImplicitly]
			public Action<IUguiDrawerScope>? CustomUguiDrawer;

			public Func<bool>? browsability;
		}

		[PublicAPI]
		public enum DamageModifier
		{
			Normal,
			Resistant,
			Weak,
			Immune,
			Ignore,
			VeryResistant,
			VeryWeak,
			None
		}

		private delegate void setDmgFunc(ref DamageTypes dmg, float value);

		private class SerializedRequirements
		{
			public readonly List<Requirement> Reqs;

			public SerializedRequirements(List<Requirement> reqs)
			{
				Reqs = reqs;
			}

			public SerializedRequirements(string reqs)
				: this(reqs.Split(new char[1] { ',' }).Selec