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 v1.0.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.Generic; using System.ComponentModel; using System.Diagnostics; using System.Globalization; using System.IO; using System.IO.Compression; using System.Linq; 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 BepInEx; using BepInEx.Bootstrap; using BepInEx.Configuration; using BepInEx.Logging; using BetterSleepBruh.Components; using BetterSleepBruh.Configuration; using HarmonyLib; using JetBrains.Annotations; using Jotunn.Entities; using Jotunn.Managers; using Jotunn.Utils; using Microsoft.CodeAnalysis; using TMPro; using UnityEngine; using UnityEngine.UI; using Vapok.Common.Abstractions; using Vapok.Common.Managers; using Vapok.Common.Managers.Configuration; using Vapok.Common.Managers.Creature; using Vapok.Common.Managers.LocalizationManager; using Vapok.Common.Managers.Location; using Vapok.Common.Managers.PieceManager; using Vapok.Common.Managers.Skill; using Vapok.Common.Managers.StatusEffects; using Vapok.Common.Shared; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: AssemblyTitle("BetterSleepBruh")] [assembly: AssemblyDescription("A Valheim Mod that Sleeps Like Enshrouded!")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("Vapok Gaming")] [assembly: AssemblyProduct("BetterSleepBruh")] [assembly: AssemblyCopyright("Copyright © 2025")] [assembly: AssemblyTrademark("")] [assembly: ComVisible(false)] [assembly: Guid("997CB563-FCC7-44B7-8F71-069747D27CC5")] [assembly: AssemblyFileVersion("1.0.2.0")] [assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.0.2.0")] [module: UnverifiableCode] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Microsoft.CodeAnalysis.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", "Better Sleep Bruh!", "1.0.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 = "Better Sleep Bruh!"; private const string _version = "1.0.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 => "Better Sleep Bruh!"; public string Version => "1.0.2"; public BaseUnityPlugin Instance => (BaseUnityPlugin)(object)_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()); } private void Start() { ConfigRegistry.Waiter.ConfigurationComplete(configDone: true); ((MonoBehaviour)this).InvokeRepeating("WaitForGame", 1f, 1f); ((MonoBehaviour)this).InvokeRepeating("WaitForZNet", 1f, 1f); } 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 ((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) { ((Component)_sleepHud).gameObject.SetActive(EnvMan.CanSleep()); } else { Log.Warning("[GuiBuild] Can't Build SleepHud"); } } private void Update() { if (Object.op_Implicit((Object)(object)Player.m_localPlayer) && Object.op_Implicit((Object)(object)ZNetScene.instance) && Object.op_Implicit((Object)(object)Game.instance) && Object.op_Implicit((Object)(object)_sleepHud)) { if (EnvMan.CanSleep() && !((Behaviour)_sleepHud).isActiveAndEnabled) { ((Component)_sleepHud).gameObject.SetActive(EnvMan.CanSleep()); } _zNetHasStopped = ZNet.instance.HaveStopped; if (_zNetHasStopped) { ((MonoBehaviour)this).InvokeRepeating("WaitForZNet", 1f, 1f); ((MonoBehaviour)this).InvokeRepeating("TryBuildSleepHud", 0f, 0.25f); _sleepHud = null; } } } public void InitializeModule(object send, EventArgs args) { if (!ValheimAwake) { ValheimAwake = true; } } private void OnDestroy() { _instance = null; } } } namespace BetterSleepBruh.Patches { public class EnvManPatches { [HarmonyPatch(typeof(EnvMan), "CalculateCanSleep")] private static class CalculateCanSleepPatch { private static bool Prefix(EnvMan __instance, ref bool __result) { if (ConfigRegistry.UseVanilleSleep.Value) { return true; } float dayFraction = __instance.GetDayFraction(); float value = ConfigRegistry.SleepStart.Value; if (value < 0.25f) { __result = dayFraction < 0.25f && dayFraction >= value; } else { __result = dayFraction >= value || dayFraction < 0.25f; } return false; } } } public class FejdStartupPatches { [HarmonyPatch(typeof(FejdStartup), "Awake")] [HarmonyAfter(new string[] { "org.bepinex.helpers.LocalizationManager" })] [HarmonyBefore(new string[] { "org.bepinex.helpers.ItemManager" })] public static class FejdStartupAwakePatch { private static void Prefix() { BetterSleepBruh.Waiter.ValheimIsAwake(awakeFlag: true); } } } public class ZDOPatches { [HarmonyPatch(typeof(ZDO), "Set", new Type[] { typeof(int), typeof(bool) })] private static class ZDOSetPatch { private static readonly Dictionary<ZDOID, bool> LastValue = new Dictionary<ZDOID, bool>(); private static void Prefix(ZDO __instance, int hash, bool value) { //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Unknown result type (might be due to invalid IL or missing references) if (hash == ZDOVars.s_inBed) { BetterSleepBruh.Log.Debug($"{__instance.m_uid}: Previous inBed: {__instance.GetBool(hash, false)}"); LastValue.Add(__instance.m_uid, __instance.GetBool(hash, false)); } } private static void Postfix(ZDO __instance, int hash, bool value) { //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0040: Unknown result type (might be due to invalid IL or missing references) //IL_0050: Unknown result type (might be due to invalid IL or missing references) //IL_0075: Unknown result type (might be due to invalid IL or missing references) if (hash == ZDOVars.s_inBed) { if (LastValue[__instance.m_uid] != value) { ZRoutedRpc.instance.InvokeRoutedRPC(ZRoutedRpc.Everybody, "NotifyBedOccupancyChanged", Array.Empty<object>()); } BetterSleepBruh.Log.Debug($"{__instance.m_uid}: LastValue: {LastValue[__instance.m_uid]} New inBed: {value}"); LastValue.Remove(__instance.m_uid); } } } } public 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 num = SleepTracker.ComputePartialSleepBoost(); if (num <= 0.0) { return; } double timeSeconds = __instance.GetTimeSeconds(); double nextMorningCapSeconds = SleepTracker.GetNextMorningCapSeconds(); if (double.IsPositiveInfinity(nextMorningCapSeconds)) { __instance.SetNetTime(timeSeconds + (double)dt * num); return; } if (timeSeconds >= nextMorningCapSeconds) { __instance.SetNetTime(nextMorningCapSeconds); return; } double num2 = nextMorningCapSeconds - timeSeconds; double num3 = num; float num4 = ((ConfigRegistry.BoostFadeRealSecondsBeforeMorning != null) ? ConfigRegistry.BoostFadeRealSecondsBeforeMorning.Value : 2f); if (num4 > 0f) { double num5 = 1.0 + num; double num6 = (double)num4 * num5; if (num2 < num6) { num3 = num * (num2 / num6); } } double num7 = Math.Min((double)dt * num3, num2); __instance.SetNetTime(timeSeconds + num7); } } } } 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 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 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 override real 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("Spoofed total player count while Testing Mode is on.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(2, 80), new object[1] { (object)new ConfigurationManagerAttributes { Order = 5, IsAdminOnly = true } }), ref TestingMaxPlayers); ConfigSyncBase.SyncedConfig("Testing Mode", "Simulate Players In Bed", 1, new ConfigDescription("Spoofed count of players in bed 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); } } public static int GetEffectiveTotalPlayersForMod(int realTotalPlayers) { if (TestingMode != null && TestingMode.Value && TestingMaxPlayers != null) { return TestingMaxPlayers.Value; } return realTotalPlayers; } public static int GetEffectiveSleepingPlayersForMod(int realSleepingCount, int effectivePlayerCount) { int max = ((effectivePlayerCount >= 0) ? effectivePlayerCount : 0); if (TestingMode != null && TestingMode.Value && TestingSleepingPlayers != null) { return ClampInt(TestingSleepingPlayers.Value, 0, max); } return ClampInt(realSleepingCount, 0, max); } 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 bool _compactLayout; 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 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 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 void Awake() { BetterSleepBruh.Log.Debug("SleepHudView Is Awoken"); } private void Start() { BetterSleepBruh.Log.Debug("SleepHudView Is Starting, registering RPC's"); 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); } private void RPC_SleepingPlayerInfo(long sender, int totalPlayers, int playersSleeping, double sleepBoost) { if (!((Object)(object)Player.m_localPlayer == (Object)null)) { if (ConfigRegistry.IsPlayerCountTestingActive) { BetterSleepBruh.Log.Debug($"[BetterSleepBruh TESTING] HUD total={totalPlayers} sleeping={playersSleeping} extraRate={sleepBoost}"); } else { BetterSleepBruh.Log.Debug($"[CLIENT] Total Players: {totalPlayers}"); BetterSleepBruh.Log.Debug($"[CLIENT] Players Sleeping: {playersSleeping}"); BetterSleepBruh.Log.Debug($"[CLIENT] Sleep Boost (extra rate × dt): {sleepBoost}"); } ((Component)this).gameObject.SetActive(true); Refresh(totalPlayers, playersSleeping); } } private void RPC_StartSleep(long sender) { if (!((Object)(object)Player.m_localPlayer == (Object)null)) { BetterSleepBruh.Log.Debug("[CLIENT] Start Sleep"); ((Component)this).gameObject.SetActive(true); } } private void RPC_StopSleep(long sender) { if (!((Object)(object)Player.m_localPlayer == (Object)null)) { BetterSleepBruh.Log.Debug("[CLIENT] Stop Sleep"); Player localPlayer = Player.m_localPlayer; localPlayer.SetSleeping(false); if (((Character)localPlayer).InBed()) { ((Character)localPlayer).AttachStop(); } ((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_0049: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_009b: Unknown result type (might be due to invalid IL or missing references) //IL_0094: Unknown result type (might be due to invalid IL or missing references) if (!((Behaviour)this).isActiveAndEnabled) { 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) { ((TMP_Text)_ratioTmp).text = $"{playersSleeping}/{totalPlayers}"; } } else { for (int i = 0; i < _segments.Length; i++) { ((Graphic)_segments[i]).color = ((i < playersSleeping) ? Color.white : PillowAwakeTint); } } if (!((Object)(object)_boostTmp == (Object)null)) { double bonusLabelPercent = GetBonusLabelPercent(totalPlayers, playersSleeping); if (bonusLabelPercent <= 0.0001) { ((TMP_Text)_boostTmp).text = "+0%"; } else { ((TMP_Text)_boostTmp).text = $"+{bonusLabelPercent:F0}%"; } } } 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_00b6: 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) //IL_00f7: Unknown result type (might be due to invalid IL or missing references) //IL_00fd: Unknown result type (might be due to invalid IL or missing references) //IL_0103: Expected O, but got Unknown //IL_010b: Unknown result type (might be due to invalid IL or missing references) //IL_0138: Unknown result type (might be due to invalid IL or missing references) //IL_0148: Unknown result type (might be due to invalid IL or missing references) //IL_015e: Unknown result type (might be due to invalid IL or missing references) //IL_0168: Expected O, but got Unknown //IL_01c8: Unknown result type (might be due to invalid IL or missing references) //IL_01cd: 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); CreateIconInRow((Transform)(object)val2, "Bed", GetBedIconSprite(), 26f, Color.white); 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); } private void EnsureSegments(int total) { //IL_0054: 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_00c9: Expected O, but got Unknown //IL_013e: Unknown result type (might be due to invalid IL or missing references) //IL_0143: Unknown result type (might be due to invalid IL or missing references) //IL_0149: Unknown result type (might be due to invalid IL or missing references) //IL_014e: Unknown result type (might be due to invalid IL or missing references) //IL_0161: Expected O, but got Unknown //IL_0182: Unknown result type (might be due to invalid IL or missing references) //IL_01ca: Unknown result type (might be due to invalid IL or missing references) //IL_01d1: Expected O, but got Unknown //IL_024c: Unknown result type (might be due to invalid IL or missing references) //IL_0253: Expected O, but got Unknown //IL_025a: Unknown result type (might be due to invalid IL or missing references) //IL_025f: Unknown result type (might be due to invalid IL or missing references) //IL_0272: Expected O, but got Unknown //IL_02a6: Unknown result type (might be due to invalid IL or missing references) //IL_02ab: Unknown result type (might be due to invalid IL or missing references) //IL_02ff: Unknown result type (might be due to invalid IL or missing references) //IL_035c: Unknown result type (might be due to invalid IL or missing references) //IL_0361: Unknown result type (might be due to invalid IL or missing references) //IL_0373: 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) bool flag = total > 5; int num = (flag ? 1 : total); if (total == _lastTotal && _compactLayout == flag && _segments.Length == num) { return; } _lastTotal = total; _compactLayout = flag; _ratioTmp = null; foreach (Transform item in (Transform)_segmentsRoot) { Object.Destroy((Object)(object)((Component)item).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 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_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_00c9: Unknown result type (might be due to invalid IL or missing references) //IL_00d9: Unknown result type (might be due to invalid IL or missing references) //IL_00f6: Unknown result type (might be due to invalid IL or missing references) 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("Label", 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; } string[] hudFontResourcePaths = HudFontResourcePaths; for (int i = 0; i < hudFontResourcePaths.Length; i++) { TMP_FontAsset val = Resources.Load<TMP_FontAsset>(hudFontResourcePaths[i]); if ((Object)(object)val != (Object)null) { return val; } } Transform val2 = nearUi; while ((Object)(object)val2.parent != (Object)null) { val2 = val2.parent; } TextMeshProUGUI[] componentsInChildren = ((Component)val2).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) { return font; } } 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) { return array[k]; } } return null; } 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 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; public static SleepTracker Instance { get; private set; } public bool CanSleep { get; private set; } public static double LastPartialSleepExtraRate { get; private set; } private static bool IsCharacterInBedForBoost(ZDO zdo) { return zdo.GetBool(ZDOVars.s_inBed, false); } private 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, nrOfPlayers); playerCount = ConfigRegistry.GetEffectiveTotalPlayersForMod(realTotalPlayers); int num = 0; foreach (ZDO item in allCharacterZDOS) { if (IsCharacterInBedForBoost(item)) { 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(); long dayLengthSec = instance.m_dayLengthSec; int day = instance.GetDay(timeSeconds - (double)dayLengthSec * 0.150000005960464); return instance.GetMorningStartSec(day + 1); } public static double ComputePartialSleepBoost() { if ((Object)(object)ZNet.instance == (Object)null || !ZNet.instance.IsServer()) { LastPartialSleepExtraRate = 0.0; return 0.0; } if ((Object)(object)EnvMan.instance == (Object)null || !EnvMan.CanSleep() || EnvMan.instance.IsTimeSkipping()) { LastPartialSleepExtraRate = 0.0; return 0.0; } GetSleepOccupancyCounts(out var playerCount, out var playersSleeping); LastPartialSleepExtraRate = ComputeExtraRateForPartialBoost(playerCount, playersSleeping); return LastPartialSleepExtraRate; } 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 = EnvMan.CanSleep(); ZRoutedRpc.instance.Register("NotifyBedOccupancyChanged", (Action<long>)NotifyBedOccupancyChanged); ((MonoBehaviour)this).InvokeRepeating("UpdateSleeping", 1f, 1f); } } private void UpdateSleeping() { if (ZNet.instance.IsServer()) { CanSleep = EnvMan.CanSleep(); if (CanSleep) { BroadcastSleepingInfoNow(); } if (CanSleep & !_lastCanSleep) { ZRoutedRpc.instance.InvokeRoutedRPC(ZRoutedRpc.Everybody, "RPC_StartSleep", Array.Empty<object>()); } if (!CanSleep & _lastCanSleep) { ZRoutedRpc.instance.InvokeRoutedRPC(ZRoutedRpc.Everybody, "RPC_StopSleep", Array.Empty<object>()); } _lastCanSleep = CanSleep; } } private void NotifyBedOccupancyChanged(long sender) { if (!((Object)(object)ZNet.instance == (Object)null) && ZNet.instance.IsServer() && !((Object)(object)Instance == (Object)null) && Instance.Enabled) { BetterSleepBruh.Log.Debug($"[SERVER] NotifyBedOccupancyChanged Heard from {sender}"); if ((Object)(object)EnvMan.instance != (Object)null && EnvMan.CanSleep()) { BroadcastSleepingInfoNow(); } } } private void BroadcastSleepingInfoNow() { if (ZNet.instance.IsServer()) { GetSleepOccupancyCounts(out var playerCount, out var playersSleeping); double num = ComputePartialSleepBoost(); if (ConfigRegistry.IsPlayerCountTestingActive) { BetterSleepBruh.Log.Debug($"[BetterSleepBruh TESTING] broadcast total={playerCount} sleeping={playersSleeping} extraRate={num}"); } else { BetterSleepBruh.Log.Debug($"[SERVER] Player Sleeping Info: Players on Server: {playerCount} Players Sleeping: {playersSleeping} Extra rate: {num}"); } ZRoutedRpc.instance.InvokeRoutedRPC(ZRoutedRpc.Everybody, "RPC_SleepingPlayerInfo", new object[3] { playerCount, playersSleeping, num }); } } } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Microsoft.CodeAnalysis.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] [Microsoft.CodeAnalysis.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) { Drops.Add(new DropTarget { creature = creatureName, chance = chance, min = min, max = max.GetValueOrDefault(min), levelMultiplier = levelMultiplier }); } } internal struct DropTarget { public string creature; public int min; public int max; public float chance; public bool levelMultiplier; } 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; public Func<bool>? browsability; } [PublicAPI] public enum DamageModifier { Normal, Resistant, Weak, Immune, Ignore, VeryResistant, VeryWeak, None } private delegate void setDmgFunc(ref DamageTypes dmg, float value); private class SerializedRequirements { public readonly List<Requirement> Reqs; public SerializedRequirements(List<Requirement> reqs) { Reqs = reqs; } public SerializedRequirements(string reqs) : this(reqs.Split(new char[1] { ',' }).Select(delegate(string r) { string[] array = r.Split(new char[1] { ':' }); Requirement result = default(Requirement); result.itemName = array[0]; result.amount = ((array.Length <= 1 || !int.TryParse(array[1], out var result2)) ? 1 : result2); result.quality = ((array.Length > 2 && int.TryParse(array[2], out var result3)) ? result3 : 0); return result; }).ToList()) { } public override string ToString() { return string.Join(",", Reqs.Select((Requirement r) => $"{r.itemName}:{r.amount}")); } public static ItemDrop? fetchByName(ObjectDB objectDB, string name) { GameObject itemPrefab = objectDB.GetItemPrefab(name); ItemDrop obj = ((itemPrefab != null) ? itemPrefab.GetComponent<ItemDrop>() : null); if ((Object)(object)obj == (Object)null) { LogManager.Log.Warning("The required item '" + name + "' does not exist."); } return obj; } public static Requirement[] toPieceReqs(ObjectDB objectDB, SerializedRequirements craft, SerializedRequirements upgrade) { //IL_00f0: Unknown result type (might be due to invalid IL or missing references) //IL_00f5: Unknown result type (might be due to invalid IL or missing references) //IL_00fd: Unknown result type (might be due to invalid IL or missing references) //IL_0178: Unknown result type (might be due to invalid IL or missing references) //IL_017d: Unknown result type (might be due to invalid IL or missing references) //IL_0185: Unknown result type (might be due to invalid IL or missing references) //IL_018c: Unknown result type (might be due to invalid IL or missing references) //IL_018f: Expected O, but got Unknown //IL_0194: Expected O, but got Unknown //IL_011c: Unknown result type (might be due to invalid IL or missing references) //IL_0125: Expected O, but got Unknown ObjectDB objectDB2 = objectDB; Dictionary<string, Requirement> dictionary = craft.Reqs.Where((Requirement r) => r.itemName != "").ToDictionary((Func<Requirement, string>)((Requirement r) => r.itemName), (Func<Requirement, Requirement>)delegate(Requirement r) { //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Expected O, but got Unknown ItemDrop val6 = ResItem(r); return (val6 != null) ? new Requirement { m_amount = (r.amountConfig?.Value ?? r.amount), m_resItem = val6, m_amountPerLevel = 0 } : ((Requirement)null); }); List<Requirement> list = dictionary.Values.Where((Requirement v) => v != null).ToList(); foreach (Requirement item in upgrade.Reqs.Where((Requirement r) => r.itemName != "")) { if (item.quality > 0) { ItemDrop val = ResItem(item); if (val != null) { Requirement val2 = new Requirement { m_resItem = val, m_amountPerLevel = (item.amountConfig?.Value ?? item.amount), m_amount = 0 }; list.Add(val2); requirementQuality.Add(val2, new RequirementQuality { quality = item.quality }); } continue; } if (!dictionary.TryGetValue(item.itemName, out var value) || value == null) { ItemDrop val3 = ResItem(item); if (val3 != null) { string itemName = item.itemName; Requirement val4 = new Requirement { m_resItem = val3, m_amount = 0 }; Requirement val5 = val4; dictionary[itemName] = val4; value = val5; list.Add(value); } } if (value != null) { value.m_amountPerLevel = item.amountConfig?.Value ?? item.amount; } } return list.ToArray(); ItemDrop? ResItem(Requirement r) { return fetchByName(objectDB2, r.itemName); } } } private class SerializedDrop { public readonly List<DropTarget> Drops; public SerializedDrop(List<DropTarget> drops) { Drops = drops; } public SerializedDrop(string drops) { Drops = ((drops == "") ? ((IEnumerable<string>)Array.Empty<string>()) : ((IEnumerable<string>)drops.Split(new char[1] { ',' }))).Select(delegate(string r) { string[] array = r.Split(new char[1] { ':' }); if (array.Length <= 2 || !int.TryParse(array[2], out var result)) { result = 1; } if (array.Length <= 3 || !int.TryParse(array[3], out var result2)) { result2 = result; } bool levelMultiplier = array.Length <= 4 || array[4] != "0"; DropTarget result3 = default(DropTarget); result3.creature = array[0]; result3.chance = ((array.Length > 1 && float.TryParse(array[1], out var result4)) ? result4 : 1f); result3.min = result; result3.max = result2; result3.levelMultiplier = levelMultiplier; return result3; }).ToList(); } public override string ToString() { return string.Join(",", Drops.Select((DropTarget r) => $"{r.creature}:{r.chance.ToString(CultureInfo.InvariantCulture)}:{r.min}:" + ((r.min == r.max) ? "" : $"{r.max}") + (r.levelMultiplier ? "" : ":0"))); } private static Character? fetchByName(ZNetScene netScene, string name) { GameObject prefab = netScene.GetPrefab(name); Character obj = ((prefab != null) ? prefab.GetComponent<Character>() : null); if ((Object)(object)obj == (Object)null) { LogManager.Log.Debug("The drop target character '" + name + "' does not exist."); } return obj; } public Dictionary<Character, Drop> toCharacterDrops(ZNetScene netScene, GameObject item) { //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_0046: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Unknown result type (might be due to invalid IL or missing references) //IL_005e: Unknown result type (might be due to invalid IL or missing references) //IL_006f: Expected O, but got Unknown Dictionary<Character, Drop> dictionary = new Dictionary<Character, Drop>(); foreach (DropTarget drop in Drops) { Character val = fetchByName(netScene, drop.creature); if (val != null) { dictionary[val] = new Drop { m_prefab = item, m_amountMin = drop.min, m_amountMax = drop.max, m_chance = drop.chance, m_levelMultiplier = drop.levelMultiplier }; } } return dictionary; } } [CompilerGenerated] private sealed class <>c__DisplayClass81_0 { public Quaternion? cameraRotation; public float lightIntensity; public ItemDrop item; public Quaternion? itemRotation; } [CompilerGenerated] private sealed class <Transpile_InventoryGui>d__83 : IEnumerable<CodeInstruction>, IEnumerable, IEnumerator<CodeInstruction>, IDisposable, IEnumerator { private int <>1__state; private CodeInstruction <>2__current; private int <>l__initialThreadId; private IEnumerable<CodeInstruction> instructions; public IEnumerable<CodeInstruction> <>3__instructions; private List<CodeInstruction> <instrs>5__2; private FieldInfo <amountField>5__3; private int <i>5__4; CodeInstruction IEnumerator<CodeInstruction>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <Transpile_InventoryGui>d__83(int <>1__state) { this.<>1__state = <>1__state; <>l__initialThreadId = Environment.CurrentManagedThreadId; } [DebuggerHidden] void IDisposable.Dispose() { <instrs>5__2 = null; <amountField>5__3 = null; <>1__state = -2; } private bool MoveNext() { //IL_0162: Unknown result type (might be due to invalid IL or missing references) //IL_016c: Expected O, but got Unknown //IL_0198: Unknown result type (might be due to invalid IL or missing references) //IL_01a2: Expected O, but got Unknown //IL_012c: Unknown result type (might be due to invalid IL or missing references) //IL_0136: Expected O, but got Unknown int num; switch (<>1__state) { default: return false; case 0: <>1__state = -1; <instrs>5__2 = instructions.ToList(); <amountField>5__3 = AccessTools.DeclaredField(typeof(Recipe), "m_amount"); <i>5__4 = 0; break; case 1: <>1__state = -1; if (<i>5__4 > 1 && <instrs>5__2[<i>5__4 - 2].opcode == OpCodes.Ldfld && CodeInstructionExtensions.OperandIs(<instrs>5__2[<i>5__4 - 2], (MemberInfo)<amountField>5__3) && <instrs>5__2[<i>5__4 - 1].opcode == OpCodes.Ldc_I4_1 && <instrs>5__2[<i>5__4].operand is Label) { <>2__current = new CodeInstruction(OpCodes.Ldarg_0, (object)null); <>1__state = 2; return true; } goto IL_01b2; case 2: <>1__state = -1; <>2__current = new CodeInstruction(OpCodes.Call, (object)AccessTools.DeclaredMethod(typeof(Item), "CheckItemIsUpgrade", (Type[])null, (Type[])null)); <>1__state = 3; return true; case 3: <>1__state = -1; <>2__current = new CodeInstruction(OpCodes.Brtrue, <instrs>5__2[<i>5__4].operand); <>1__state = 4; return true; case 4: { <>1__state = -1; goto IL_01b2; } IL_01b2: num = <i>5__4 + 1; <i>5__4 = num; break; } if (<i>5__4 < <instrs>5__2.Count) { <>2__current = <instrs>5__2[<i>5__4]; <>1__state = 1; return true; } return false; } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } [DebuggerHidden] IEnumerator<CodeInstruction> IEnumerable<CodeInstruction>.GetEnumerator() { <Transpile_InventoryGui>d__83 <Transpile_InventoryGui>d__; if (<>1__state == -2 && <>l__initialThreadId == Environment.CurrentManagedThreadId) { <>1__state = 0; <Transpile_InventoryGui>d__ = this; } else { <Transpile_InventoryGui>d__ = new <Transpile_InventoryGui>d__83(0); } <Transpile_InventoryGui>d__.instructions = <>3__instructions; return <Transpile_InventoryGui>d__; } [DebuggerHidden] IEnumerator IEnumerable.GetEnumerator() { return ((IEnumerable<CodeInstruction>)this).GetEnumerator(); } } private static bool _initialized = false; private static readonly List<Item> registeredItems = new List<Item>(); private static readonly Dictionary<ItemDrop, Item> itemDropMap = new Dictionary<ItemDrop, Item>(); private static Dictionary<Item, Dictionary<string, List<Recipe>>> activeRecipes = new Dictionary<Item, Dictionary<string, List<Recipe>>>(); private static Dictionary<Recipe, ConfigEntryBase?> hiddenCraftRecipes = new Dictionary<Recipe, ConfigEntryBase>(); private static Dictionary<Recipe, ConfigEntryBase?> hiddenUpgradeRecipes = new Dictionary<Recipe, ConfigEntryBase>(); private static Dictionary<Item, Dictionary<string, ItemConfig>> itemCraftConfigs = new Dictionary<Item, Dictionary<string, ItemConfig>>(); private static Dictionary<Item, ConfigEntry<string>> itemDropConfigs = new Dictionary<Item, ConfigEntry<string>>(); private static Dictionary<Item, ConfigEntry<bool>> itemDropEnabledConfig = new Dictionary<Item, ConfigEntry<bool>>(); private Dictionary<CharacterDrop, Drop> characterDrops = new Dictionary<CharacterDrop, Drop>(); private readonly Dictionary<ConfigEntryBase, Action> statsConfigs = new Dictionary<ConfigEntryBase, Action>(); private static readonly ConditionalWeakTable<Requirement, RequirementQuality> requirementQuality = new ConditionalWeakTable<Requirement, RequirementQuality>(); public string SectionName = string.Empty; public static Configurability DefaultConfigurability = Configurability.Full; public Configurability? Configurable; private Configurability configurationVisible = Configurability.Full; private TraderConfig? traderConfig; public readonly GameObject Prefab; [Description("Specifies the maximum required crafting station level to upgrade and repair the item.\nDefault is calculated from crafting station level and maximum quality.")] public int MaximumRequiredStationLevel = int.MaxValue; [Description("Assigns the item as a drop item to a creature.\nUses a creature name, a drop chance and a minimum and maximum amount.")] public readonly DropTargets DropsFrom = new DropTargets(); [Description("Configures whether the item can be bought at the trader.\nDon't forget to set cost to something above 0 or the item will be sold for free.")] public readonly Trade Trade = new Trade(); internal List<Conversion> Conversions = new List<Conversion>(); internal List<ItemConversion> conversions = new List<ItemConversion>(); public Dictionary<string, ItemRecipe> Recipes = new Dictionary<string, ItemRecipe>(); private static object? configManager; private static BaseUnityPlugin? _plugin; private Configurability configurability => Configurable ?? DefaultConfigurability; [Description("Specifies the resources needed to craft the item.\nUse .Add to add resources with their internal ID and an amount.\nUse one .Add for each resource type the item should need.")] public RequiredResourceList RequiredItems => this[""].RequiredItems; [Description("Specifies the resources needed to upgrade the item.\nUse .Add to add resources with their internal ID and an amount. This amount will be multipled by the item quality level.\nUse one .Add for each resource type the upgrade should need.")] public RequiredResourceList RequiredUpgradeItems => this[""].RequiredUpgradeItems; [Description("Specifies the crafting station needed to craft the item.\nUse .Add to add a crafting station, using the CraftingTable enum and a minimum level for the crafting station.\nUse one .Add for each crafting station.")] public CraftingStationList Crafting => this[""].Crafting; [Description("Specifies a config entry which toggles whether a recipe is active.")] public ConfigEntryBase? RecipeIsActive { get { return this[""].RecipeIsActive; } set { this[""].RecipeIsActive = value; } } [Description("Specifies the number of items that should be given to the player with a single craft of the item.\nDefaults to 1.")] public int CraftAmount { get { return this[""].CraftAmount; } set { this[""].CraftAmount = value; } } public bool RequireOnlyOneIngredient { get { return this[""].RequireOnlyOneIngredient; } set { this[""].RequireOnlyOneIngredient = value; } } public float QualityResultAmountMultiplier { get { return this[""].QualityResultAmountMultiplier; } set { this[""].QualityResultAmountMultiplier = value; } } public ItemRecipe this[string name] { get { if (Recipes.TryGetValue(name, out ItemRecipe value)) { return value; } return Recipes[name] = new ItemRecipe(); } } private static BaseUnityPlugin plugin { get { //IL_009b: Unknown result type (might be due to invalid IL or missing references) //IL_00a5: Expected O, but got Unknown if (_plugin == null) { IEnumerable<TypeInfo> source; try { source = Assembly.GetExecutingAssembly().DefinedTypes.ToList(); } catch (ReflectionTypeLoadException ex) { source = from t in ex.Types where t != null select t.GetTypeInfo(); } _plugin = (BaseUnityPlugin)Chainloader.ManagerObject.GetComponent((Type)source.First((TypeInfo t) => t.IsClass && typeof(BaseUnityPlugin).IsAssignableFrom(t))); } return _plugin; } } public static void Init() { if (!_initialized) { _initialized = true; } } public Item(string assetBundleFileName, string prefabName, string folderName = "assets") : this(PrefabManager.RegisterAssetBundle(assetBundleFileName, folderName), prefabName) { } public Item(AssetBundle bundle, string prefabName) : this(PrefabManager.RegisterPrefab(bundle, prefabName, addToObjectDb: true), skipRegistering: true) { } public Item(GameObject prefab, bool skipRegistering = false) { if (!skipRegistering) { PrefabManager.RegisterPrefab(prefab, addToObjectDb: true); } Prefab = prefab; registeredItems.Add(this); itemDropMap[Prefab.GetComponent<ItemDrop>()] = this; Prefab.GetComponent<ItemDrop>().m_itemData.m_dropPrefab = Prefab; } public void ToggleConfigurationVisibility(Configurability visible) { configurationVisible = visible; if (itemDropConfigs.TryGetValue(this, out ConfigEntry<string> value)) { Toggle((ConfigEntryBase)(object)value, Configurability.Drop); } if (itemCraftConfigs.TryGetValue(this, out Dictionary<string, ItemConfig> value2)) { foreach (ItemConfig value4 in value2.Values) { ToggleObj(value4, Configurability.Recipe); } } foreach (Conversion conversion in Conversions) { if (conversion.config != null) { ToggleObj(conversion.config, Configurability.Recipe); } } foreach (KeyValuePair<ConfigEntryBase, Action> statsConfig in statsConfigs) { Toggle(statsConfig.Key, Configurability.Stats); if ((visible & Configurability.Stats) != 0) { statsConfig.Value(); } } reloadConfigDisplay(); void Toggle(ConfigEntryBase cfg, Configurability check) { object[] tags = cfg.Description.Tags; for (int j = 0; j < tags.Length; j++) { if (tags[j] is ConfigurationManagerAttributes configurationManagerAttributes) { configurationManagerAttributes.Browsable = (visible & check) != 0 && (configurationManagerAttributes.browsability == null || configurationManagerAttributes.browsability()); } } } void ToggleObj(object obj, Configurability check) { FieldInfo[] fields = obj.GetType().GetFields(); for (int i = 0; i < fields.Length; i++) { object? value3 = fields[i].GetValue(obj); ConfigEntryBase val = (ConfigEntryBase)((value3 is ConfigEntryBase) ? value3 : null); if (val != null) { Toggle(val, check); } } } } internal static void reloadConfigDisplay() { object obj = configManager?.GetType().GetProperty("DisplayingWindow").GetValue(configManager); if (obj is bool && (bool)obj) { configManager.GetType().GetMethod("BuildSettingList").Invoke(configManager, Array.Empty<object>()); } } private void UpdateItemTableConfig(string recipeKey, CraftingTable table, string customTableValue) { if (activeRecipes.ContainsKey(this) && activeRecipes[this].TryGetValue(recipeKey, out List<Recipe> value)) { value.First().m_enabled = table != CraftingTable.Disabled; if ((uint)table <= 1u) { value.First().m_craftingStation = null; } else if (table == CraftingTable.Custom) { Recipe obj = value.First(); GameObject prefab = ZNetScene.instance.GetPrefab(customTableValue); obj.m_craftingStation = ((prefab != null) ? prefab.GetComponent<CraftingStation>() : null); } else { value.First().m_craftingStation = ZNetScene.instance.GetPrefab(getInternalName(table)).GetComponent<CraftingStation>(); } } } private void UpdateCraftConfig(string recipeKey, SerializedRequirements craftRequirements, SerializedRequirements upgradeRequirements) { if (!Object.op_Implicit((Object)(object)ObjectDB.instance) || !activeRecipes.ContainsKey(this) || !activeRecipes[this].TryGetValue(recipeKey, out List<Recipe> value)) { return; } foreach (Recipe item in value) { item.m_resources = SerializedRequirements.toPieceReqs(ObjectDB.instance, craftRequirements, upgradeRequirements); } } internal static void Patch_FejdStartup() { //IL_107a: Unknown result type (might be due to invalid IL or missing references) //IL_107f: Unknown result type (might be due to invalid IL or missing references) //IL_2333: Unknown result type (might be due to invalid IL or missing references) //IL_2340: Expected O, but got Unknown //IL_1143: Unknown result type (might be due to invalid IL or missing references) //IL_1146: Unknown result type (might be due to invalid IL or missing references) //IL_119c: Expected I4, but got Unknown //IL_0c4a: Unknown result type (might be due to invalid IL or missing references) //IL_0c5c: Expected O, but got Unknown //IL_0d1c: Unknown result type (might be due to invalid IL or missing references) //IL_0d29: Expected O, but got Unknown //IL_12d0: Unknown result type (might be due to invalid IL or missing references) //IL_12d3: Unknown result type (might be due to invalid IL or missing references) //IL_12d5: Invalid comparison between Unknown and I4 //IL_03a3: Unknown result type (might be due to invalid IL or missing references) //IL_03ba: Expected O, but got Unknown //IL_12d7: Unknown result type (might be due to invalid IL or missing references) //IL_12db: Invalid comparison between Unknown and I4 //IL_0e7d: Unknown result type (might be due to invalid IL or missing references) //IL_0e99: Expected O, but got Unknown //IL_0f29: Unknown result type (might be due to invalid IL or missing references) //IL_0f45: Expected O, but got Unknown //IL_12dd: Unknown result type (might be due to invalid IL or missing references) //IL_12e1: Invalid comparison between Unknown and I4 //IL_0fde: Unknown result type (might be due to invalid IL or missing references) //IL_0ffa: Expected O, but got Unknown //IL_14dc: Unknown result type (might be due to invalid IL or missing references) //IL_14df: Unknown result type (might be due to invalid IL or missing references) //IL_14e1: Invalid comparison between Unknown and I4 //IL_0497: Unknown result type (might be due to invalid IL or missing references) //IL_04ae: Expected O, but got Unknown //IL_14e3: Unknown result type (might be due to invalid IL or missing references) //IL_14e7: Unknown result type (might be due to invalid IL or missing references) //IL_14e9: Invalid comparison between Unknown and I4 //IL_14eb: Unknown result type (might be due to invalid IL or missing references) //IL_14ef: Invalid comparison between Unknown and I4 //IL_05d3: Unknown result type (might be due to invalid IL or missing references) //IL_05ea: Expected O, but got Unknown //IL_15c4: Unknown result type (might be due to invalid IL or missing references) //IL_15c9: Unknown result type (might be due to invalid IL or missing references) //IL_15cb: Unknown result type (might be due to invalid IL or missing references) //IL_15ce: Invalid comparison between Unknown and I4 //IL_15d0: Unknown result type (might be due to invalid IL or missing references) //IL_15d4: Invalid comparison between Unknown and I4 //IL_06ec: Unknown result type (might be due to invalid IL or missing references) //IL_0703: Expected O, but got Unknown //IL_1643: Unknown result type (might be due to invalid IL or missing references) //IL_1646: Unknown result type (might be due to invalid IL or missing references) //IL_1648: Invalid comparison between Unknown and I4 //IL_164a: Unknown result type (might be due to invalid IL or missing references) //IL_164e: Unknown result type (might be due to invalid IL or missing references) //IL_1650: Invalid comparison between Unknown and I4 //IL_07cc: Unknown result type (might be due to invalid IL or missing references) //IL_07e3: Expected O, but got Unknown //IL_1652: Unknown result type (might be due to invalid IL or missing references) //IL_1656: Invalid comparison between Unknown and I4 //IL_1793: Unknown result type (might be due to invalid IL or missing references) //IL_1796: Invalid comparison between Unknown and I4 //IL_08d7: Unknown result type (might be due to invalid IL or missing references) //IL_08ee: Expected O, but got Unknown //IL_1993: Unknown result type (might be due to invalid IL or missing references) //IL_199a: Invalid comparison between Unknown and I4 //IL_1a63: Unknown result type (might be due to invalid IL or missing references) //IL_1a68: Unknown result type (might be due to invalid IL or missing references) //IL_1a6a: Unknown result type (might be due to invalid IL or missing references) //IL_1a6e: Unknown result type (might be due to invalid IL or missing references) //IL_1a70: Invalid comparison between Unknown and I4 //IL_1adf: Unknown result type (might be due to invalid IL or missing references) //IL_1ae2: Unknown result type (might be due to invalid IL or missing references) //IL_1ae4: Invalid comparison between Unknown and I4 //IL_1709: Unknown result type (might be due to invalid IL or missing references) //IL_170e: Unknown result type (might be due to invalid IL or missing references) //IL_1ae6: Unknown result type (might be due to invalid IL or missing references) //IL_1aea: Invalid comparison between Unknown and I4 //IL_1aec: Unknown result type (might be due to invalid IL or missing references) //IL_1af0: Invalid comparison between Unknown and I4 //IL_1f5d: Unknown result type (might be due to invalid IL or missing references) //IL_1f60: Invalid comparison between Unknown and I4 Type type = AppDomain.CurrentDomain.GetAssemblies().FirstOrDefault((Assembly a) => a.GetName().Name == "ConfigurationManager")?.GetType("ConfigurationManager.ConfigurationManager"); configManager = ((type == null) ? null : Chainloader.ManagerObject.GetComponent(type)); if (DefaultConfigurability != 0) { bool saveOnConfigSet = plugin.Config.SaveOnConfigSet; plugin.Config.SaveOnConfigSet = false; foreach (Item item4 in registeredItems.Where((Item i) => i.configurability != Configurability.Disabled)) { Item item3 = item4; string text = (string.IsNullOrEmpty(item3.SectionName) ? item3.Prefab.GetComponent<ItemDrop>().m_itemData.m_shared.m_name : item3.SectionName); string englishName = new Regex("['[\"\\]]").Replace(Localizer.GetTranslation("English", text), "").Trim(); string localizedName = Localization.instance.Localize(text).Trim(); int order = 0; if ((item3.configurability & Configurability.Recipe) != 0) { itemCraftConfigs[item3] = new Dictionary<string, ItemConfig>(); foreach (string item5 in item3.Recipes.Keys.DefaultIfEmpty("")) { string configKey = item5; string text2 = ((configKey == "") ? "" : (" (" + configKey + ")")); if (configKey == "") { Configurability? configurable = item3.Configurable; if (configurable.HasValue && item3.Crafting.Stations.Count == 0) { item3.Crafting.Add(CraftingTable.Disabled, 1); } } if (!item3.Recipes.ContainsKey(configKey) || item3.Recipes[configKey].Crafting.Stations.Count <= 0) { continue; } ItemConfig itemConfig2 = (itemCraftConfigs[item3][configKey] = new ItemConfig()); ItemConfig cfg = itemConfig2; List<ConfigurationManagerAttributes> hideWhenNoneAttributes = new List<ConfigurationManagerAttributes>(); ConfigSyncBase.SyncedConfig(englishName, "Crafting Station" + text2, item3.Recipes[configKey].Crafting.Stations.First().Table, new ConfigDescription("Crafting station where " + englishName + " is available.", (AcceptableValueBase)null, new object[1] { new ConfigurationManagerAttributes { Order = (order -= 1), Browsable = ((item3.configurationVisible & Configurability.Recipe) != 0), Category = localizedName } }), ref cfg.table); ConfigurationManagerAttributes customTableAttributes = new ConfigurationManagerAttributes { Order = (order -= 1), browsability = CustomTableBrowsability, Browsable = (CustomTableBrowsability() && (item3.configurationVisible & Configurability.Recipe) != 0), Category = localizedName }; ConfigSyncBase.SyncedConfig(englishName, "Custom Crafting Station" + text2, item3.Recipes[configKey].Crafting.Stations.First().custom ?? "", new ConfigDescription("", (AcceptableValueBase)null, new object[1] { customTableAttributes }), ref cfg.customTable); cfg.table.SettingChanged += TableConfigChanged; cfg.customTable.SettingChanged += TableConfigChanged; ConfigurationManagerAttributes configurationManagerAttributes = new ConfigurationManagerAttributes { Order = (order -= 1), browsability = TableLevelBrowsability, Browsable = (TableLevelBrowsability() && (item3.configurationVisible & Configurability.Recipe) != 0), Category = localizedName }; hideWhenNoneAttributes.Add(configurationManagerAttributes); ConfigSyncBase.SyncedConfig(englishName, "Crafting Station Level" + text2, item3.Recipes[configKey].Crafting.Stations.First().level, new ConfigDescription("Required crafting station level to craft " + englishName + ".", (AcceptableValueBase)null, new object[1] { configurationManagerAttributes }), ref cfg.tableLevel); cfg.tableLevel.SettingChanged += delegate { if (activeRecipes.ContainsKey(item3) && activeRecipes[item3].TryGetValue(configKey, out List<Recipe> value6)) { value6.First().m_minStationLevel = cfg.tableLevel.Value; } }; if (item3.Prefab.GetComponent<ItemDrop>().m_itemData.m_shared.m_maxQuality > 1) { ConfigSyncBase.SyncedConfig(englishName, "Maximum Crafting Station Level" + text2, (item3.MaximumRequiredStationLevel == int.MaxValue) ? (item3.Recipes[configKey].Crafting.Stations.First().level + item3.Prefab.GetComponent<ItemDrop>().m_itemData.m_shared.m_maxQuality - 1) : item3.MaximumRequiredStationLevel, new ConfigDescription("Maximum crafting station level to upgrade and repair " + englishName + ".", (AcceptableValueBase)null, new object[1] { configurationManagerAttributes }), ref cfg.maximumTableLevel); } ConfigSyncBase.SyncedConfig(englishName, "Require only one resource" + text2, item3.Recipes[configKey].RequireOnlyOneIngredient ? Toggle.On : Toggle.Off, new ConfigDescription("Whether only one of the ingredients is needed to craft " + englishName, (AcceptableValueBase)null, new object[1] { new ConfigurationManagerAttributes { Order = (order -= 1), browsability = TableLevelBrowsability, Browsable = (TableLevelBrowsability() && (item3.configurationVisible & Configurability.Recipe) != 0), Category = localizedName } }), ref cfg.requireOneIngredient); ConfigurationManagerAttributes qualityResultAttributes = new ConfigurationManagerAttributes { Order = (order -= 1), browsability = QualityResultBrowsability, Browsable = (QualityResultBrowsability() && (item3.configurationVisible & Configurability.Recipe) != 0), Category = localizedName }; cfg.requireOneIngredient.SettingChanged += delegate { if (activeRecipes.ContainsKey(item3) && activeRecipes[item3].TryGetValue(configKey, out List<Recipe> value5)) { foreach (Recipe item6 in value5) { item6.m_requireOnlyOneIngredient = cfg.requireOneIngredient.Value == Toggle.On; } } qualityResultAttributes.Browsable = QualityResultBrowsability(); reloadConfigDisplay(); }; ConfigSyncBase.SyncedConfig(englishName, "Quality Multiplier" + text2, item3.Recipes[configKey].QualityResultAmountMultiplier, new ConfigDescription("Multiplies the crafted amount based on the quality of the resources when crafting " + englishName + ". Only works, if Require Only One Resource is true.", (AcceptableValueBase)null, new object[1] { qualityResultAttributes }), ref cfg.qualityResultAmountMultiplier); cfg.qualityResultAmountMultiplier.SettingChanged += delegate { if (activeRecipes.ContainsKey(item3) && activeRecipes[item3].TryGetValue(configKey, out List<Recipe> value4)) { foreach (Recipe item7 in value4) { item7.m_qualityResultAmountMultiplier = cfg.qualityResultAmountMultiplier.Value; } } }; if ((!item3.Recipes[configKey].RequiredItems.Free || item3.Recipes[configKey].RequiredItems.Requirements.Count > 0) && item3.Recipes[configKey].RequiredItems.Requirements.All((Requirement r) => r.amountConfig == null)) { cfg.craft = itemConfig("Crafting Costs" + text2, new SerializedRequirements(item3.Recipes[configKey].RequiredItems.Requirements).ToString(), "Item costs to craft " + englishName, isUpgrade: false); } if (item3.Prefab.GetComponent<ItemDrop>().m_itemData.m_shared.m_maxQuality > 1 && (!item3.Recipes[configKey].RequiredUpgradeItems.Free || item3.Recipes[configKey].RequiredUpgradeItems.Requirements.Count > 0) && item3.Recipes[configKey].RequiredUpgradeItems.Requirements.All((Requirement r) => r.amountConfig == null)) { cfg.upgrade = itemConfig("Upgrading Costs" + text2, new SerializedRequirements(item3.Recipes[configKey].RequiredUpgradeItems.Requirements).ToString(), "Item costs per level to upgrade " + englishName, isUpgrade: true); } if (cfg.craft != null) { cfg.craft.SettingChanged += ConfigChanged; } if (cfg.upgrade != null) { cfg.upgrade.SettingChanged += ConfigChanged; } void ConfigChanged(object o, EventArgs e) { item3.UpdateCraftConfig(configKey, new SerializedRequirements(cfg.craft?.Value ?? ""), new SerializedRequirements(cfg.upgrade?.Value ?? "")); } bool CustomTableBrowsability() { return cfg.table.Value == CraftingTable.Custom; } bool ItemBrowsability() { return cfg.table.Value != CraftingTable.Disabled; } bool QualityResultBrowsability() { return cfg.requireOneIngredient.Value == Toggle.On; } void TableConfigChanged(object o, EventArgs e) { item3.UpdateItemTableConfig(configKey, cfg.table.Value, cfg.customTable.Value); customTableAttributes.Browsable = cfg.table.Value == CraftingTable.Custom; foreach (ConfigurationManagerAttributes item8 in hideWhenNoneAttributes) { item8.Browsable = cfg.table.Value != CraftingTable.Disabled; } reloadConfigDisplay(); } bool TableLevelBrowsability() { return cfg.table.Value != CraftingTable.Disabled; } ConfigEntry<string> itemConfig(string name, string value, string desc, bool isUpgrade) { //IL_00a9: Unknown result type (might be due to invalid IL or missing references) //IL_00b6: Expected O, but got Unknown ConfigurationManagerAttributes configurationManagerAttributes3 = new ConfigurationManagerAttributes { CustomDrawer = drawRequirementsConfigTable(item3, isUpgrade), Order = (order -= 1), browsability = ItemBrowsability, Browsable = (ItemBrowsability() && (item3.configurationVisible & Configurability.Recipe) != 0), Category = localizedName }; hideWhenNoneAttributes.Add(configurationManagerAttributes3); ConfigEntry<string> configEntry4 = null; ConfigSyncBase.SyncedConfig(englishName, name, value, new ConfigDescription(desc, (AcceptableValueBase)null, new object[1] { configurationManagerAttributes3 }), ref configEntry4); return configEntry4; } } if ((item3.configurability & Configurability.Drop) != 0) { ConfigEntry<bool> dropsEnabledConfig = null; ConfigSyncBase.SyncedConfig(englishName, "Drops Enabled", value: false, new ConfigDescription("Enables " + englishName + " drops", (AcceptableValueBase)null, new object[1] { new ConfigurationManagerAttributes { Category = localizedName, Browsable = ((item3.configurationVisible & Configurability.Drop) != 0) } }), ref dropsEnabledConfig); itemDropEnabledConfig[item3] = dropsEnabledConfig; ConfigEntry<string> configEntry = null; ConfigSyncBase.SyncedConfig(englishName, "Drops from", new SerializedDrop(item3.DropsFrom.Drops).ToString(), new ConfigDescription("Creatures " + englishName + " drops from", (AcceptableValueBase)null, new object[1] { new ConfigurationManagerAttributes { CustomDrawer = drawDropsConfigTable, Category = localizedName, Browsable = ((item3.configurationVisible & Configurability.Drop) != 0) } }), ref configEntry); itemDropConfigs[item3] = configEntry; dropsEnabledConfig.SettingChanged += delegate { item3.UpdateCharacterDrop(dropsEnabledConfig.Value); }; configEntry.SettingChanged += delegate { item3.UpdateCharacterDrop(dropsEnabledConfig.Value); }; item3.UpdateCharacterDrop(dropsEnabledConfig.Value); } for (int j = 0; j < item3.Conversions.Count; j++) { string text3 = ((item3.Conversions.Count > 1) ? $"{j + 1}. " : ""); Conversion conversion = item3.Conversions[j];