Please disclose if any significant portion of your mod was created using AI tools by adding the 'AI Generated' category. Failing to do so may result in the mod being removed from Thunderstore.
Decompiled source of BetterSleepBruh v2.1.2
plugins/BetterSleepBruh.dll
Decompiled a month ago
The result has been truncated due to the large size, download it to view full contents!
using System; using System.Collections; using System.Collections.Concurrent; using System.Collections.Generic; using System.ComponentModel; using System.Diagnostics; using System.Globalization; using System.IO; using System.Linq; using System.Net.Http; using System.Reflection; using System.Reflection.Emit; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using System.Text; using System.Text.RegularExpressions; using System.Threading; using System.Threading.Tasks; using BepInEx; using BepInEx.Bootstrap; using BepInEx.Configuration; using BepInEx.Logging; using BetterSleepBruh.Components; using BetterSleepBruh.Configuration; using BetterSleepBruh.Patches; using HarmonyLib; using JetBrains.Annotations; using Jotunn.Entities; using Jotunn.Managers; using Jotunn.Utils; using Microsoft.CodeAnalysis; using TMPro; using UnityEngine; using UnityEngine.EventSystems; using UnityEngine.Events; using UnityEngine.InputSystem; using UnityEngine.InputSystem.Controls; using UnityEngine.Networking; using UnityEngine.UI; using Valheim.SettingsGui; using Vapok.Common.Abstractions; using Vapok.Common.Managers; using Vapok.Common.Managers.Configuration; using Vapok.Common.Managers.Creature; using Vapok.Common.Managers.LocalizationManager; using Vapok.Common.Managers.Location; using Vapok.Common.Managers.PieceManager; using Vapok.Common.Managers.Skill; using Vapok.Common.Managers.Splash; using Vapok.Common.Managers.StatusEffects; using Vapok.Common.Managers.Telemetry; using Vapok.Common.Shared; using Vapok.Common.Tools; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: AssemblyTitle("BetterSleepBruh")] [assembly: AssemblyDescription("A Valheim Mod that Sleeps Like Enshrouded!")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("Vapok Gaming")] [assembly: AssemblyProduct("BetterSleepBruh")] [assembly: AssemblyCopyright("Copyright © 2025")] [assembly: AssemblyTrademark("")] [assembly: ComVisible(false)] [assembly: Guid("997CB563-FCC7-44B7-8F71-069747D27CC5")] [assembly: AssemblyFileVersion("2.1.2.0")] [assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("2.1.2.0")] [module: UnverifiableCode] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace BetterSleepBruh { [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInPlugin("vapok.mods.BetterSleepBruh", "BetterSleepBruh", "2.1.2")] [SynchronizationMode(/*Could not decode attribute arguments.*/)] public class BetterSleepBruh : BaseUnityPlugin, IPluginInfo { public class Waiting { public event EventHandler StatusChanged; public void ValheimIsAwake(bool awakeFlag) { if (awakeFlag) { this.StatusChanged?.Invoke(this, EventArgs.Empty); } } } private const string _pluginId = "vapok.mods.BetterSleepBruh"; private const string _displayName = "BetterSleepBruh"; private const string _version = "2.1.2"; private SleepHudView _sleepHud; private int _sleepHudBuildAttempts; private bool _zNetHasStopped; public static bool ValheimAwake; public static Waiting Waiter; private static BetterSleepBruh _instance; private static ConfigSyncBase _config; private static ILogIt _log; private Harmony _harmony; public string PluginId => "vapok.mods.BetterSleepBruh"; public string DisplayName => "BetterSleepBruh"; public string Version => "2.1.2"; public BaseUnityPlugin Instance => (BaseUnityPlugin)(object)_instance; public static BetterSleepBruh ModInstance => _instance; public static ILogIt Log => _log; [UsedImplicitly] private void Awake() { //IL_0066: Unknown result type (might be due to invalid IL or missing references) //IL_0070: Expected O, but got Unknown _instance = this; Waiter = new Waiting(); CustomLocalization localization = LocalizationManager.Instance.GetLocalization(); LogManager.Init(PluginId, out _log); Localizer.Init(localization); _config = new ConfigRegistry(_instance); Localizer.Waiter.StatusChanged += InitializeModule; _harmony = new Harmony(((BaseUnityPlugin)this).Info.Metadata.GUID); _harmony.PatchAll(Assembly.GetExecutingAssembly()); ModSplashManager.Register(new ModSplashDossier(_instance) { Tagline = "Sleep mechanics inspired by Enshrouded allowing fast time progression without requiring all players in bed.", ShowOnStartup = ConfigSyncBase.ShowSplashOnStartup }); } private void Start() { ConfigRegistry.Waiter.ConfigurationComplete(configDone: true); ResetSession(); } public void ResetSession() { _zNetHasStopped = false; _sleepHudBuildAttempts = 0; _sleepHud = null; ((MonoBehaviour)this).CancelInvoke("WaitForGame"); ((MonoBehaviour)this).CancelInvoke("WaitForZNet"); ((MonoBehaviour)this).CancelInvoke("TryBuildSleepHud"); ((MonoBehaviour)this).InvokeRepeating("WaitForGame", 0.5f, 0.5f); ((MonoBehaviour)this).InvokeRepeating("WaitForZNet", 0.5f, 0.5f); } private void WaitForGame() { if (!((Object)(object)Game.instance == (Object)null)) { ((MonoBehaviour)this).CancelInvoke("WaitForGame"); ((MonoBehaviour)this).InvokeRepeating("TryBuildSleepHud", 0f, 0.25f); } } private void WaitForZNet() { if (!((Object)(object)ZNet.instance == (Object)null) && !_zNetHasStopped) { ((MonoBehaviour)this).CancelInvoke("WaitForZNet"); if (ZNet.instance.IsServer()) { ((Component)Game.instance).gameObject.AddComponent<SleepTracker>(); } } } private void TryBuildSleepHud() { Log.Debug("Waiting for GuiBuild"); if ((Object)(object)_sleepHud != (Object)null) { ((MonoBehaviour)this).CancelInvoke("TryBuildSleepHud"); return; } Log.Debug("[GuiBuild] Checking for Server..."); if (GUIManager.IsHeadless() || ((Object)(object)ZNet.instance != (Object)null && ZNet.instance.IsDedicated())) { ((MonoBehaviour)this).CancelInvoke("TryBuildSleepHud"); return; } Log.Debug($"[GuiBuild] Checking for previous ZNetShutdown {_zNetHasStopped}..."); if (_zNetHasStopped) { return; } Log.Debug("[GuiBuild] Checking for Player..."); if ((Object)(object)Player.m_localPlayer == (Object)null) { return; } Log.Debug("[GuiBuild] Checking Attempts..."); if (_sleepHudBuildAttempts++ > 120) { ((MonoBehaviour)this).CancelInvoke("TryBuildSleepHud"); Log.Warning("[GuiBuild] Gave up building sleep HUD: minimap hierarchy not found in time."); return; } Log.Debug("[GuiBuild] Building GUI"); BuildSleepGui(); if ((Object)(object)_sleepHud != (Object)null) { ((MonoBehaviour)this).CancelInvoke("TryBuildSleepHud"); } Log.Debug($"[GuiBuild] SleepHud is built: {(Object)(object)_sleepHud != (Object)null}"); } private void BuildSleepGui() { GameObject val = GameObject.Find("_GameMain"); if ((Object)(object)val == (Object)null) { Log.Debug("[GuiBuild] Can't Find _GameMain"); return; } Transform val2 = val.transform.Find("LoadingGUI/PixelFix/IngameGui/HUD/hudroot"); if ((Object)(object)val2 == (Object)null) { Log.Debug("[GuiBuild] Can't Find HUD"); return; } Transform val3 = val2.Find("MiniMap/small"); if ((Object)(object)val3 == (Object)null) { Log.Debug("[GuiBuild] Can't Find Minimap"); return; } _sleepHud = SleepHudView.TryCreate(val3); if ((Object)(object)_sleepHud != (Object)null) { bool active = (Object)(object)EnvMan.instance != (Object)null && EnvManPatches.IsInSleepWindow(EnvMan.instance); ((Component)_sleepHud).gameObject.SetActive(active); } else { Log.Warning("[GuiBuild] Can't Build SleepHud"); } } private void Update() { if (!((Object)(object)ZNet.instance == (Object)null)) { bool haveStopped = ZNet.instance.HaveStopped; if (haveStopped && !_zNetHasStopped) { _zNetHasStopped = true; _sleepHud = null; ((MonoBehaviour)this).CancelInvoke("WaitForGame"); ((MonoBehaviour)this).CancelInvoke("WaitForZNet"); ((MonoBehaviour)this).CancelInvoke("TryBuildSleepHud"); } else if (!haveStopped && _zNetHasStopped) { ResetSession(); } else if (Object.op_Implicit((Object)(object)Player.m_localPlayer) && Object.op_Implicit((Object)(object)ZNetScene.instance) && Object.op_Implicit((Object)(object)Game.instance) && (Object)(object)_sleepHud == (Object)null && !((MonoBehaviour)this).IsInvoking("TryBuildSleepHud")) { _sleepHudBuildAttempts = 0; ((MonoBehaviour)this).InvokeRepeating("TryBuildSleepHud", 0f, 0.25f); } } } public void InitializeModule(object send, EventArgs args) { if (!ValheimAwake) { ValheimAwake = true; } } private void OnDestroy() { _instance = null; } } } namespace BetterSleepBruh.Patches { internal static class CookingStationPatches { [HarmonyPatch(typeof(CookingStation), "GetDeltaTime")] private static class GetDeltaTimePatch { private static void Postfix(ref float __result) { if (ConfigRegistry.ProtectCookingTimers != null && ConfigRegistry.ProtectCookingTimers.Value && SleepTracker.CurrentExtraRate > 0.0) { __result /= (float)(1.0 + SleepTracker.CurrentExtraRate); } } } } internal static class EnvManPatches { [HarmonyPatch(typeof(EnvMan), "CalculateCanSleep")] private static class CalculateCanSleepPatch { private static bool Prefix(EnvMan __instance, ref bool __result) { if (ConfigRegistry.UseVanilleSleep != null && ConfigRegistry.UseVanilleSleep.Value) { return true; } if (!IsInSleepWindow(__instance)) { __result = false; return false; } Player localPlayer = Player.m_localPlayer; if ((Object)(object)localPlayer != (Object)null && (Object)(object)ZNet.instance != (Object)null && ZNet.instance.GetTimeSeconds() <= localPlayer.m_wakeupTime + __instance.m_sleepCooldownSeconds) { __result = false; return false; } __result = true; return false; } } public static bool IsInSleepWindow(EnvMan envMan) { if ((Object)(object)envMan == (Object)null || envMan.IsTimeSkipping()) { return false; } float dayFraction = envMan.GetDayFraction(); float num = ((ConfigRegistry.SleepStart != null) ? ConfigRegistry.SleepStart.Value : 0.5f); if (num < 0.25f) { if (dayFraction < 0.25f) { return dayFraction >= num; } return false; } if (!(dayFraction >= num)) { return dayFraction < 0.25f; } return true; } } public class FejdStartupPatches { [HarmonyPatch(typeof(FejdStartup), "Awake")] [HarmonyAfter(new string[] { "vapok.common.LocalizationManager", "org.bepinex.helpers.LocalizationManager" })] [HarmonyBefore(new string[] { "vapok.common.ItemManager", "org.bepinex.helpers.ItemManager" })] public static class FejdStartupAwakePatch { private static void Prefix() { BetterSleepBruh.Waiter.ValheimIsAwake(awakeFlag: true); BetterSleepBruh.ModInstance?.ResetSession(); } } } internal static class FermenterPatches { [HarmonyPatch(typeof(Fermenter), "GetFermentationTime")] private static class GetFermentationTimePatch { private static void Prefix(Fermenter __instance) { if (ConfigRegistry.ProtectMeadTimers == null || !ConfigRegistry.ProtectMeadTimers.Value) { return; } ZNetView nview = __instance.m_nview; if ((Object)(object)nview == (Object)null || !nview.IsValid() || !nview.IsOwner()) { return; } ZDO zDO = nview.GetZDO(); if (zDO == null) { return; } long num = zDO.GetLong(ZDOVars.s_startTime, 0L); if (num == 0L) { return; } long num2 = (long)(SleepTracker.TotalPartialSleepBoostSeconds * 10000000.0); long num3 = zDO.GetLong(_lastBoostCheckKey, -1L); if (num3 < 0) { if (nview.IsOwner()) { zDO.Set(_lastBoostCheckKey, num2); } return; } long num4 = num2 - num3; if (num4 > 0) { if (nview.IsOwner()) { long num5 = num + num4; zDO.Set(ZDOVars.s_startTime, num5); zDO.Set(_lastBoostCheckKey, num2); } } else if (num3 > num2 && nview.IsOwner()) { zDO.Set(_lastBoostCheckKey, num2); } } } private static readonly int _lastBoostCheckKey = StringExtensionMethods.GetStableHashCode("BSB_FermenterBoostChecked"); } internal static class GamePatches { [HarmonyPatch(typeof(Game), "UpdateSleeping")] private static class UpdateSleepingPatch { private static bool Prefix(Game __instance) { if (ConfigRegistry.UseVanilleSleep != null && ConfigRegistry.UseVanilleSleep.Value) { return true; } if ((Object)(object)__instance == (Object)null || (Object)(object)ZNet.instance == (Object)null || !ZNet.instance.IsServer() || (Object)(object)EnvMan.instance == (Object)null) { return false; } if (__instance.m_sleeping) { if (!EnvMan.instance.IsTimeSkipping()) { __instance.m_sleeping = false; if (ZRoutedRpc.instance != null) { ZRoutedRpc.instance.InvokeRoutedRPC(0L, "SleepStop", Array.Empty<object>()); } } return false; } if (EnvMan.instance.IsTimeSkipping() || !EnvManPatches.IsInSleepWindow(EnvMan.instance)) { return false; } if (SleepTracker.AllPlayersSleeping) { __instance.m_sleeping = true; if (ZRoutedRpc.instance != null) { ZRoutedRpc.instance.InvokeRoutedRPC(0L, "SleepStart", Array.Empty<object>()); } try { EnvMan.instance.SkipToMorning(); } catch (Exception ex) { BetterSleepBruh.Log.Warning("Error while skipping to morning: " + ex.Message); } } return false; } } } internal static class PickablePatches { [HarmonyPatch(typeof(Pickable), "ShouldRespawn")] private static class ShouldRespawnPatch { private static void Prefix(Pickable __instance) { ApplyBoostShift(__instance); } } [HarmonyPatch(typeof(Pickable), "SetPicked")] private static class SetPickedPatch { private static void Postfix(Pickable __instance, bool picked) { if (!picked || ConfigRegistry.ProtectPickableTimers == null || !ConfigRegistry.ProtectPickableTimers.Value || (Object)(object)__instance == (Object)null || __instance.m_respawnTimeMinutes <= 0f) { return; } ZNetView val = _nviewRef.Invoke(__instance); if ((Object)(object)val == (Object)null) { val = ((Component)__instance).GetComponent<ZNetView>(); } if (!((Object)(object)val == (Object)null) && val.IsValid() && val.IsOwner()) { ZDO zDO = val.GetZDO(); if (zDO != null) { long num = (long)(SleepTracker.TotalPartialSleepBoostSeconds * 10000000.0); zDO.Set(_lastBoostCheckKey, num); } } } } [HarmonyPatch(typeof(Pickable), "GetHoverText")] private static class GetHoverTextPatch { private static void Prefix(Pickable __instance) { ApplyBoostShift(__instance); } } private static readonly int _lastBoostCheckKey = StringExtensionMethods.GetStableHashCode("BSB_PickableBoostChecked"); private static readonly FieldRef<Pickable, ZNetView> _nviewRef = AccessTools.FieldRefAccess<Pickable, ZNetView>("m_nview"); private static void ApplyBoostShift(Pickable pickable) { if (ConfigRegistry.ProtectPickableTimers == null || !ConfigRegistry.ProtectPickableTimers.Value || (Object)(object)pickable == (Object)null || pickable.m_respawnTimeMinutes <= 0f || !pickable.GetPicked()) { return; } ZNetView val = _nviewRef.Invoke(pickable); if ((Object)(object)val == (Object)null) { val = ((Component)pickable).GetComponent<ZNetView>(); } if ((Object)(object)val == (Object)null || !val.IsValid() || !val.IsOwner()) { return; } ZDO zDO = val.GetZDO(); if (zDO == null) { return; } long num = (long)(SleepTracker.TotalPartialSleepBoostSeconds * 10000000.0); long num2 = zDO.GetLong(_lastBoostCheckKey, -1L); if (num2 < 0) { zDO.Set(_lastBoostCheckKey, num); return; } long num3 = num - num2; if (num3 > 0) { long num4 = zDO.GetLong(ZDOVars.s_pickedTime, 0L); if (num4 > 0) { long num5 = num4 + num3; zDO.Set(ZDOVars.s_pickedTime, num5); } zDO.Set(_lastBoostCheckKey, num); } else if (num2 > num) { zDO.Set(_lastBoostCheckKey, num); } } } internal static class PlantPatches { [HarmonyPatch(typeof(Plant), "TimeSincePlanted")] private static class TimeSincePlantedPatch { private static void Prefix(Plant __instance) { if (ConfigRegistry.ProtectCropTimers == null || !ConfigRegistry.ProtectCropTimers.Value) { return; } ZNetView nview = __instance.m_nview; if ((Object)(object)nview == (Object)null || !nview.IsValid() || !nview.IsOwner()) { return; } ZDO zDO = nview.GetZDO(); if (zDO == null) { return; } long num = (long)(SleepTracker.TotalPartialSleepBoostSeconds * 10000000.0); long num2 = zDO.GetLong(_lastBoostCheckKey, -1L); if (num2 < 0) { if (nview.IsOwner()) { zDO.Set(_lastBoostCheckKey, num); } return; } long num3 = num - num2; if (num3 > 0) { if (nview.IsOwner()) { long num4 = zDO.GetLong(ZDOVars.s_plantTime, 0L); if (num4 > 0) { long num5 = num4 + num3; zDO.Set(ZDOVars.s_plantTime, num5); } zDO.Set(_lastBoostCheckKey, num); } } else if (num2 > num && nview.IsOwner()) { zDO.Set(_lastBoostCheckKey, num); } } } private static readonly int _lastBoostCheckKey = StringExtensionMethods.GetStableHashCode("BSB_LastBoostChecked"); } internal static class PlayerPatches { [HarmonyPatch(typeof(Player), "AttachStart")] private static class AttachStartPatch { private static void Postfix(Player __instance, bool isBed) { if (isBed && !((Object)(object)ZNet.instance == (Object)null)) { if ((Object)(object)SleepTracker.Instance != (Object)null && ZNet.instance.IsServer()) { SleepTracker.Instance.OnBedOccupancyChanged(); } else if ((Object)(object)__instance == (Object)(object)Player.m_localPlayer && ZRoutedRpc.instance != null) { ZRoutedRpc.instance.InvokeRoutedRPC(ZRoutedRpc.instance.GetServerPeerID(), "NotifyBedOccupancyChanged", Array.Empty<object>()); } } } } [HarmonyPatch(typeof(Player), "AttachStop")] private static class AttachStopPatch { private static void Prefix(Player __instance, out bool __state) { __state = ((Character)__instance).InBed(); } private static void Postfix(Player __instance, bool __state) { if (__state && !((Object)(object)ZNet.instance == (Object)null)) { if ((Object)(object)SleepTracker.Instance != (Object)null && ZNet.instance.IsServer()) { SleepTracker.Instance.OnBedOccupancyChanged(); } else if ((Object)(object)__instance == (Object)(object)Player.m_localPlayer && ZRoutedRpc.instance != null) { ZRoutedRpc.instance.InvokeRoutedRPC(ZRoutedRpc.instance.GetServerPeerID(), "NotifyBedOccupancyChanged", Array.Empty<object>()); } } } } } internal static class ShipPatches { [HarmonyPatch(typeof(Ship), "UpdateWaterForce")] private static class UpdateWaterForcePatch { private static bool Prefix(Ship __instance, float depth, float time) { if (SleepTracker.CurrentExtraRate <= 0.0) { return true; } bool num = ConfigRegistry.PreventBoatSleepImpactDamage != null && ConfigRegistry.PreventBoatSleepImpactDamage.Value; bool flag = ConfigRegistry.SuppressBoatImpactScreenShake != null && ConfigRegistry.SuppressBoatImpactScreenShake.Value; if (num || flag) { __instance.m_lastDepth = depth; __instance.m_lastUpdateWaterForceTime = time; return false; } return true; } } } internal static class SmelterPatches { [HarmonyPatch(typeof(Smelter), "GetDeltaTime")] private static class GetDeltaTimePatch { private static void Postfix(ref double __result) { if (ConfigRegistry.ProtectSmelterTimers != null && ConfigRegistry.ProtectSmelterTimers.Value && SleepTracker.CurrentExtraRate > 0.0) { __result /= 1.0 + SleepTracker.CurrentExtraRate; } } } } internal static class WaterVolumePatches { [HarmonyPatch(typeof(WaterVolume), "UpdateWaterTime")] private static class UpdateWaterTimePatch { private static bool Prefix(float dt) { if (ConfigRegistry.DecoupleWaterWaveSpeed == null || !ConfigRegistry.DecoupleWaterWaveSpeed.Value) { return true; } if (SleepTracker.CurrentExtraRate <= 0.0) { return true; } WaterVolume.s_wrappedDayTimeSeconds = (WaterVolume.s_wrappedDayTimeSeconds + dt) % 86400f; WaterVolume.s_waterTime += dt; return false; } } [HarmonyPatch(typeof(WaterVolume), "GetWaterSurface")] private static class GetWaterSurfacePatch { private static void Prefix(ref float waveFactor) { if (ConfigRegistry.CalmOceanDuringSleep != null && ConfigRegistry.CalmOceanDuringSleep.Value) { float num = ((!(SleepTracker.CurrentExtraRate > 0.0)) ? 1f : ((ConfigRegistry.OceanCalmMultiplier != null) ? ConfigRegistry.OceanCalmMultiplier.Value : 0.5f)); int frameCount = Time.frameCount; if (_lastCalmFrame != frameCount) { _lastCalmFrame = frameCount; _currentCalmFactor = Mathf.MoveTowards(_currentCalmFactor, num, Time.deltaTime * 0.5f); } waveFactor *= _currentCalmFactor; } } } private static float _currentCalmFactor = 1f; private static int _lastCalmFrame = -1; } internal static class ZNetPatches { [HarmonyPatch(typeof(ZNet), "UpdateNetTime")] private static class UpdateNetTime { private static void Postfix(ZNet __instance, float dt) { if (!__instance.IsServer() || __instance.GetNrOfPlayers() <= 0 || (Object)(object)SleepTracker.Instance == (Object)null || !SleepTracker.Instance.Enabled) { return; } double currentExtraRate = SleepTracker.CurrentExtraRate; if (currentExtraRate <= 0.0) { _timeSyncTimer = 0f; return; } double timeSeconds = __instance.GetTimeSeconds(); double nextMorningCapSeconds = SleepTracker.GetNextMorningCapSeconds(); if (double.IsPositiveInfinity(nextMorningCapSeconds)) { __instance.SetNetTime(timeSeconds + (double)dt * currentExtraRate); SyncNetTimeToPeers(__instance, dt); return; } if (timeSeconds >= nextMorningCapSeconds) { __instance.SetNetTime(nextMorningCapSeconds); _timeSyncTimer = 0f; return; } double num = nextMorningCapSeconds - timeSeconds; double num2 = currentExtraRate; float num3 = ((ConfigRegistry.BoostFadeRealSecondsBeforeMorning != null) ? ConfigRegistry.BoostFadeRealSecondsBeforeMorning.Value : 2f); if (num3 > 0f) { double num4 = 1.0 + currentExtraRate; double num5 = (double)num3 * num4; if (num < num5) { num2 = currentExtraRate * (num / num5); } } double num6 = Math.Min((double)dt * num2, num); __instance.SetNetTime(timeSeconds + num6); if (num6 > 0.0) { SleepTracker.TotalPartialSleepBoostSeconds += num6; SyncNetTimeToPeers(__instance, dt); } } private static void SyncNetTimeToPeers(ZNet znet, float dt) { if (znet.m_peers == null || znet.m_peers.Count == 0) { return; } _timeSyncTimer += dt; if (_timeSyncTimer < 0.25f) { return; } _timeSyncTimer = 0f; double timeSeconds = znet.GetTimeSeconds(); for (int i = 0; i < znet.m_peers.Count; i++) { ZNetPeer val = znet.m_peers[i]; if (val != null && val.IsReady() && val.m_rpc != null) { val.m_rpc.Invoke("NetTime", new object[1] { timeSeconds }); } } if (ZRoutedRpc.instance != null) { ZRoutedRpc.instance.InvokeRoutedRPC(0L, "BSB_SyncSleepBoostTotal", new object[1] { SleepTracker.TotalPartialSleepBoostSeconds }); } } } [HarmonyPatch(typeof(ZNet), "SaveWorld")] private static class SaveWorldPatch { private static void Postfix() { SleepTracker.SaveData(); } } private static float _timeSyncTimer; private const float TimeSyncInterval = 0.25f; } } namespace BetterSleepBruh.Configuration { public class ConfigRegistry : ConfigSyncBase { public static Waiting Waiter; public static ConfigEntry<bool> UseVanilleSleep; public static ConfigEntry<bool> TestingMode; public static ConfigEntry<int> TestingMaxPlayers; public static ConfigEntry<int> TestingSleepingPlayers; public static ConfigEntry<float> SleepStart; public static ConfigEntry<float> BonusMultiplier; public static ConfigEntry<float> BonusIncrementScale; public static ConfigEntry<float> BoostFadeRealSecondsBeforeMorning; public static ConfigEntry<bool> ProtectCookingTimers; public static ConfigEntry<bool> ProtectSmelterTimers; public static ConfigEntry<bool> ProtectCropTimers; public static ConfigEntry<bool> ProtectMeadTimers; public static ConfigEntry<bool> ProtectPickableTimers; public static ConfigEntry<bool> DecoupleWaterWaveSpeed; public static ConfigEntry<bool> CalmOceanDuringSleep; public static ConfigEntry<float> OceanCalmMultiplier; public static ConfigEntry<bool> PreventBoatSleepImpactDamage; public static ConfigEntry<bool> SuppressBoatImpactScreenShake; public static bool IsPlayerCountTestingActive { get { if (TestingMode != null) { return TestingMode.Value; } return false; } } public ConfigRegistry(IPluginInfo mod, bool enableLockedConfigs = false) : base(mod, enableLockedConfigs) { Waiter = new Waiting(); InitializeConfigurationSettings(); } public sealed override void InitializeConfigurationSettings() { //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Expected O, but got Unknown //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Expected O, but got Unknown //IL_0075: Unknown result type (might be due to invalid IL or missing references) //IL_007a: Unknown result type (might be due to invalid IL or missing references) //IL_0086: Unknown result type (might be due to invalid IL or missing references) //IL_008e: Expected O, but got Unknown //IL_008e: Unknown result type (might be due to invalid IL or missing references) //IL_009e: Expected O, but got Unknown //IL_00c9: Unknown result type (might be due to invalid IL or missing references) //IL_00ce: Unknown result type (might be due to invalid IL or missing references) //IL_00da: Unknown result type (might be due to invalid IL or missing references) //IL_00e2: Expected O, but got Unknown //IL_00e2: Unknown result type (might be due to invalid IL or missing references) //IL_00f2: Expected O, but got Unknown //IL_011d: Unknown result type (might be due to invalid IL or missing references) //IL_0122: Unknown result type (might be due to invalid IL or missing references) //IL_012e: Unknown result type (might be due to invalid IL or missing references) //IL_0136: Expected O, but got Unknown //IL_0136: Unknown result type (might be due to invalid IL or missing references) //IL_0146: Expected O, but got Unknown //IL_0171: Unknown result type (might be due to invalid IL or missing references) //IL_0176: Unknown result type (might be due to invalid IL or missing references) //IL_0182: Unknown result type (might be due to invalid IL or missing references) //IL_018a: Expected O, but got Unknown //IL_018a: Unknown result type (might be due to invalid IL or missing references) //IL_019a: Expected O, but got Unknown //IL_01b3: Unknown result type (might be due to invalid IL or missing references) //IL_01b8: Unknown result type (might be due to invalid IL or missing references) //IL_01c4: Unknown result type (might be due to invalid IL or missing references) //IL_01cc: Expected O, but got Unknown //IL_01cc: Unknown result type (might be due to invalid IL or missing references) //IL_01dc: Expected O, but got Unknown //IL_01fd: Unknown result type (might be due to invalid IL or missing references) //IL_0202: Unknown result type (might be due to invalid IL or missing references) //IL_020e: Unknown result type (might be due to invalid IL or missing references) //IL_0216: Expected O, but got Unknown //IL_0216: Unknown result type (might be due to invalid IL or missing references) //IL_0226: Expected O, but got Unknown //IL_0246: Unknown result type (might be due to invalid IL or missing references) //IL_024b: Unknown result type (might be due to invalid IL or missing references) //IL_0257: Unknown result type (might be due to invalid IL or missing references) //IL_025f: Expected O, but got Unknown //IL_025f: Unknown result type (might be due to invalid IL or missing references) //IL_026f: Expected O, but got Unknown //IL_0288: Unknown result type (might be due to invalid IL or missing references) //IL_028d: Unknown result type (might be due to invalid IL or missing references) //IL_0299: Unknown result type (might be due to invalid IL or missing references) //IL_02a1: Expected O, but got Unknown //IL_02a1: Unknown result type (might be due to invalid IL or missing references) //IL_02b1: Expected O, but got Unknown //IL_02ca: Unknown result type (might be due to invalid IL or missing references) //IL_02cf: Unknown result type (might be due to invalid IL or missing references) //IL_02db: Unknown result type (might be due to invalid IL or missing references) //IL_02e3: Expected O, but got Unknown //IL_02e3: Unknown result type (might be due to invalid IL or missing references) //IL_02f3: Expected O, but got Unknown //IL_030c: Unknown result type (might be due to invalid IL or missing references) //IL_0311: Unknown result type (might be due to invalid IL or missing references) //IL_031d: Unknown result type (might be due to invalid IL or missing references) //IL_0325: Expected O, but got Unknown //IL_0325: Unknown result type (might be due to invalid IL or missing references) //IL_0335: Expected O, but got Unknown //IL_034e: Unknown result type (might be due to invalid IL or missing references) //IL_0353: Unknown result type (might be due to invalid IL or missing references) //IL_035f: Unknown result type (might be due to invalid IL or missing references) //IL_0367: Expected O, but got Unknown //IL_0367: Unknown result type (might be due to invalid IL or missing references) //IL_0377: Expected O, but got Unknown //IL_0390: Unknown result type (might be due to invalid IL or missing references) //IL_0395: Unknown result type (might be due to invalid IL or missing references) //IL_03a1: Unknown result type (might be due to invalid IL or missing references) //IL_03a9: Expected O, but got Unknown //IL_03a9: Unknown result type (might be due to invalid IL or missing references) //IL_03b9: Expected O, but got Unknown //IL_03d2: Unknown result type (might be due to invalid IL or missing references) //IL_03d7: Unknown result type (might be due to invalid IL or missing references) //IL_03e3: Unknown result type (might be due to invalid IL or missing references) //IL_03eb: Expected O, but got Unknown //IL_03eb: Unknown result type (might be due to invalid IL or missing references) //IL_03fb: Expected O, but got Unknown //IL_0414: Unknown result type (might be due to invalid IL or missing references) //IL_0419: Unknown result type (might be due to invalid IL or missing references) //IL_0425: Unknown result type (might be due to invalid IL or missing references) //IL_042d: Expected O, but got Unknown //IL_042d: Unknown result type (might be due to invalid IL or missing references) //IL_043d: Expected O, but got Unknown //IL_0468: Unknown result type (might be due to invalid IL or missing references) //IL_046d: Unknown result type (might be due to invalid IL or missing references) //IL_0479: Unknown result type (might be due to invalid IL or missing references) //IL_0481: Expected O, but got Unknown //IL_0481: Unknown result type (might be due to invalid IL or missing references) //IL_0491: Expected O, but got Unknown //IL_04aa: Unknown result type (might be due to invalid IL or missing references) //IL_04af: Unknown result type (might be due to invalid IL or missing references) //IL_04bb: Unknown result type (might be due to invalid IL or missing references) //IL_04c3: Expected O, but got Unknown //IL_04c3: Unknown result type (might be due to invalid IL or missing references) //IL_04d3: Expected O, but got Unknown //IL_04ec: Unknown result type (might be due to invalid IL or missing references) //IL_04f1: Unknown result type (might be due to invalid IL or missing references) //IL_04fd: Unknown result type (might be due to invalid IL or missing references) //IL_0505: Expected O, but got Unknown //IL_0505: Unknown result type (might be due to invalid IL or missing references) //IL_0515: Expected O, but got Unknown if (ConfigSyncBase._config != null) { ConfigSyncBase.SyncedConfig("Server Settings", "Use Vanilla Sleep Start", value: false, new ConfigDescription("Default is false/disabled; Set to True/Enabled to resume Vanilla Sleep Start", (AcceptableValueBase)null, new object[1] { (object)new ConfigurationManagerAttributes { Order = 1, IsAdminOnly = true } }), ref UseVanilleSleep); ConfigSyncBase.SyncedConfig("Server Settings", "Sleep Start", 0.5f, new ConfigDescription("Day Fraction to allow sleep to begin. Default is 0.5, or Noon. Only applies when Vanilla Sleep Start is disabled/false.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 0.99f), new object[1] { (object)new ConfigurationManagerAttributes { Order = 2, IsAdminOnly = true } }), ref SleepStart); ConfigSyncBase.SyncedConfig("Server Settings", "Bonus Multiplier", 0.6f, new ConfigDescription("Scales the bonus increment (added on top of normal time): extra rate = this × sleep fraction × 10. At 1.0 and all-but-one in bed, extra rate is 10 (time advances 11× vs vanilla dt alone).", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1f), new object[1] { (object)new ConfigurationManagerAttributes { Order = 3, IsAdminOnly = true } }), ref BonusMultiplier); ConfigSyncBase.SyncedConfig("Server Settings", "Bonus Increment Scale", 20f, new ConfigDescription("Scales the bonus increment (added on top of normal time): extra rate = this × sleep fraction × 10. At 1.0 and all-but-one in bed, extra rate is 10 (time advances 11× vs vanilla dt alone).", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 30f), new object[1] { (object)new ConfigurationManagerAttributes { Order = 4, IsAdminOnly = true } }), ref BonusIncrementScale); ConfigSyncBase.SyncedConfig("Server Settings", "Boost Fade (Real Seconds)", 3f, new ConfigDescription("Partial boost linearly ramps to zero over this many real-time seconds before the next morning. Uses net rate (1 + extra) so higher boost = longer game-time taper. 0 = no taper (hard cut only at morning).", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 30f), new object[1] { (object)new ConfigurationManagerAttributes { Order = 5, IsAdminOnly = true } }), ref BoostFadeRealSecondsBeforeMorning); ConfigSyncBase.SyncedConfig("Testing Mode", "Enable Testing Mode", value: false, new ConfigDescription("When enabled, Fake Total Players and Simulate Players In Bed are added on top of real player counts for boost math and HUD (server + RPC).", (AcceptableValueBase)null, new object[1] { (object)new ConfigurationManagerAttributes { Order = 4, IsAdminOnly = true } }), ref TestingMode); ConfigSyncBase.SyncedConfig("Testing Mode", "Fake Total Players", 10, new ConfigDescription("Count of fake connected players to add to the server while Testing Mode is on.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 80), new object[1] { (object)new ConfigurationManagerAttributes { Order = 5, IsAdminOnly = true } }), ref TestingMaxPlayers); ConfigSyncBase.SyncedConfig("Testing Mode", "Simulate Players In Bed", 1, new ConfigDescription("Count of fake players in bed to add while Testing Mode is on (clamped to Fake Total Players).", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 80), new object[1] { (object)new ConfigurationManagerAttributes { Order = 6, IsAdminOnly = true } }), ref TestingSleepingPlayers); ConfigSyncBase.SyncedConfig("Station Timers", "Protect Cooking Timers", value: true, new ConfigDescription("If enabled, food on cooking stations and in ovens will not cook or burn faster during partial sleep.", (AcceptableValueBase)null, new object[1] { (object)new ConfigurationManagerAttributes { Order = 1, IsAdminOnly = true } }), ref ProtectCookingTimers); ConfigSyncBase.SyncedConfig("Station Timers", "Protect Smelter Timers", value: true, new ConfigDescription("If enabled, smelters, blast furnaces, and kilns process at normal speed during partial sleep.", (AcceptableValueBase)null, new object[1] { (object)new ConfigurationManagerAttributes { Order = 2, IsAdminOnly = true } }), ref ProtectSmelterTimers); ConfigSyncBase.SyncedConfig("Station Timers", "Protect Crop Timers", value: true, new ConfigDescription("If enabled, crops and planted saplings grow at normal speed during partial sleep.", (AcceptableValueBase)null, new object[1] { (object)new ConfigurationManagerAttributes { Order = 3, IsAdminOnly = true } }), ref ProtectCropTimers); ConfigSyncBase.SyncedConfig("Station Timers", "Protect Mead Timers", value: true, new ConfigDescription("If enabled, fermenters and mead barrels ferment at normal speed during partial sleep.", (AcceptableValueBase)null, new object[1] { (object)new ConfigurationManagerAttributes { Order = 4, IsAdminOnly = true } }), ref ProtectMeadTimers); ConfigSyncBase.SyncedConfig("Station Timers", "Protect Pickable Timers", value: true, new ConfigDescription("If enabled, berry bushes and wild pickables respawn at normal speed during partial sleep.", (AcceptableValueBase)null, new object[1] { (object)new ConfigurationManagerAttributes { Order = 5, IsAdminOnly = true } }), ref ProtectPickableTimers); ConfigSyncBase.SyncedConfig("Ocean & Boat Physics", "Decouple Water Wave Speed", value: true, new ConfigDescription("If enabled, ocean wave simulation moves at normal real-time speed while time is accelerated, preventing violent wave physics.", (AcceptableValueBase)null, new object[1] { (object)new ConfigurationManagerAttributes { Order = 1, IsAdminOnly = true } }), ref DecoupleWaterWaveSpeed); ConfigSyncBase.SyncedConfig("Ocean & Boat Physics", "Calm Ocean During Sleep", value: true, new ConfigDescription("If enabled, ocean waves are calmed and smoothed while night is accelerated.", (AcceptableValueBase)null, new object[1] { (object)new ConfigurationManagerAttributes { Order = 2, IsAdminOnly = true } }), ref CalmOceanDuringSleep); ConfigSyncBase.SyncedConfig("Ocean & Boat Physics", "Ocean Calm Multiplier", 0.5f, new ConfigDescription("Wave height multiplier applied when ocean calming is active (0.0 = completely flat, 1.0 = normal storm waves).", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1f), new object[1] { (object)new ConfigurationManagerAttributes { Order = 3, IsAdminOnly = true } }), ref OceanCalmMultiplier); ConfigSyncBase.SyncedConfig("Ocean & Boat Physics", "Prevent Boat Sleep Impact Damage", value: true, new ConfigDescription("Prevents boats from taking spurious water impact damage from waves during accelerated sleep.", (AcceptableValueBase)null, new object[1] { (object)new ConfigurationManagerAttributes { Order = 4, IsAdminOnly = true } }), ref PreventBoatSleepImpactDamage); ConfigSyncBase.SyncedConfig("Ocean & Boat Physics", "Suppress Boat Impact Screen Shake", value: true, new ConfigDescription("Prevents camera screen shake caused by high-velocity wave wakes during accelerated sleep.", (AcceptableValueBase)null, new object[1] { (object)new ConfigurationManagerAttributes { Order = 5, IsAdminOnly = true } }), ref SuppressBoatImpactScreenShake); } } public static int GetEffectiveTotalPlayersForMod(int realTotalPlayers) { int num = Math.Max(0, realTotalPlayers); if (TestingMode != null && TestingMode.Value && TestingMaxPlayers != null) { num += Math.Max(0, TestingMaxPlayers.Value); } return num; } public static int GetEffectiveSleepingPlayersForMod(int realSleepingCount, int effectivePlayerCount) { int num = Math.Max(0, realSleepingCount); if (TestingMode != null && TestingMode.Value && TestingSleepingPlayers != null) { int max = ((TestingMaxPlayers != null) ? Math.Max(0, TestingMaxPlayers.Value) : 0); int num2 = ClampInt(TestingSleepingPlayers.Value, 0, max); num += num2; } return ClampInt(num, 0, effectivePlayerCount); } private static int ClampInt(int value, int min, int max) { if (value < min) { return min; } if (value <= max) { return value; } return max; } } public class Waiting { public event EventHandler StatusChanged; public void ConfigurationComplete(bool configDone) { if (configDone) { this.StatusChanged?.Invoke(this, EventArgs.Empty); } } } } namespace BetterSleepBruh.Components { public sealed class SleepHudView : MonoBehaviour { private const int MaxPillowSegments = 5; private RectTransform _segmentsRoot; private Image[] _segments = Array.Empty<Image>(); private TextMeshProUGUI _boostTmp; private TextMeshProUGUI _ratioTmp; private TMP_FontAsset _hudFont; private int _lastTotal = -1; private int _lastRefreshedTotal = -1; private int _lastRefreshedSleeping = -1; private bool _compactLayout; private GameObject _bedIconGo; private GameObject _arrowChaserGo; private Image[] _arrowImages; private bool _isBoosting; private float _boostFraction; private float _arrowTimer; private const float ArrowMinStepDuration = 0.08f; private const float ArrowMaxStepDuration = 0.35f; private static readonly Color BgMidnight = new Color(0f, 0f, 0f, 0.39f); private static readonly Color PillowAwakeTint = new Color(0.32f, 0.32f, 0.34f, 1f); private static readonly Color ArrowDimTint = new Color(0.35f, 0.28f, 0.2f, 0.45f); private static readonly Color32 MoonBeige = new Color32((byte)235, (byte)225, (byte)190, byte.MaxValue); private static readonly Color32 BoostYellow = new Color32(byte.MaxValue, (byte)183, (byte)91, byte.MaxValue); private const float StripHeightPx = 40f; private bool _rpcsRegistered; private static readonly string[] HudFontResourcePaths = new string[2] { "Fonts & Materials/LiberationSans SDF", "Fonts & Materials/LiberationSans SDF TMP" }; private static Sprite _whiteSprite; private static Sprite _moonCrescentSprite; private static Sprite _bedFilledSprite; private static Sprite _resolvedMoonIcon; private static Sprite _resolvedBedIcon; private static Sprite _resolvedPillowSprite; private const string EmbeddedMoonName = "sleephud_moon.png"; private const string EmbeddedBedName = "sleephud_bed.png"; private const string EmbeddedPillowName = "sleephud_pillow.png"; private static Sprite _chevronSprite; private void Awake() { BetterSleepBruh.Log.Debug("SleepHudView Is Awoken"); RegisterRpcs(); } private void Start() { BetterSleepBruh.Log.Debug("[CLIENT] SleepHudView Is Starting"); RegisterRpcs(); RequestOrSyncInitialState(); } private void RegisterRpcs() { if (!_rpcsRegistered && ZRoutedRpc.instance != null) { BetterSleepBruh.Log.Debug("[CLIENT] Registering SleepHudView RPCs"); ZRoutedRpc.instance.Register<int, int, double>("RPC_SleepingPlayerInfo", (Action<long, int, int, double>)RPC_SleepingPlayerInfo); ZRoutedRpc.instance.Register("RPC_StartSleep", (Action<long>)RPC_StartSleep); ZRoutedRpc.instance.Register("RPC_StopSleep", (Action<long>)RPC_StopSleep); ZRoutedRpc.instance.Register<double>("BSB_SyncSleepBoostTotal", (Action<long, double>)RPC_SyncSleepBoostTotal); _rpcsRegistered = true; } } private void OnEnable() { RequestOrSyncInitialState(); } private void OnDisable() { _isBoosting = false; _arrowTimer = 0f; } private void Update() { //IL_0060: Unknown result type (might be due to invalid IL or missing references) //IL_0067: Unknown result type (might be due to invalid IL or missing references) //IL_006c: Unknown result type (might be due to invalid IL or missing references) //IL_0086: Unknown result type (might be due to invalid IL or missing references) //IL_008d: Unknown result type (might be due to invalid IL or missing references) //IL_0092: Unknown result type (might be due to invalid IL or missing references) //IL_00af: Unknown result type (might be due to invalid IL or missing references) //IL_00b4: Unknown result type (might be due to invalid IL or missing references) //IL_00a8: Unknown result type (might be due to invalid IL or missing references) if (_isBoosting && _arrowImages != null && _arrowImages.Length >= 3) { float num = Mathf.Lerp(0.35f, 0.08f, _boostFraction); _arrowTimer += Time.deltaTime; int num2 = (int)(_arrowTimer / num) % 4; ((Graphic)_arrowImages[0]).color = ((num2 >= 0 && num2 <= 2) ? Color32.op_Implicit(BoostYellow) : ArrowDimTint); ((Graphic)_arrowImages[1]).color = ((num2 >= 1 && num2 <= 2) ? Color32.op_Implicit(BoostYellow) : ArrowDimTint); ((Graphic)_arrowImages[2]).color = ((num2 == 2) ? Color32.op_Implicit(BoostYellow) : ArrowDimTint); } } private void RequestOrSyncInitialState() { if ((Object)(object)SleepTracker.Instance != (Object)null) { if (SleepTracker.Instance.CanSleep) { ((Component)this).gameObject.SetActive(true); Refresh(SleepTracker.CurrentPlayerCount, SleepTracker.CurrentSleepingCount); } else { ((Component)this).gameObject.SetActive(false); } } else if (ZRoutedRpc.instance != null) { ZRoutedRpc.instance.InvokeRoutedRPC(ZRoutedRpc.instance.GetServerPeerID(), "RPC_RequestSleepingPlayerInfo", Array.Empty<object>()); } } private void RPC_SyncSleepBoostTotal(long sender, double totalBoost) { SleepTracker.TotalPartialSleepBoostSeconds = totalBoost; } private void RPC_SleepingPlayerInfo(long sender, int totalPlayers, int playersSleeping, double sleepBoost) { SleepTracker.CurrentExtraRate = sleepBoost; if (!((Object)(object)Player.m_localPlayer == (Object)null)) { if (ConfigRegistry.IsPlayerCountTestingActive) { BetterSleepBruh.Log.Debug($"[BetterSleepBruh TESTING] HUD total={totalPlayers} sleeping={playersSleeping} extraRate={sleepBoost}"); } else { BetterSleepBruh.Log.Debug($"[CLIENT] Total Players: {totalPlayers}"); BetterSleepBruh.Log.Debug($"[CLIENT] Players Sleeping: {playersSleeping}"); BetterSleepBruh.Log.Debug($"[CLIENT] Sleep Boost (extra rate × dt): {sleepBoost}"); } if (!((Component)this).gameObject.activeSelf && ((Object)(object)EnvMan.instance == (Object)null || EnvManPatches.IsInSleepWindow(EnvMan.instance))) { ((Component)this).gameObject.SetActive(true); } Refresh(totalPlayers, playersSleeping); } } private void RPC_StartSleep(long sender) { if (!((Object)(object)Player.m_localPlayer == (Object)null)) { BetterSleepBruh.Log.Debug("[CLIENT] Start Sleep"); ((Component)this).gameObject.SetActive(true); } } private void RPC_StopSleep(long sender) { SleepTracker.CurrentExtraRate = 0.0; if ((Object)(object)Player.m_localPlayer == (Object)null) { return; } BetterSleepBruh.Log.Debug("[CLIENT] Stop Sleep"); _isBoosting = false; if ((Object)(object)_arrowChaserGo != (Object)null && _arrowChaserGo.activeSelf) { _arrowChaserGo.SetActive(false); } if ((Object)(object)_bedIconGo != (Object)null && !_bedIconGo.activeSelf) { _bedIconGo.SetActive(true); } if ((Object)(object)EnvMan.instance == (Object)null || !EnvMan.instance.IsTimeSkipping()) { Player localPlayer = Player.m_localPlayer; if ((Object)(object)localPlayer != (Object)null) { localPlayer.SetSleeping(false); if (((Character)localPlayer).InBed()) { ((Character)localPlayer).AttachStop(); } localPlayer.m_wakeupTime = (((Object)(object)ZNet.instance != (Object)null) ? ZNet.instance.GetTimeSeconds() : 0.0); } } ((Component)this).gameObject.SetActive(false); } public static SleepHudView TryCreate(Transform mapGeometryTransform, float gapBelowMinimap = 1f) { //IL_007b: Unknown result type (might be due to invalid IL or missing references) //IL_0082: Expected O, but got Unknown //IL_0098: Unknown result type (might be due to invalid IL or missing references) //IL_00ad: Unknown result type (might be due to invalid IL or missing references) //IL_00c2: Unknown result type (might be due to invalid IL or missing references) //IL_00d7: Unknown result type (might be due to invalid IL or missing references) //IL_00e8: Unknown result type (might be due to invalid IL or missing references) //IL_00f9: Unknown result type (might be due to invalid IL or missing references) //IL_0119: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)mapGeometryTransform == (Object)null) { return null; } RectTransform val = (RectTransform)(object)((mapGeometryTransform is RectTransform) ? mapGeometryTransform : null); if ((Object)(object)val == (Object)null) { return null; } Transform val2 = ((Transform)val).Find("BetterSleepBruh_SleepHud"); if ((Object)(object)val2 != (Object)null) { Object.Destroy((Object)(object)((Component)val2).gameObject); } Sprite sprite = BaseWhiteSprite(); float num = 40f; GameObject val3 = new GameObject("BetterSleepBruh_SleepHud", new Type[3] { typeof(RectTransform), typeof(Image), typeof(SleepHudView) }); RectTransform component = val3.GetComponent<RectTransform>(); ((Transform)component).SetParent((Transform)(object)val, false); ((Transform)component).SetAsLastSibling(); ((Transform)component).localScale = Vector3.one; component.anchorMin = new Vector2(0f, 0f); component.anchorMax = new Vector2(1f, 0f); component.pivot = new Vector2(0.5f, 1f); component.sizeDelta = new Vector2(0f, num); component.anchoredPosition = new Vector2(0f, 0f - gapBelowMinimap); Image component2 = val3.GetComponent<Image>(); component2.sprite = sprite; component2.type = (Type)0; ((Graphic)component2).color = BgMidnight; ((Graphic)component2).raycastTarget = false; val3.AddComponent<RectMask2D>(); TMP_FontAsset val4 = ResolveTmpFont((Transform)(object)val); if ((Object)(object)val4 == (Object)null) { BetterSleepBruh.Log.Warning("[SleepHud] No TMP font; not creating sleep HUD."); Object.Destroy((Object)(object)val3); return null; } SleepHudView component3 = val3.GetComponent<SleepHudView>(); component3.BuildContent(val3.GetComponent<RectTransform>(), val4); return component3; } public void Refresh(int totalPlayers, int playersSleeping) { //IL_004f: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_00d1: Unknown result type (might be due to invalid IL or missing references) //IL_00ca: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_segmentsRoot == (Object)null) { return; } totalPlayers = Mathf.Max(0, totalPlayers); playersSleeping = Mathf.Clamp(playersSleeping, 0, totalPlayers); EnsureSegments(totalPlayers); if (_compactLayout) { if (_segments.Length == 1) { ((Graphic)_segments[0]).color = ((playersSleeping > 0) ? Color.white : PillowAwakeTint); } if ((Object)(object)_ratioTmp != (Object)null) { string text = $"{playersSleeping}/{totalPlayers}"; if (((TMP_Text)_ratioTmp).text != text) { ((TMP_Text)_ratioTmp).text = text; } } } else if (totalPlayers != _lastRefreshedTotal || playersSleeping != _lastRefreshedSleeping) { for (int i = 0; i < _segments.Length; i++) { ((Graphic)_segments[i]).color = ((i < playersSleeping) ? Color.white : PillowAwakeTint); } } _lastRefreshedTotal = totalPlayers; _lastRefreshedSleeping = playersSleeping; double bonusLabelPercent = GetBonusLabelPercent(totalPlayers, playersSleeping); double num = ((ConfigRegistry.BonusMultiplier != null) ? ((double)ConfigRegistry.BonusMultiplier.Value * 100.0) : 60.0); bool flag = (_isBoosting = totalPlayers > 1 && playersSleeping > 0 && playersSleeping < totalPlayers && bonusLabelPercent > 0.0001); _boostFraction = ((flag && num > 0.0) ? Mathf.Clamp01((float)(bonusLabelPercent / num)) : 0f); if ((Object)(object)_bedIconGo != (Object)null && (Object)(object)_arrowChaserGo != (Object)null) { if (flag) { if (!_arrowChaserGo.activeSelf) { _arrowChaserGo.SetActive(true); } if (_bedIconGo.activeSelf) { _bedIconGo.SetActive(false); } } else { if (_arrowChaserGo.activeSelf) { _arrowChaserGo.SetActive(false); } if (!_bedIconGo.activeSelf) { _bedIconGo.SetActive(true); } } } if (!((Object)(object)_boostTmp == (Object)null)) { string text2 = ((bonusLabelPercent <= 0.0001) ? "+0%" : $"+{bonusLabelPercent:F0}%"); if (((TMP_Text)_boostTmp).text != text2) { ((TMP_Text)_boostTmp).text = text2; } } } private static double GetBonusLabelPercent(int playerCount, int playersSleeping) { if (playerCount <= 1 || playersSleeping <= 0) { return 0.0; } double num = (double)ConfigRegistry.BonusMultiplier.Value * 100.0; if (playersSleeping >= playerCount - 1) { return num; } return (double)playersSleeping / (double)playerCount * num; } private void BuildContent(RectTransform rootRt, TMP_FontAsset font) { //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Expected O, but got Unknown //IL_0055: Unknown result type (might be due to invalid IL or missing references) //IL_005f: Expected O, but got Unknown //IL_009c: Unknown result type (might be due to invalid IL or missing references) //IL_00df: Unknown result type (might be due to invalid IL or missing references) //IL_00e4: Unknown result type (might be due to invalid IL or missing references) //IL_00ea: Unknown result type (might be due to invalid IL or missing references) //IL_00f0: Expected O, but got Unknown //IL_00f8: Unknown result type (might be due to invalid IL or missing references) //IL_0125: Unknown result type (might be due to invalid IL or missing references) //IL_0135: Unknown result type (might be due to invalid IL or missing references) //IL_014b: Unknown result type (might be due to invalid IL or missing references) //IL_0155: Expected O, but got Unknown //IL_01b5: Unknown result type (might be due to invalid IL or missing references) //IL_01ba: Unknown result type (might be due to invalid IL or missing references) _hudFont = font; GameObject val = new GameObject("Row", new Type[2] { typeof(RectTransform), typeof(HorizontalLayoutGroup) }); RectTransform val2 = (RectTransform)val.transform; ((Transform)val2).SetParent((Transform)(object)rootRt, false); StretchFull(val2); HorizontalLayoutGroup component = val.GetComponent<HorizontalLayoutGroup>(); ((LayoutGroup)component).padding = new RectOffset(4, 4, 3, 3); ((HorizontalOrVerticalLayoutGroup)component).spacing = 4f; ((LayoutGroup)component).childAlignment = (TextAnchor)3; ((HorizontalOrVerticalLayoutGroup)component).childControlWidth = true; ((HorizontalOrVerticalLayoutGroup)component).childControlHeight = true; ((HorizontalOrVerticalLayoutGroup)component).childForceExpandWidth = false; ((HorizontalOrVerticalLayoutGroup)component).childForceExpandHeight = true; CreateIconInRow((Transform)(object)val2, "Moon", GetMoonIconSprite(), 28f, Color.white); CreateBedSlot((Transform)(object)val2); GameObject val3 = new GameObject("BarHost", new Type[3] { typeof(RectTransform), typeof(HorizontalLayoutGroup), typeof(Image) }); RectTransform val4 = (RectTransform)val3.transform; ((Transform)val4).SetParent((Transform)(object)val2, false); Image component2 = val3.GetComponent<Image>(); component2.sprite = BaseWhiteSprite(); component2.type = (Type)0; ((Graphic)component2).color = new Color(0f, 0f, 0f, 0.25f); ((Graphic)component2).raycastTarget = false; HorizontalLayoutGroup component3 = val3.GetComponent<HorizontalLayoutGroup>(); ((HorizontalOrVerticalLayoutGroup)component3).spacing = 3f; ((LayoutGroup)component3).padding = new RectOffset(4, 4, 4, 4); ((LayoutGroup)component3).childAlignment = (TextAnchor)4; ((HorizontalOrVerticalLayoutGroup)component3).childControlWidth = true; ((HorizontalOrVerticalLayoutGroup)component3).childControlHeight = true; ((HorizontalOrVerticalLayoutGroup)component3).childForceExpandWidth = true; ((HorizontalOrVerticalLayoutGroup)component3).childForceExpandHeight = true; LayoutElement obj = val3.AddComponent<LayoutElement>(); obj.flexibleWidth = 1f; obj.minWidth = 48f; obj.preferredHeight = 26f; _segmentsRoot = val4; _boostTmp = CreateTmpInRow((Transform)(object)val2, "Boost", font, 40f, 14f, Color32.op_Implicit(BoostYellow), "0%", (TextAlignmentOptions)4100); SleepTracker.GetSleepOccupancyCounts(out var playerCount, out var playersSleeping); if (playerCount <= 0) { playerCount = 1; } Refresh(playerCount, playersSleeping); } private void EnsureSegments(int total) { //IL_00cc: Unknown result type (might be due to invalid IL or missing references) //IL_00d3: Expected O, but got Unknown //IL_0148: Unknown result type (might be due to invalid IL or missing references) //IL_014d: Unknown result type (might be due to invalid IL or missing references) //IL_0153: Unknown result type (might be due to invalid IL or missing references) //IL_0158: Unknown result type (might be due to invalid IL or missing references) //IL_016b: Expected O, but got Unknown //IL_018c: Unknown result type (might be due to invalid IL or missing references) //IL_01d4: Unknown result type (might be due to invalid IL or missing references) //IL_01db: Expected O, but got Unknown //IL_0256: Unknown result type (might be due to invalid IL or missing references) //IL_025d: Expected O, but got Unknown //IL_0264: Unknown result type (might be due to invalid IL or missing references) //IL_0269: Unknown result type (might be due to invalid IL or missing references) //IL_027c: Expected O, but got Unknown //IL_02b0: Unknown result type (might be due to invalid IL or missing references) //IL_02b5: Unknown result type (might be due to invalid IL or missing references) //IL_0309: Unknown result type (might be due to invalid IL or missing references) //IL_0366: Unknown result type (might be due to invalid IL or missing references) //IL_036b: Unknown result type (might be due to invalid IL or missing references) //IL_037d: Unknown result type (might be due to invalid IL or missing references) //IL_039f: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_segmentsRoot == (Object)null) { return; } bool flag = total > 5; int num = (flag ? 1 : total); if (total == _lastTotal && _compactLayout == flag && _segments.Length == num) { return; } _lastTotal = total; _compactLayout = flag; _ratioTmp = null; for (int num2 = ((Transform)_segmentsRoot).childCount - 1; num2 >= 0; num2--) { Transform child = ((Transform)_segmentsRoot).GetChild(num2); if ((Object)(object)child != (Object)null) { Object.Destroy((Object)(object)((Component)child).gameObject); } } if (total <= 0) { _segments = Array.Empty<Image>(); return; } Sprite pillowSegmentSprite = GetPillowSegmentSprite(); if (flag) { GameObject val = new GameObject("PillowCompact", new Type[2] { typeof(RectTransform), typeof(LayoutElement) }); val.transform.SetParent((Transform)(object)_segmentsRoot, false); LayoutElement component = val.GetComponent<LayoutElement>(); component.flexibleWidth = 0f; component.minWidth = 28f; component.preferredWidth = 40f; component.preferredHeight = 22f; component.flexibleHeight = 1f; GameObject val2 = new GameObject("Seg_0", new Type[2] { typeof(RectTransform), typeof(Image) }); RectTransform val3 = (RectTransform)val2.transform; ((Transform)val3).SetParent(val.transform, false); StretchFull(val3); Image component2 = val2.GetComponent<Image>(); component2.sprite = pillowSegmentSprite; component2.type = (Type)0; component2.preserveAspect = true; ((Graphic)component2).color = PillowAwakeTint; ((Graphic)component2).raycastTarget = false; _segments = (Image[])(object)new Image[1] { component2 }; GameObject val4 = new GameObject("Ratio", new Type[2] { typeof(RectTransform), typeof(LayoutElement) }); val4.transform.SetParent((Transform)(object)_segmentsRoot, false); LayoutElement component3 = val4.GetComponent<LayoutElement>(); component3.flexibleWidth = 1f; component3.minWidth = 52f; component3.preferredHeight = 22f; component3.flexibleHeight = 1f; if ((Object)(object)_hudFont != (Object)null) { GameObject val5 = new GameObject("Label", new Type[2] { typeof(RectTransform), typeof(TextMeshProUGUI) }); RectTransform val6 = (RectTransform)val5.transform; ((Transform)val6).SetParent(val4.transform, false); StretchFull(val6); _ratioTmp = val5.GetComponent<TextMeshProUGUI>(); ApplyFont(_ratioTmp, _hudFont); ((TMP_Text)_ratioTmp).fontSize = 14f; ((Graphic)_ratioTmp).color = Color32.op_Implicit(BoostYellow); ((TMP_Text)_ratioTmp).text = "0/0"; ((TMP_Text)_ratioTmp).alignment = (TextAlignmentOptions)4097; ((TMP_Text)_ratioTmp).textWrappingMode = (TextWrappingModes)0; ((TMP_Text)_ratioTmp).overflowMode = (TextOverflowModes)0; ((Graphic)_ratioTmp).raycastTarget = false; ((TMP_Text)_ratioTmp).margin = Vector4.zero; } } else { _segments = (Image[])(object)new Image[total]; for (int i = 0; i < total; i++) { GameObject val7 = new GameObject($"Seg_{i}", new Type[3] { typeof(RectTransform), typeof(Image), typeof(LayoutElement) }); val7.transform.SetParent((Transform)(object)_segmentsRoot, false); Image component4 = val7.GetComponent<Image>(); component4.sprite = pillowSegmentSprite; component4.type = (Type)0; component4.preserveAspect = true; ((Graphic)component4).color = PillowAwakeTint; ((Graphic)component4).raycastTarget = false; LayoutElement component5 = val7.GetComponent<LayoutElement>(); component5.flexibleWidth = 1f; component5.preferredHeight = 22f; component5.minWidth = 8f; _segments[i] = component4; } } } private static void StretchFull(RectTransform rt) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Unknown result type (might be due to invalid IL or missing references) rt.anchorMin = Vector2.zero; rt.anchorMax = Vector2.one; rt.offsetMin = Vector2.zero; rt.offsetMax = Vector2.zero; } private void CreateBedSlot(Transform rowParent) { //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Expected O, but got Unknown //IL_00a2: Unknown result type (might be due to invalid IL or missing references) //IL_00ac: Expected O, but got Unknown //IL_00b7: Unknown result type (might be due to invalid IL or missing references) //IL_00bc: Unknown result type (might be due to invalid IL or missing references) //IL_00c9: Expected O, but got Unknown //IL_00e7: Unknown result type (might be due to invalid IL or missing references) //IL_0124: Unknown result type (might be due to invalid IL or missing references) //IL_012e: Expected O, but got Unknown //IL_0139: Unknown result type (might be due to invalid IL or missing references) //IL_013f: Expected O, but got Unknown //IL_015d: Unknown result type (might be due to invalid IL or missing references) //IL_0167: Expected O, but got Unknown //IL_01df: Unknown result type (might be due to invalid IL or missing references) //IL_01e4: Unknown result type (might be due to invalid IL or missing references) //IL_01ea: Unknown result type (might be due to invalid IL or missing references) //IL_01ef: Unknown result type (might be due to invalid IL or missing references) //IL_0201: Unknown result type (might be due to invalid IL or missing references) //IL_0224: Unknown result type (might be due to invalid IL or missing references) float num = 28f; GameObject val = new GameObject("BedSlot", new Type[1] { typeof(RectTransform) }); RectTransform val2 = (RectTransform)val.transform; ((Transform)val2).SetParent(rowParent, false); ConfigureRowItemStretch(val2, num); LayoutElement obj = val.AddComponent<LayoutElement>(); obj.preferredWidth = num; obj.minWidth = num; obj.flexibleWidth = 0f; obj.minHeight = -1f; obj.preferredHeight = -1f; obj.flexibleHeight = 1f; _bedIconGo = new GameObject("BedIcon", new Type[2] { typeof(RectTransform), typeof(Image) }); RectTransform val3 = (RectTransform)_bedIconGo.transform; ((Transform)val3).SetParent((Transform)(object)val2, false); StretchFull(val3); Image component = _bedIconGo.GetComponent<Image>(); component.sprite = GetBedIconSprite(); component.type = (Type)0; ((Graphic)component).color = Color.white; component.preserveAspect = true; ((Graphic)component).raycastTarget = false; _arrowChaserGo = new GameObject("ArrowChaser", new Type[2] { typeof(RectTransform), typeof(HorizontalLayoutGroup) }); RectTransform val4 = (RectTransform)_arrowChaserGo.transform; ((Transform)val4).SetParent((Transform)(object)val2, false); StretchFull(val4); HorizontalLayoutGroup component2 = _arrowChaserGo.GetComponent<HorizontalLayoutGroup>(); ((LayoutGroup)component2).padding = new RectOffset(0, 0, 0, 0); ((HorizontalOrVerticalLayoutGroup)component2).spacing = 1f; ((LayoutGroup)component2).childAlignment = (TextAnchor)4; ((HorizontalOrVerticalLayoutGroup)component2).childControlWidth = false; ((HorizontalOrVerticalLayoutGroup)component2).childControlHeight = false; ((HorizontalOrVerticalLayoutGroup)component2).childForceExpandWidth = false; ((HorizontalOrVerticalLayoutGroup)component2).childForceExpandHeight = false; Sprite chevronSprite = GetChevronSprite(); _arrowImages = (Image[])(object)new Image[3]; for (int i = 0; i < 3; i++) { GameObject val5 = new GameObject($"Arrow_{i}", new Type[2] { typeof(RectTransform), typeof(Image) }); RectTransform val6 = (RectTransform)val5.transform; ((Transform)val6).SetParent((Transform)(object)val4, false); val6.sizeDelta = new Vector2(8f, 14f); Image component3 = val5.GetComponent<Image>(); component3.sprite = chevronSprite; component3.type = (Type)0; ((Graphic)component3).color = ArrowDimTint; component3.preserveAspect = true; ((Graphic)component3).raycastTarget = false; _arrowImages[i] = component3; } _arrowChaserGo.SetActive(false); _bedIconGo.SetActive(true); } private static void CreateIconInRow(Transform rowParent, string name, Sprite sprite, float cellWidth, Color tint) { //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Expected O, but got Unknown //IL_0097: Unknown result type (might be due to invalid IL or missing references) //IL_009c: Unknown result type (might be due to invalid IL or missing references) //IL_00a2: Unknown result type (might be due to invalid IL or missing references) //IL_00a7: Unknown result type (might be due to invalid IL or missing references) //IL_00b4: Expected O, but got Unknown //IL_00c8: Unknown result type (might be due to invalid IL or missing references) GameObject val = new GameObject(name, new Type[1] { typeof(RectTransform) }); RectTransform val2 = (RectTransform)val.transform; ((Transform)val2).SetParent(rowParent, false); ConfigureRowItemStretch(val2, cellWidth); LayoutElement obj = val.AddComponent<LayoutElement>(); obj.preferredWidth = cellWidth; obj.minWidth = cellWidth; obj.flexibleWidth = 0f; obj.minHeight = -1f; obj.preferredHeight = -1f; obj.flexibleHeight = 1f; GameObject val3 = new GameObject("Icon", new Type[2] { typeof(RectTransform), typeof(Image) }); RectTransform val4 = (RectTransform)val3.transform; ((Transform)val4).SetParent((Transform)(object)val2, false); StretchFull(val4); Image component = val3.GetComponent<Image>(); component.sprite = sprite; component.type = (Type)0; ((Graphic)component).color = tint; component.preserveAspect = true; ((Graphic)component).raycastTarget = false; } private static TextMeshProUGUI CreateTmpInRow(Transform rowParent, string name, TMP_FontAsset font, float cellWidth, float fontSize, Color color, string text, TextAlignmentOptions alignment) { //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Expected O, but got Unknown //IL_0093: Unknown result type (might be due to invalid IL or missing references) //IL_0098: Unknown result type (might be due to invalid IL or missing references) //IL_009e: Unknown result type (might be due to invalid IL or missing references) //IL_00a3: Unknown result type (might be due to invalid IL or missing references) //IL_00b0: Expected O, but got Unknown //IL_00c5: Unknown result type (might be due to invalid IL or missing references) //IL_00d5: Unknown result type (might be due to invalid IL or missing references) //IL_00f2: Unknown result type (might be due to invalid IL or missing references) GameObject val = new GameObject(name, new Type[1] { typeof(RectTransform) }); RectTransform val2 = (RectTransform)val.transform; ((Transform)val2).SetParent(rowParent, false); ConfigureRowItemStretch(val2, cellWidth); LayoutElement obj = val.AddComponent<LayoutElement>(); obj.preferredWidth = cellWidth; obj.minWidth = cellWidth; obj.flexibleWidth = 0f; obj.minHeight = -1f; obj.preferredHeight = -1f; obj.flexibleHeight = 1f; GameObject val3 = new GameObject(name, new Type[2] { typeof(RectTransform), typeof(TextMeshProUGUI) }); RectTransform val4 = (RectTransform)val3.transform; ((Transform)val4).SetParent((Transform)(object)val2, false); StretchFull(val4); TextMeshProUGUI component = val3.GetComponent<TextMeshProUGUI>(); ApplyFont(component, font); ((TMP_Text)component).fontSize = fontSize; ((Graphic)component).color = color; ((TMP_Text)component).text = text; ((TMP_Text)component).alignment = alignment; ((TMP_Text)component).textWrappingMode = (TextWrappingModes)0; ((TMP_Text)component).overflowMode = (TextOverflowModes)0; ((Graphic)component).raycastTarget = false; ((TMP_Text)component).margin = Vector4.zero; return component; } private static void ConfigureRowItemStretch(RectTransform rt, float width) { //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_0046: Unknown result type (might be due to invalid IL or missing references) //IL_0051: Unknown result type (might be due to invalid IL or missing references) rt.anchorMin = new Vector2(0f, 0f); rt.anchorMax = new Vector2(0f, 1f); rt.pivot = new Vector2(0f, 0.5f); rt.sizeDelta = new Vector2(width, 0f); rt.anchoredPosition = Vector2.zero; } private static void ApplyFont(TextMeshProUGUI tmp, TMP_FontAsset font) { ((TMP_Text)tmp).font = font; if ((Object)(object)font != (Object)null && (Object)(object)((TMP_Asset)font).material != (Object)null) { ((TMP_Text)tmp).fontSharedMaterial = ((TMP_Asset)font).material; } } private static TMP_FontAsset ResolveTmpFont(Transform nearUi) { if ((Object)(object)TMP_Settings.instance != (Object)null && (Object)(object)TMP_Settings.defaultFontAsset != (Object)null) { return TMP_Settings.defaultFontAsset; } TMP_FontAsset val = null; for (int i = 0; i < HudFontResourcePaths.Length; i++) { TMP_FontAsset val2 = Resources.Load<TMP_FontAsset>(HudFontResourcePaths[i]); if ((Object)(object)val2 != (Object)null) { val = val2; break; } } if ((Object)(object)val == (Object)null) { Transform val3 = nearUi; while ((Object)(object)val3.parent != (Object)null) { val3 = val3.parent; } TextMeshProUGUI[] componentsInChildren = ((Component)val3).GetComponentsInChildren<TextMeshProUGUI>(true); for (int j = 0; j < componentsInChildren.Length; j++) { TMP_FontAsset font = ((TMP_Text)componentsInChildren[j]).font; if ((Object)(object)font != (Object)null) { val = font; break; } } } if ((Object)(object)val == (Object)null) { TMP_FontAsset[] array = Resources.FindObjectsOfTypeAll<TMP_FontAsset>(); for (int k = 0; k < array.Length; k++) { if ((Object)(object)array[k] != (Object)null && (Object)(object)((TMP_Asset)array[k]).material != (Object)null) { val = array[k]; break; } } } if ((Object)(object)val != (Object)null && (Object)(object)TMP_Settings.defaultFontAsset == (Object)null) { try { TMP_Settings.defaultFontAsset = val; } catch { } } return val; } private static Sprite GetMoonIconSprite() { if ((Object)(object)_resolvedMoonIcon != (Object)null) { return _resolvedMoonIcon; } _resolvedMoonIcon = TryLoadEmbeddedPngSprite("sleephud_moon.png") ?? GetMoonCrescentSprite(); return _resolvedMoonIcon; } private static Sprite GetBedIconSprite() { if ((Object)(object)_resolvedBedIcon != (Object)null) { return _resolvedBedIcon; } _resolvedBedIcon = TryLoadEmbeddedPngSprite("sleephud_bed.png") ?? GetBedFilledSprite(); return _resolvedBedIcon; } private static Sprite GetPillowSegmentSprite() { if ((Object)(object)_resolvedPillowSprite != (Object)null) { return _resolvedPillowSprite; } _resolvedPillowSprite = TryLoadEmbeddedPngSprite("sleephud_pillow.png") ?? BaseWhiteSprite(); return _resolvedPillowSprite; } private static bool TryLoadPngIntoTexture(Texture2D tex, byte[] bytes) { try { Type type = Type.GetType("UnityEngine.ImageConversion, UnityEngine.ImageConversionModule"); if (type == null) { return false; } MethodInfo method = type.GetMethod("LoadImage", BindingFlags.Static | BindingFlags.Public, null, new Type[2] { typeof(Texture2D), typeof(byte[]) }, null); if (method == null) { return false; } return (bool)method.Invoke(null, new object[2] { tex, bytes }); } catch { return false; } } private static Sprite TryLoadEmbeddedPngSprite(string manifestEndsWith) { //IL_0081: Unknown result type (might be due to invalid IL or missing references) //IL_0088: Expected O, but got Unknown //IL_00dc: Unknown result type (might be due to invalid IL or missing references) //IL_00eb: Unknown result type (might be due to invalid IL or missing references) try { Assembly executingAssembly = Assembly.GetExecutingAssembly(); string text = null; string[] manifestResourceNames = executingAssembly.GetManifestResourceNames(); foreach (string text2 in manifestResourceNames) { if (text2.EndsWith(manifestEndsWith, StringComparison.OrdinalIgnoreCase)) { text = text2; break; } } if (text == null) { return null; } using Stream stream = executingAssembly.GetManifestResourceStream(text); if (stream == null) { return null; } int num = (int)stream.Length; byte[] array = new byte[num]; if (stream.Read(array, 0, num) != num) { return null; } Texture2D val = new Texture2D(2, 2, (TextureFormat)4, false); if (!TryLoadPngIntoTexture(val, array)) { return null; } ((Texture)val).filterMode = (FilterMode)1; ((Texture)val).wrapMode = (TextureWrapMode)1; BetterSleepBruh.Log.Debug("[SleepHud] Using embedded HUD icon: " + text); return Sprite.Create(val, new Rect(0f, 0f, (float)((Texture)val).width, (float)((Texture)val).height), new Vector2(0.5f, 0.5f), 100f); } catch (Exception ex) { BetterSleepBruh.Log.Warning("[SleepHud] Could not load embedded " + manifestEndsWith + ": " + ex.Message); return null; } } private static Sprite GetMoonCrescentSprite() { //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Expected O, but got Unknown //IL_00f1: Unknown result type (might be due to invalid IL or missing references) //IL_0100: Unknown result type (might be due to invalid IL or missing references) //IL_00a5: Unknown result type (might be due to invalid IL or missing references) //IL_00ad: Unknown result type (might be due to invalid IL or missing references) //IL_00a8: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_moonCrescentSprite != (Object)null) { return _moonCrescentSprite; } Texture2D val = new Texture2D(32, 32, (TextureFormat)4, false); Color32 val2 = default(Color32); ((Color32)(ref val2))..ctor((byte)0, (byte)0, (byte)0, (byte)0); float num = 15.5f; float num2 = 15.5f; float num3 = 14.08f; float num4 = 11.52f; float num5 = num + 4.48f; for (int i = 0; i < 32; i++) { for (int j = 0; j < 32; j++) { float num6 = (float)j - num; float num7 = (float)i - num2; bool flag = num6 * num6 + num7 * num7 <= num3 * num3; float num8 = (float)j - num5; float num9 = (float)i - num2; bool flag2 = num8 * num8 + num9 * num9 <= num4 * num4; val.SetPixel(j, i, Color32.op_Implicit((flag && !flag2) ? MoonBeige : val2)); } } val.Apply(); ((Texture)val).filterMode = (FilterMode)0; _moonCrescentSprite = Sprite.Create(val, new Rect(0f, 0f, 32f, 32f), new Vector2(0.5f, 0.5f), 100f); return _moonCrescentSprite; } private static Sprite GetBedFilledSprite() { //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Expected O, but got Unknown //IL_009b: Unknown result type (might be due to invalid IL or missing references) //IL_00ac: Unknown result type (might be due to invalid IL or missing references) //IL_00c2: Unknown result type (might be due to invalid IL or missing references) //IL_00e8: Unknown result type (might be due to invalid IL or missing references) //IL_0114: Unknown result type (might be due to invalid IL or missing references) //IL_0123: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_bedFilledSprite != (Object)null) { return _bedFilledSprite; } Texture2D val = new Texture2D(36, 24, (TextureFormat)4, false); for (int i = 0; i < 24; i++) { for (int j = 0; j < 36; j++) { val.SetPixel(j, i, Color32.op_Implicit(new Color32((byte)0, (byte)0, (byte)0, (byte)0))); } } Color32 c = default(Color32); ((Color32)(ref c))..ctor((byte)((float)(int)MoonBeige.r * 0.72f), (byte)((float)(int)MoonBeige.g * 0.72f), (byte)((float)(int)MoonBeige.b * 0.72f), byte.MaxValue); FillRect(val, 36, 24, 3, 3, 22, 5, c); FillRect(val, 36, 24, 2, 7, 24, 11, MoonBeige); FillRect(val, 36, 24, 24, 5, 10, 15, MoonBeige); FillRect(val, 36, 24, 5, 9, 12, 5, new Color32(byte.MaxValue, byte.MaxValue, byte.MaxValue, (byte)90)); val.Apply(); ((Texture)val).filterMode = (FilterMode)0; _bedFilledSprite = Sprite.Create(val, new Rect(0f, 0f, 36f, 24f), new Vector2(0.5f, 0.5f), 100f); return _bedFilledSprite; } private static void FillRect(Texture2D tex, int tw, int th, int x0, int y0, int rw, int rh, Color32 c) { //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_000e: Unknown result type (might be due to invalid IL or missing references) for (int i = y0; i < y0 + rh && i < th; i++) { for (int j = x0; j < x0 + rw && j < tw; j++) { tex.SetPixel(j, i, Color32.op_Implicit(c)); } } } private static Sprite GetChevronSprite() { //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Expected O, but got Unknown //IL_00c0: Unknown result type (might be due to invalid IL or missing references) //IL_00cf: Unknown result type (might be due to invalid IL or missing references) //IL_007f: Unknown result type (might be due to invalid IL or missing references) //IL_007c: Unknown result type (might be due to invalid IL or missing references) //IL_0080: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_chevronSprite != (Object)null) { return _chevronSprite; } Texture2D val = new Texture2D(8, 14, (TextureFormat)4, false); Color32 val2 = default(Color32); ((Color32)(ref val2))..ctor((byte)0, (byte)0, (byte)0, (byte)0); Color32 val3 = default(Color32); ((Color32)(ref val3))..ctor(byte.MaxValue, byte.MaxValue, byte.MaxValue, byte.MaxValue); for (int i = 0; i < 14; i++) { int num = ((i > 6) ? (i - 7) : (6 - i)); int num2 = 7 - num; for (int j = 0; j < 8; j++) { bool flag = j == num2 || j == num2 - 1; val.SetPixel(j, i, Color32.op_Implicit(flag ? val3 : val2)); } } val.Apply(); ((Texture)val).filterMode = (FilterMode)0; _chevronSprite = Sprite.Create(val, new Rect(0f, 0f, 8f, 14f), new Vector2(0.5f, 0.5f), 100f); return _chevronSprite; } private static Sprite BaseWhiteSprite() { //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_0041: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_whiteSprite != (Object)null) { return _whiteSprite; } Texture2D whiteTexture = Texture2D.whiteTexture; _whiteSprite = Sprite.Create(whiteTexture, new Rect(0f, 0f, (float)((Texture)whiteTexture).width, (float)((Texture)whiteTexture).height), new Vector2(0.5f, 0.5f), 100f); return _whiteSprite; } } public class SleepTracker : MonoBehaviour { public bool Enabled = true; private bool _lastCanSleep; private int _lastBroadcastTotal = -1; private int _lastBroadcastSleeping = -1; private double _lastBroadcastExtraRate = -1.0; private float _lastRpcRecalcTime; private int _heartbeatCounter; public static SleepTracker Instance { get; private set; } public bool CanSleep { get; private set; } public static double CurrentExtraRate { get; internal set; } public static double TotalPartialSleepBoostSeconds { get; internal set; } public static int CurrentPlayerCount { get; private set; } public static int CurrentSleepingCount { get; private set; } public static bool AllPlayersSleeping { get { if (CurrentPlayerCount > 0) { return CurrentSleepingCount >= CurrentPlayerCount; } return false; } } public static double LastPartialSleepExtraRate => CurrentExtraRate; private static bool IsCharacterInBedForBoost(ZDO zdo) { if (zdo != null && zdo.IsValid()) { return zdo.GetBool(ZDOVars.s_inBed, false); } return false; } public static void GetSleepOccupancyCounts(out int playerCount, out int playersSleeping) { playerCount = 0; playersSleeping = 0; ZNet instance = ZNet.instance; if ((Object)(object)instance == (Object)null) { return; } List<ZDO> allCharacterZDOS = instance.GetAllCharacterZDOS(); int nrOfPlayers = instance.GetNrOfPlayers(); int realTotalPlayers = Math.Max(allCharacterZDOS?.Count ?? 0, nrOfPlayers); playerCount = ConfigRegistry.GetEffectiveTotalPlayersForMod(realTotalPlayers); int num = 0; if (allCharacterZDOS != null) { for (int i = 0; i < allCharacterZDOS.Count; i++) { ZDO val = allCharacterZDOS[i]; if (val != null && IsCharacterInBedForBoost(val)) { num++; } } } playersSleeping = ConfigRegistry.GetEffectiveSleepingPlayersForMod(num, playerCount); } private static double ComputeExtraRateForPartialBoost(int playerCount, int playersSleeping) { if (playerCount <= 1) { return 0.0; } if (playersSleeping <= 0 || playersSleeping >= playerCount) { return 0.0; } double num = (double)playersSleeping / (double)(playerCount - 1); return (double)ConfigRegistry.BonusMultiplier.Value * num * (double)ConfigRegistry.BonusIncrementScale.Value; } public static double GetNextMorningCapSeconds() { if ((Object)(object)ZNet.instance == (Object)null || !ZNet.instance.IsServer() || (Object)(object)EnvMan.instance == (Object)null) { return double.PositiveInfinity; } EnvMan instance = EnvMan.instance; double timeSeconds = ZNet.instance.GetTimeSeconds(); double num = instance.m_dayLengthSec; int day = instance.GetDay(timeSeconds - num * 0.150000005960464); return instance.GetMorningStartSec(day + 1); } public static double ComputePartialSleepBoost() { return CurrentExtraRate; } private void Awake() { if ((Object)(object)ZNet.instance == (Object)null || !ZNet.instance.IsServer()) { Object.Destroy((Object)(object)this); return; } Instance = this; BetterSleepBruh.Log.Debug("[SERVER] SleepTracker Awakes."); } private void Start() { BetterSleepBruh.Log.Debug("[SERVER] SleepTracker Start."); if (ZNet.instance.IsServer()) { _lastCanSleep = (Object)(object)EnvMan.instance != (Object)null && EnvManPatches.IsInSleepWindow(EnvMan.instance); if (ZRoutedRpc.instance != null) { ZRoutedRpc.instance.Register("NotifyBedOccupancyChanged", (Action<long>)NotifyBedOccupancyChanged); ZRoutedRpc.instance.Register("RPC_RequestSleepingPlayerInfo", (Action<long>)RPC_RequestSleepingPlayerInfo); } LoadData(); ((MonoBehaviour)this).InvokeRepeating("UpdateSleeping", 1f, 1f); } } private static string GetSaveFilePath() { if ((Object)(object)ZNet.instance == (Object)null) { return null; } string worldName = ZNet.instance.GetWorldName(); if (string.IsNullOrEmpty(worldName)) { return null; } return Path.Combine(Paths.ConfigPath, "BetterSleepBruh_Data_" + worldName + ".txt"); } public static void SaveData() { string saveFilePath = GetSaveFilePath(); if (string.IsNullOrEmpty(saveFilePath)) { return; } try { File.WriteAllText(saveFilePath, TotalPartialSleepBoostSeconds.ToString(CultureInfo.InvariantCulture)); } catch (Exception ex) { BetterSleepBruh.Log.Warning("Failed to save sleep boost data: " + ex.Message); } } public static void LoadData() { string saveFilePath = GetSaveFilePath(); if (string.IsNullOrEmpty(saveFilePath) || !File.Exists(saveFilePath)) { return; } try { if (double.TryParse(File.ReadAllText(saveFilePath), NumberStyles.Float, CultureInfo.InvariantCulture, out var result)) { TotalPartialSleepBoostSeconds = result; } } catch (Exception ex) { BetterSleepBruh.Log.Warning("Failed to load sleep boost data: " + ex.Message); } } public void OnBedOccupancyChanged() { if (!((Object)(object)ZNet.instance == (Object)null) && ZNet.instance.IsServer() && Enabled) { RecalculateOccupancy(); } } private void NotifyBedOccupancyChanged(long sender) { ZNet instance = ZNet.instance; if (!((Object)(object)instance == (Object)null) && instance.IsServer() && Enabled && (sender == ZNet.GetUID() || instance.GetPeer(sender) != null)) { float time = Time.time; if (!(time - _lastRpcRecalcTime < 0.25f)) { _lastRpcRecalcTime = time; BetterSleepBruh.Log.Debug($"[SERVER] NotifyBedOccupancyChanged Heard from {sender}"); RecalculateOccupancy(); } } } private void RPC_RequestSleepingPlayerInfo(long sender) { ZNet instance = ZNet.instance; if (!((Object)(object)instance == (Object)null) && instance.IsServer() && (sender == ZNet.GetUID() || instance.GetPeer(sender) != null) && ZRoutedRpc.instance != null) { if (CanSleep) { ZRoutedRpc.instance.InvokeRoutedRPC(sender, "RPC_StartSleep", Array.Empty<object>()); } else { ZRoutedRpc.instance.InvokeRoutedRPC(sender, "RPC_StopSleep", Array.Empty<object>()); } ZRoutedRpc.instance.InvokeRoutedRPC(sender, "RPC_SleepingPlayerInfo", new object[3] { CurrentPlayerCount, CurrentSleepingCount, CurrentExtraRate }); ZRoutedRpc.instance.InvokeRoutedRPC(sender, "BSB_SyncSleepBoostTotal", new object[1] { TotalPartialSleepBoostSeconds }); } } public void RecalculateOccupancy(bool forceBroadcast = false) { if ((Object)(object)ZNet.instance == (Object)null || !ZNet.instance.IsServer()) { CurrentPlayerCount = 0; CurrentSleepingCount = 0; CurrentExtraRate = 0.0; return; } GetSleepOccupancyCounts(out var playerCount, out var playersSleeping); CurrentPlayerCount = playerCount; CurrentSleepingCount = playersSleeping; CurrentExtraRate = (((Object)(object)EnvMan.instance != (Object)null && EnvManPatches.IsInSleepWindow(EnvMan.instance)) ? ComputeExtraRateForPartialBoost(playerCount, playersSleeping) : 0.0); if (forceBroadcast || playerCount != _lastBroadcastTotal || playersSleeping != _lastBroadcastSleeping || Math.Abs(CurrentExtraRate - _lastBroadcastExtraRate) > 0.001) { BroadcastSleepingInfoNow(); } } private void UpdateSleeping() { if ((Object)(object)ZNet.instance == (Object)null || !ZNet.instance.IsServer()) { return; } CanSleep = (Object)(object)EnvMan.instance != (Object)null && EnvManPatches.IsInSleepWindow(EnvMan.instance); if (CanSleep) { _heartbeatCounter++; bool flag = _heartbeatCounter >= 3; if (flag) { _heartbeatCounter = 0; } RecalculateOccupancy(flag); } else { RecalculateOccupancy(); } if (CanSleep && !_lastCanSleep) { if (ZRoutedRpc.instance != null) { ZRoutedRpc.instance.InvokeRoutedRPC(0L, "RPC_StartSleep", Array.Empty<object>()); } RecalculateOccupancy(forceBroadcast: true); } if (!CanSleep && _lastCanSleep) { if (((Object)(object)EnvMan.instance == (Object)null || !EnvMan.instance.IsTimeSkipping()) && ZRoutedRpc.instance != null) { ZRoutedRpc.instance.InvokeRoutedRPC(0L, "RPC_StopSleep", Array.Empty<object>()); } _lastBroadcastTotal = -1; _lastBroadcastSleeping = -1; _lastBroadcastExtraRate = -1.0; SaveData(); } _lastCanSleep = CanSleep; } private void BroadcastSleepingInfoNow() { if (!((Object)(object)ZNet.instance == (Object)null) && ZNet.instance.IsServer()) { _lastBroadcastTotal = CurrentPlayerCount; _lastBroadcastSleeping = CurrentSleepingCount; _lastBroadcastExtraRate = CurrentExtraRate; if (ConfigRegistry.IsPlayerCountTestingActive) { BetterSleepBruh.Log.Debug($"[BetterSleepBruh TESTING] broadcast total={CurrentPlayerCount} sleeping={CurrentSleepingCount} extraRate={CurrentExtraRate}"); } else { BetterSleepBruh.Log.Debug($"[SERVER] Player Sleeping Info: Players on Server: {CurrentPlayerCount} Players Sleeping: {CurrentSleepingCount} Extra rate: {CurrentExtraRate}"); } if (ZRoutedRpc.instance != null) { ZRoutedRpc.instance.InvokeRoutedRPC(0L, "RPC_SleepingPlayerInfo", new object[3] { CurrentPlayerCount, CurrentSleepingCount, CurrentExtraRate }); } } } private void OnDestroy() { SaveData(); if ((Object)(object)Instance == (Object)(object)this) { Instance = null; } } } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)] internal sealed class NullableAttribute : Attribute { public readonly byte[] NullableFlags; public NullableAttribute(byte P_0) { NullableFlags = new byte[1] { P_0 }; } public NullableAttribute(byte[] P_0) { NullableFlags = P_0; } } [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] internal sealed class NullableContextAttribute : Attribute { public readonly byte Flag; public NullableContextAttribute(byte P_0) { Flag = P_0; } } } namespace ItemManager { [PublicAPI] internal enum CraftingTable { Disabled, Inventory, [InternalName("piece_workbench")] Workbench, [InternalName("piece_cauldron")] Cauldron, [InternalName("forge")] Forge, [InternalName("piece_artisanstation")] ArtisanTable, [InternalName("piece_stonecutter")] StoneCutter, [InternalName("piece_magetable")] MageTable, [InternalName("blackforge")] BlackForge, [InternalName("piece_preptable")] FoodPreparationTable, [InternalName("piece_MeadCauldron")] MeadKetill, Custom } [PublicAPI] internal enum ConversionPiece { Disabled, [InternalName("smelter")] Smelter, [InternalName("charcoal_kiln")] CharcoalKiln, [InternalName("blastfurnace")] BlastFurnace, [InternalName("windmill")] Windmill, [InternalName("piece_spinningwheel")] SpinningWheel, [InternalName("eitrrefinery")] EitrRefinery, Custom } internal class InternalName : Attribute { public readonly string internalName; public InternalName(string internalName) { this.internalName = internalName; } } [PublicAPI] internal class RequiredResourceList { public readonly List<Requirement> Requirements = new List<Requirement>(); public bool Free; public void Add(string itemName, int amount, int quality = 0) { Requirements.Add(new Requirement { itemName = itemName, amount = amount, quality = quality }); } public void Add(string itemName, ConfigEntry<int> amountConfig, int quality = 0) { Requirements.Add(new Requirement { itemName = itemName, amountConfig = amountConfig, quality = quality }); } } [PublicAPI] internal class CraftingStationList { public readonly List<CraftingStationConfig> Stations = new List<CraftingStationConfig>(); public void Add(CraftingTable table, int level) { Stations.Add(new CraftingStationConfig { Table = table, level = level }); } public void Add(string customTable, int level) { Stations.Add(new CraftingStationConfig { Table = CraftingTable.Custom, level = level, custom = customTable }); } } [PublicAPI] internal class ItemRecipe { public readonly RequiredResourceList RequiredItems = new RequiredResourceList(); public readonly RequiredResourceList RequiredUpgradeItems = new RequiredResourceList(); public readonly CraftingStationList Crafting = new CraftingStationList(); public int CraftAmount = 1; public bool RequireOnlyOneIngredient; public float QualityResultAmountMultiplier = 1f; public ConfigEntryBase? RecipeIsActive; } [PublicAPI] internal class Trade { public Trader Trader; public uint Price; public uint Stack = 1u; public string? RequiredGlobalKey; } [PublicAPI] [Flags] internal enum Trader { None = 0, Haldor = 1, Hildir = 2 } internal struct Requirement { public string itemName; public int amount; public ConfigEntry<int>? amountConfig; [Description("Set to a non-zero value to apply the requirement only for a specific quality")] public int quality; } internal struct CraftingStationConfig { public CraftingTable Table; public int level; public string? custom; } [Flags] internal enum Configurability { Disabled = 0, Recipe = 1, Stats = 2, Drop = 4, Trader = 8, Full = 0xF } [PublicAPI] internal class DropTargets { public readonly List<DropTarget> Drops = new List<DropTarget>(); public void Add(string creatureName, float chance, int min = 1, int? max = null, bool levelMultiplier = true, bool dontScale = false) { Drops.Add(new DropTarget { creature = creatureName, chance = chance, min = min, max = (max ?? min), levelMultiplier = levelMultiplier, dontScale = dontScale }); } } internal struct DropTarget { public string creature; public int min; public int max; public float chance; public bool levelMultiplier; public bool dontScale; } internal enum Toggle { On = 1, Off = 0 } [PublicAPI] internal class Item { private class ItemConfig { public ConfigEntry<string>? craft; public ConfigEntry<string>? upgrade; public ConfigEntry<CraftingTable> table; public ConfigEntry<int> tableLevel; public ConfigEntry<string> customTable; public ConfigEntry<int>? maximumTableLevel; public ConfigEntry<Toggle> requireOneIngredient; public ConfigEntry<float> qualityResultAmountMultiplier; } private class TraderConfig { public ConfigEntry<Trader> trader; public ConfigEntry<uint> price; public ConfigEntry<uint> stack; public ConfigEntry<string> requiredGlobalKey; } private class RequirementQuality { public int quality; } private class ConfigurationManagerAttributes { [UsedImplicitly] public int? Order; [UsedImplicitly] public bool? Browsable; [UsedImplicitly] public string? Category; [UsedImplicitly] public Action<ConfigEntryBase>? CustomDrawer; [UsedImplicitly] public Action<IUguiDrawerScope>? CustomUguiDrawer; public Func<bool>? browsability; } [PublicAPI] public enum DamageModifier { Normal, Resistant, Weak, Immune, Ignore, VeryResistant, VeryWeak, None } private delegate void setDmgFunc(ref DamageTypes dmg, float value); private class SerializedRequirements { public readonly List<Requirement> Reqs; public SerializedRequirements(List<Requirement> reqs) { Reqs = reqs; } public SerializedRequirements(string reqs) : this(reqs.Split(new char[1] { ',' }).Selec