Decompiled source of BetterSleepBruh v2.0.10

plugins/BetterSleepBruh.dll

Decompiled 4 days 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.IO.Compression;
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.Networking;
using UnityEngine.UI;
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;

[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.0.10.0")]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("2.0.10.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.0.10")]
	[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.0.10";

		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.0.10";

		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 = ConfigRegistry.ShowSplashOnStartup,
				EnableTelemetry = ConfigRegistry.EnableTelemetry
			});
		}

		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 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[] { "org.bepinex.helpers.LocalizationManager" })]
		[HarmonyBefore(new string[] { "org.bepinex.helpers.ItemManager" })]
		public static class FejdStartupAwakePatch
		{
			private static void Prefix()
			{
				BetterSleepBruh.Waiter.ValheimIsAwake(awakeFlag: true);
				BetterSleepBruh.ModInstance?.ResetSession();
			}
		}
	}
	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)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>());
					}
					EnvMan.instance.SkipToMorning();
				}
				return false;
			}
		}
	}
	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 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)
				{
					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 });
					}
				}
			}
		}

		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;

		internal static ConfigEntry<bool> ShowSplashOnStartup;

		internal static ConfigEntry<bool> EnableTelemetry;

		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_029a: Expected O, but got Unknown
			//IL_029a: Unknown result type (might be due to invalid IL or missing references)
			//IL_02a9: Expected O, but got Unknown
			//IL_02c2: Unknown result type (might be due to invalid IL or missing references)
			//IL_02c7: Unknown result type (might be due to invalid IL or missing references)
			//IL_02d4: Expected O, but got Unknown
			//IL_02d4: Unknown result type (might be due to invalid IL or missing references)
			//IL_02e3: 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.UnsyncedConfig("Local Config", "Show Splash on Startup", value: true, new ConfigDescription("If enabled, displays the mod overview and links splash screen on game startup.", (AcceptableValueBase)null, new object[1] { (object)new ConfigurationManagerAttributes
				{
					Order = 4
				} }), ref ShowSplashOnStartup);
				ConfigSyncBase.UnsyncedConfig("Local Config", "Enable Anonymous Telemetry", value: true, new ConfigDescription("If enabled, sends anonymous mod launch and heartbeat telemetry to help improve mod stability and track active versions.", (AcceptableValueBase)null, new object[1] { (object)new ConfigurationManagerAttributes
				{
					Order = 5
				} }), ref EnableTelemetry);
			}
		}

		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);
				_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_SleepingPlayerInfo(long sender, int totalPlayers, int playersSleeping, double 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)
		{
			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; private 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);
				}
				((MonoBehaviour)this).InvokeRepeating("UpdateSleeping", 1f, 1f);
			}
		}

		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 });
			}
		}

		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;
			}
			_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()
		{
			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] { ',' }).Select(delegate(string r)
				{
					string[] array = r.Split(new char[1] { ':' });
					int result;
					int result2;
					return new Requirement
					{
						itemName = array[0],
						amount = ((array.Length <= 1 || !int.TryParse(array[1], out result)) ? 1 : result),
						quality = ((array.Length > 2 && int.TryParse(array[2], out result2)) ? result2 : 0)
					};
				}).ToList())
			{
			}

			public override string ToString()
			{
				return string.Join(",", Reqs.Select((Requirement r) => $"{r.itemName}:{r.amount}"));
			}

			public static ItemDrop? fetchByName(ObjectDB objectDB, string name)
			{
				GameObject itemPrefab = objectDB.GetItemPrefab(name);
				ItemDrop obj = (((Object)(object)itemPrefab != (Object)null) ? itemPrefab.GetComponent<ItemDrop>() : null);
				if ((Object)(object)obj == (Object)null)
				{
					LogManager.Log.Warning("The required item '" + name + "' does not exist.");
				}
				return obj;
			}

			public static Requirement[] toPieceReqs(ObjectDB objectDB, SerializedRequirements craft, SerializedRequirements upgrade)
			{
				//IL_00f0: Unknown result type (might be due to invalid IL or missing references)
				//IL_00f5: Unknown result type (might be due to invalid IL or missing references)
				//IL_00fd: Unknown result type (might be due to invalid IL or missing references)
				//IL_0178: Unknown result type (might be due to invalid IL or missing references)
				//IL_017d: Unknown result type (might be due to invalid IL or missing references)
				//IL_0185: Unknown result type (might be due to invalid IL or missing references)
				//IL_018c: Unknown result type (might be due to invalid IL or missing references)
				//IL_018f: Expected O, but got Unknown
				//IL_0194: Expected O, but got Unknown
				//IL_011c: Unknown result type (might be due to invalid IL or missing references)
				//IL_0125: Expected O, but got Unknown
				Dictionary<string, Requirement> dictionary = craft.Reqs.Where((Requirement r) => r.itemName != "").ToDictionary((Func<Requirement, string>)((Requirement r) => r.itemName), (Func<Requirement, Requirement>)delegate(Requirement r)
				{
					//IL_000d: Unknown result type (might be due to invalid IL or missing references)
					//IL_0012: Unknown result type (might be due to invalid IL or missing references)
					//IL_002f: Unknown result type (might be due to invalid IL or missing references)
					//IL_0036: Unknown result type (might be due to invalid IL or missing references)
					//IL_003e: Expected O, but got Unknown
					ItemDrop val6 = ResItem(r);
					return (val6 != null) ? new Requirement
					{
						m_amount = (r.amountConfig?.Value ?? r.amount),
						m_resItem = val6,
						m_amountPerLevel = 0
					} : ((Requirement)null);
				});
				List<Requirement> list = dictionary.Values.Where((Requirement v) => v != null).ToList();
				foreach (Requirement item in upgrade.Reqs.Where((Requirement r) => r.itemName != ""))
				{
					if (item.quality > 0)
					{
						ItemDrop val = ResItem(item);
						if (val != null)
						{
							Requirement val2 = new Requirement
							{
								m_resItem = val,
								m_amountPerLevel = (item.amountConfig?.Value ?? item.amount),
								m_amount = 0
							};
							list.Add(val2);
							requirementQuality.Add(val2, new RequirementQuality
							{
								quality = item.quality
							});
						}
						continue;
					}
					if (!dictionary.TryGetValue(item.itemName, out var value) || value == null)
					{
						ItemDrop val3 = ResItem(item);
						if (val3 != null)
						{
							string itemName = item.itemName;
							Requirement val4 = new Requirement
							{
								m_resItem = val3,
								m_amount = 0
							};
							Requirement val5 = val4;
							dictionary[itemName] = val4;
							value = val5;
							list.Add(value);
						}
					}
					if (value != null)
					{
						value.m_amountPerLevel = item.amountConfig?.Value ?? item.amount;
					}
				}
				return list.ToArray();
				ItemDrop? ResItem(Requirement r)
				{
					return fetchByName(objectDB, r.itemName);
				}
			}
		}

		private class SerializedDrop
		{
			public readonly List<DropTarget> Drops;

			public SerializedDrop(List<DropTarget> drops)
			{
				Drops = drops;
			}

			public SerializedDrop(string drops)
			{
				Drops = ((drops == "") ? ((IEnumerable<string>)Array.Empty<string>()) : ((IEnumerable<string>)drops.Split(new char[1] { ',' }))).Select(delegate(string r)
				{
					string[] array = r.Split(new char[1] { ':' });
					if (array.Length <= 2 || !int.TryParse(array[2], out var result))
					{
						result = 1;
					}
					if (array.Length <= 3 || !int.TryParse(array[3], out var result2))
					{
						result2 = result;
					}
					bool levelMultiplier = array.Length <= 4 || array[4] != "0";
					float result3;
					return new DropTarget
					{
						creature = array[0],
						chance = ((array.Length > 1 && float.TryParse(array[1], out result3)) ? result3 : 1f),
						min = result,
						max = result2,
						levelMultiplier = levelMultiplier
					};
				}).ToList();
			}

			public override string ToString()
			{
				return string.Join(",", Drops.Select((DropTarget r) => $"{r.creature}:{r.chance.ToString(CultureInfo.InvariantCulture)}:{r.min}:" + ((r.min == r.max) ? "" : $"{r.max}") + (r.levelMultiplier ? "" : ":0")));
			}

			private static Character? fetchByName(ZNetScene netScene, string name)
			{
				GameObject prefab = netScene.GetPrefab(name);
				Character obj = (((Object)(object)prefab != (Object)null) ? prefab.GetComponent<Character>() : null);
				if ((Object)(object)obj == (Object)null)
				{
					LogManager.Log.Debug("The drop target character '" + name + "' does not exist.");
				}
				return obj;
			}

			public Dictionary<Character, Drop> toCharacterDrops(ZNetScene netScene, GameObject item, bool adjustLevel = false, bool adjustScaling = false)
			{
				//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)
				//IL_003a: 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_0052: Unknown result type (might be due to invalid IL or missing references)
				//IL_005e: Unknown result type (might be due to invalid IL or missing references)
				//IL_0065: Unknown result type (might be due to invalid IL or missing references)
				//IL_0075: Expected O, but got Unknown
				Dictionary<Character, Drop> dictionary = new Dictionary<Character, Drop>();
				foreach (DropTarget drop in Drops)
				{
					Character val = fetchByName(netScene, drop.creature);
					if (val != null)
					{
						dictionary[val] = new Drop
						{
							m_prefab = item,
							m_amountMin = drop.min,
							m_amountMax = drop.max,
							m_chance = drop.chance,
							m_levelMultiplier = adjustLevel,
							m_dontScale = !adjustScaling
						};
					}
				}
				return dictionary;
			}
		}

		private static bool _initialized = false;

		private static readonly List<Item> registeredItems = new List<Item>();

		private static readonly Dictionary<ItemDrop, Item> itemDropMap = new Dictionary<ItemDrop, Item>();

		private static Dictionary<Item, Dictionary<string, List<Recipe>>> activeRecipes = new Dictionary<Item, Dictionary<string, List<Recipe>>>();

		private static Dictionary<Recipe, ConfigEntryBase?> hiddenCraftRecipes = new Dictionary<Recipe, ConfigEntryBase>();

		private static Dictionary<Recipe, ConfigEntryBase?> hiddenUpgradeRecipes = new Dictionary<Recipe, ConfigEntryBase>();

		private static Dictionary<Item, Dictionary<string, ItemConfig>> itemCraftConfigs = new Dictionary<Item, Dictionary<string, ItemConfig>>();

		private static Dictionary<Item, ConfigEntry<string>> itemDropConfigs = new Dictionary<Item, ConfigEntry<string>>();

		private static Dictionary<Item, ConfigEntry<bool>> itemDropEnabledConfig = new Dictionary<Item, ConfigEntry<bool>>();

		private static Dictionary<Item, ConfigEntry<bool>> itemDropScalingConfig = new Dictionary<Item, ConfigEntry<bool>>();

		private static Dictionary<Item, ConfigEntry<bool>> itemDropLevelingConfig = new Dictionary<Item, ConfigEntry<bool>>();

		private Dictionary<CharacterDrop, Drop> characterDrops = new Dictionary<CharacterDrop, Drop>();

		private readonly Dictionary<ConfigEntryBase, Action> statsConfigs = new Dictionary<ConfigEntryBase, Action>();

		private static readonly ConditionalWeakTable<Requirement, RequirementQuality> requirementQuality = new ConditionalWeakTable<Requirement, RequirementQuality>();

		public string SectionName = string.Empty;

		public static Configurability DefaultConfigurability = Configurability.Full;

		public Configurability? Configurable;

		private Configurability configurationVisible = Configurability.Full;

		private TraderConfig? traderConfig;

		public readonly GameObject Prefab;

		[Description("Specifies the maximum required crafting station level to upgrade and repair the item.\nDefault is calculated from crafting station level and maximum quality.")]
		public int MaximumRequiredStationLevel = int.MaxValue;

		[Description("Assigns the item as a drop item to a creature.\nUses a creature name, a drop chance and a minimum and maximum amount.")]
		public readonly DropTargets DropsFrom = new DropTargets();

		[Description("Configures whether the item can be bought at the trader.\nDon't forget to set cost to something above 0 or the item will be sold for free.")]
		public readonly Trade Trade = new Trade();

		internal List<Conversion> Conversions = new List<Conversion>();

		internal List<ItemConversion> conversions = new List<ItemConversion>();

		public Dictionary<string, ItemRecipe> Recipes = new Dictionary<string, ItemRecipe>();

		private static object? configManager;

		private static BaseUnityPlugin? _plugin;

		private Configurability configurability => Configurable ?? DefaultConfigurability;

		[Description("Specifies the resources needed to craft the item.\nUse .Add to add resources with their internal ID and an amount.\nUse one .Add for each resource type the item should need.")]
		public RequiredResourceList RequiredItems => this[""].RequiredItems;

		[Description("Specifies the resources needed to upgrade the item.\nUse .Add to add resources with their internal ID and an amount. This amount will be multipled by the item quality level.\nUse one .Add for each resource type the upgrade should need.")]
		public RequiredResourceList RequiredUpgradeItems => this[""].RequiredUpgradeItems;

		[Description("Specifies the crafting station needed to craft the item.\nUse .Add to add a crafting station, using the CraftingTable enum and a minimum level for the crafting station.\nUse one .Add for each crafting station.")]
		public CraftingStationList Crafting => this[""].Crafting;

		[Description("Specifies a config entry which toggles whether a recipe is active.")]
		public ConfigEntryBase? RecipeIsActive
		{
			get
			{
				return this[""].RecipeIsActive;
			}
			set
			{
				this[""].RecipeIsActive = value;
			}
		}

		[Description("Specifies the number of items that should be given to the player with a single craft of the item.\nDefaults to 1.")]
		public int CraftAmount
		{
			get
			{
				return this[""].CraftAmount;
			}
			set
			{
				this[""].CraftAmount = value;
			}
		}

		public bool RequireOnlyOneIngredient
		{
			get
			{
				return this[""].RequireOnlyOneIngredient;
			}
			set
			{
				this[""].RequireOnlyOneIngredient = value;
			}
		}

		public float QualityResultAmountMultiplier
		{
			get
			{
				return this[""].QualityResultAmountMultiplier;
			}
			set
			{
				this[""].QualityResultAmountMultiplier = value;
			}
		}

		public ItemRecipe this[string name]
		{
			get
			{
				if (Recipes.TryGetValue(name, out ItemRecipe value))
				{
					return value;
				}
				return Recipes[name] = new ItemRecipe();
			}
		}

		private static BaseUnityPlugin plugin
		{
			get
			{
				//IL_00a1: Unknown result type (might be due to invalid IL or missing references)
				//IL_00ab: Expected O, but got Unknown
				if ((Object)(object)_plugin == (Object)null)
				{
					IEnumerable<TypeInfo> source;
					try
					{
						source = Assembly.GetExecutingAssembly().DefinedTypes.ToList();
					}
					catch (ReflectionTypeLoadException ex)
					{
						source = from t in ex.Types
							where t != null
							select t.GetTypeInfo();
					}
					_plugin = (BaseUnityPlugin)Chainloader.ManagerObject.GetComponent((Type)source.First((TypeInfo t) => t.IsClass && typeof(BaseUnityPlugin).IsAssignableFrom(t)));
				}
				return _plugin;
			}
		}

		public static void Init()
		{
			if (!_initialized)
			{
				_initialized = true;
			}
		}

		public Item(string assetBundleFileName, string prefabName, string folderName = "assets")
			: this(PrefabManager.RegisterAssetBundle(assetBundleFileName, folderName), prefabName)
		{
		}

		public Item(AssetBundle bundle, string prefabName)
			: this(PrefabManager.RegisterPrefab(bundle, prefabName, addToObjectDb: true), skipRegistering: true)
		{
		}

		public Item(GameObject prefab, bool skipRegistering = false)
		{
			if ((Object)(object)prefab == (Object)null)
			{
				LogManager.Log?.Warning("Attempted to initialize Item with a null prefab.");
				Prefab = null;
				return;
			}
			if (!skipRegistering)
			{
				PrefabManager.RegisterPrefab(prefab, addToObjectDb: true);
			}
			Prefab = prefab;
			registeredItems.Add(this);
			ItemDrop component = Prefab.GetComponent<ItemDrop>();
			if ((Object)(object)component != (Object)null)
			{
				itemDropMap[component] = this;
				if (component.m_itemData != null)
				{
					component.m_itemData.m_dropPrefab = Prefab;
				}
			}
		}

		public void ToggleConfigurationVisibility(Configurability visible)
		{
			configurationVisible = visible;
			if (itemDropConfigs.TryGetValue(this, out ConfigEntry<string> value))
			{
				Toggle((ConfigEntryBase)(object)value, Configurability.Drop);
			}
			if (itemCraftConfigs.TryGetValue(this, out Dictionary<string, ItemConfig> value2))
			{
				foreach (ItemConfig value4 in value2.Values)
				{
					ToggleObj(value4, Configurability.Recipe);
				}
			}
			foreach (Conversion conversion in Conversions)
			{
				if (conversion.config != null)
				{
					ToggleObj(conversion.config, Configurability.Recipe);
				}
			}
			foreach (KeyValuePair<ConfigEntryBase, Action> statsConfig in statsConfigs)
			{
				Toggle(statsConfig.Key, Configurability.Stats);
				if ((visible & Configurability.Stats) != Configurability.Disabled)
				{
					statsConfig.Value();
				}
			}
			reloadConfigDisplay();
			void Toggle(ConfigEntryBase cfg, Configurability check)
			{
				object[] tags = cfg.Description.Tags;
				for (int i = 0; i < tags.Length; i++)
				{
					if (tags[i] is ConfigurationManagerAttributes configurationManagerAttributes)
					{
						configurationManagerAttributes.Browsable = (visible & check) != Configurability.Disabled && (configurationManagerAttributes.browsability == null || configurationManagerAttributes.browsability());
					}
				}
			}
			void ToggleObj(object obj, Configurability check)
			{
				FieldInfo[] fields = obj.GetType().GetFields();
				for (int i = 0; i < fields.Length; i++)
				{
					object? value3 = fields[i].GetValue(obj);
					ConfigEntryBase val = (ConfigEntryBase)((value3 is ConfigEntryBase) ? value3 : null);
					if (val != null)
					{
						Toggle(val, check);
					}
				}
			}
		}

		internal static void reloadConfigDisplay()
		{
			object obj = configManager?.GetType().GetProperty("DisplayingWindow").GetValue(configManager);
			if (obj is bool && (bool)obj)
			{
				configManager.GetType().GetMethod("BuildSettingList").Invoke(configManager, Array.Empty<object>());
			}
		}

		private void UpdateItemTableConfig(string recipeKey, CraftingTable table, string customTableValue)
		{
			if (activeRecipes.ContainsKey(this) && activeRecipes[this].TryGetValue(recipeKey, out List<Recipe> value))
			{
				value.First().m_enabled = table != CraftingTable.Disabled;
				if ((uint)table <= 1u)
				{
					value.First().m_craftingStation = null;
				}
				else if (table == CraftingTable.Custom)
				{
					GameObject prefab = ZNetScene.instance.GetPrefab(customTableValue);
					value.First().m_craftingStation = (((Object)(object)prefab != (Object)null) ? prefab.GetComponent<CraftingStation>() : null);
				}
				else
				{
					GameObject prefab2 = ZNetScene.instance.GetPrefab(getInternalName(table));
					value.First().m_craftingStation = (((Object)(object)prefab2 != (Object)null) ? prefab2.GetComponent<CraftingStation>() : null);
				}
			}
		}

		private void UpdateCraftConfig(string recipeKey, SerializedRequirements craftRequirements, SerializedRequirements upgradeRequirements)
		{
			if (!Object.op_Implicit((Object)(object)ObjectDB.instance) || !activeRecipes.ContainsKey(this) || !activeRecipes[this].TryGetValue(recipeKey, out List<Recipe> value))
			{
				return;
			}
			foreach (Recipe item in value)
			{
				item.m_resources = SerializedRequirements.toPieceReqs(ObjectDB.instance, craftRequirements, upgradeRequirements);
			}
		}

		internal static void Patch_FejdStartup()
		{
			//IL_11ca: Unknown result type (might be due to invalid IL or missing references)
			//IL_11cf: Unknown result type (might be due to invalid IL or missing references)
			//IL_2483: Unknown result type (might be due to invalid IL or missing references)
			//IL_2490: Expected O, but got Unknown
			//IL_1293: Unknown result type (might be due to invalid IL or missing references)
			//IL_1296: Unknown result type (might be due to invalid IL or missing references)
			//IL_12ec: Expected I4, but got Unknown
			//IL_0c57: Unknown result type (might be due to invalid IL or missing references)
			//IL_0c69: Expected O, but got Unknown
			//IL_0d45: Unknown result type (might be due to invalid IL or missing references)
			//IL_0d57: Expected O, but got Unknown
			//IL_0dc6: Unknown result type