Decompiled source of HexBaseEnhancements v1.1.0

Plugins/HexBaseEnhancements.dll

Decompiled 7 hours ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Reflection.Emit;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using HexBaseEnhancements.Features;
using HexBaseEnhancements.Patches;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyTitle("HexNowYouRest")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("HexNowYouRest")]
[assembly: AssemblyCopyright("Copyright ©  2026")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("2f19ccf3-f7b4-4290-8797-0a4a4d8f585b")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: AssemblyVersion("1.0.0.0")]
namespace HexBaseEnhancements
{
	[BepInPlugin("com.hex.baseenhancements", "HexBaseEnhancements", "1.1.0")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	public class Plugin : BaseUnityPlugin
	{
		private const string PluginGuid = "com.hex.baseenhancements";

		private const string PluginName = "HexBaseEnhancements";

		private const string PluginVersion = "1.1.0";

		private Harmony _harmonyInstance;

		private ConfigEntry<bool> _isRemoveWetDebuffEnabled;

		private ConfigEntry<bool> _isCustomRestedDelayEnabled;

		private ConfigEntry<int> _restedDelayInSeconds;

		private ConfigEntry<bool> _isRapidHealthAndStaminaRegenEnabled;

		private ConfigEntry<bool> _isAutoRepairEnabled;

		private ConfigEntry<bool> _isDoorOpenFaster;

		private ConfigEntry<bool> _isDoorsAutoClose;

		private ConfigEntry<int> _doorAutoCloseInSeconds;

		private ConfigEntry<bool> _isIncreasedComfortRadiusEnabled;

		private ConfigEntry<bool> _isAutoRepairSoundEnabled;

		private ConfigEntry<int> _comfortRadiusInMeters;

		private ConfigEntry<bool> _isAutoFuelFireplacesEnabled;

		private ConfigEntry<int> _fireplaceDetectionRadiusInMeters;

		internal static ManualLogSource Log;

		internal static Plugin Instance;

		internal static bool IsRemoveWetDebuffEnabled => Instance?._isRemoveWetDebuffEnabled?.Value == true;

		internal static bool IsCustomRestedDelayEnabled => Instance?._isCustomRestedDelayEnabled?.Value == true;

		internal static int RestedDelayInSeconds => Instance?._restedDelayInSeconds?.Value ?? 2;

		internal static bool IsRapidHealthAndStaminaRegenEnabled => Instance?._isRapidHealthAndStaminaRegenEnabled?.Value == true;

		internal static bool IsAutoRepairEnabled => Instance?._isAutoRepairEnabled?.Value == true;

		internal static bool DoorsOpensFaster => Instance?._isDoorOpenFaster?.Value == true;

		internal static bool DoorsAutoClose => Instance?._isDoorsAutoClose?.Value == true;

		internal static int DoorAutoCloseInSeconds => Instance?._doorAutoCloseInSeconds?.Value ?? 1;

		internal static bool IsIncreasedComfortRadiusEnabled => Instance?._isIncreasedComfortRadiusEnabled?.Value == true;

		internal static int ComfortRadiusInMeters => Instance?._comfortRadiusInMeters?.Value ?? 10;

		internal static bool IsAutoRepairSoundEnabled => Instance?._isAutoRepairSoundEnabled?.Value == true;

		internal static bool IsAutoFuelFireplacesEnabled => Instance?._isAutoFuelFireplacesEnabled?.Value == true;

		internal static int FireplaceDetectionRadiusInMeters => Instance?._fireplaceDetectionRadiusInMeters?.Value ?? 20;

		private void Awake()
		{
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_002d: Expected O, but got Unknown
			Instance = this;
			Log = ((BaseUnityPlugin)this).Logger;
			BindConfig();
			Assembly executingAssembly = Assembly.GetExecutingAssembly();
			_harmonyInstance = new Harmony("com.hex.baseenhancements");
			_harmonyInstance.PatchAll(executingAssembly);
			Log.LogInfo((object)"HexBaseEnhancements v1.1.0 loaded.");
		}

		private void OnDestroy()
		{
			if (_isCustomRestedDelayEnabled != null)
			{
				_isCustomRestedDelayEnabled.SettingChanged -= OnCustomRestedDelayEnabledChanged;
			}
			if (_restedDelayInSeconds != null)
			{
				_restedDelayInSeconds.SettingChanged -= OnRestedDelaySecondsChanged;
			}
			Log.LogInfo((object)"HexBaseEnhancements v1.1.0 unloaded.");
			Harmony harmonyInstance = _harmonyInstance;
			if (harmonyInstance != null)
			{
				harmonyInstance.UnpatchSelf();
			}
			_harmonyInstance = null;
			Instance = null;
			Log = null;
		}

		private void BindConfig()
		{
			//IL_014e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0158: Expected O, but got Unknown
			//IL_01c4: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ce: Expected O, but got Unknown
			_isRemoveWetDebuffEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("Wet Debuff", "RemoveWetDebuff", true, "Removes the Wet status effect when the player is sheltered and near a fire.");
			_isCustomRestedDelayEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("Resting", "CustomRestedDelay", true, "Enables a custom delay before the player receives the Rested status effect.");
			_restedDelayInSeconds = ((BaseUnityPlugin)this).Config.Bind<int>("Resting", "RestedDelayInSeconds", 2, "The number of seconds the player must rest before receiving the Rested status effect. Only used when CustomRestedDelay is enabled.");
			_isRapidHealthAndStaminaRegenEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("Health and Stamina Regen", "EnableRapidHealthAndStaminaRegen", true, "Rapidly restores health and stamina while the player is resting.");
			_isAutoRepairEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("Auto-Repair", "EnableAutoRepair", true, "Automatically repairs all repairable items in the player's inventory when the player is sheltered and near a fire.");
			_isDoorOpenFaster = ((BaseUnityPlugin)this).Config.Bind<bool>("Doors", "EnableDoorOpenFaster", true, "Makes doors open really fast.");
			_isDoorsAutoClose = ((BaseUnityPlugin)this).Config.Bind<bool>("Doors", "EnableDoorsAutoClose", true, "Automatically closes doors after a short delay when opened.");
			_doorAutoCloseInSeconds = ((BaseUnityPlugin)this).Config.Bind<int>("Doors", "DoorAutoCloseInSeconds", 1, "The number of seconds after which doors will automatically close when opened. Only used when EnableDoorsAutoClose is enabled.");
			_isIncreasedComfortRadiusEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("Comfort", "EnableIncreasedComfortRadius", true, "Increases the radius used to detect nearby comfort-providing pieces.");
			_comfortRadiusInMeters = ((BaseUnityPlugin)this).Config.Bind<int>("Comfort", "ComfortRadiusInMeters", 20, new ConfigDescription("The radius in meters used to detect nearby comfort-providing pieces. Only used when EnableIncreasedComfortRadius is enabled.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 50), Array.Empty<object>()));
			_isAutoRepairSoundEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("Auto-Repair", "EnableAutoRepairSound", true, "Plays a sound when auto-repairing items. Only used when EnableAutoRepair is enabled.");
			_isAutoFuelFireplacesEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("Fireplaces", "EnableAutoFuelFireplaces", true, "Automatically adds fuel to nearby fireplaces when their fuel level is low.");
			_fireplaceDetectionRadiusInMeters = ((BaseUnityPlugin)this).Config.Bind<int>("Fireplaces", "FireplaceDetectionRadiusInMeters", 20, new ConfigDescription("The radius in meters used to detect fireplaces for automatic fueling.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(5, 100), Array.Empty<object>()));
			_isCustomRestedDelayEnabled.SettingChanged += OnCustomRestedDelayEnabledChanged;
			_restedDelayInSeconds.SettingChanged += OnRestedDelaySecondsChanged;
		}

		private void OnCustomRestedDelayEnabledChanged(object sender, EventArgs e)
		{
			PatchSECozySetup.ApplyRestedDelay();
		}

		private void OnRestedDelaySecondsChanged(object sender, EventArgs e)
		{
			PatchSECozySetup.ApplyRestedDelay();
		}
	}
}
namespace HexBaseEnhancements.Patches
{
	[HarmonyPatch(typeof(Door), "SetState")]
	internal static class PatchDoorSetState
	{
		private const float VanillaAnimationSpeed = 1f;

		private const float FastOpenAnimationSpeed = 50f;

		[HarmonyPrefix]
		private static void Prefix(int state, Animator ___m_animator)
		{
			if (!((Object)(object)___m_animator == (Object)null))
			{
				___m_animator.speed = ((Plugin.DoorsOpensFaster && state != 0) ? 50f : 1f);
			}
		}

		[HarmonyPostfix]
		private static void Postfix(Door __instance, int state, ZNetView ___m_nview)
		{
			if (Plugin.DoorsAutoClose && !((Object)(object)__instance == (Object)null) && !((Object)(object)___m_nview == (Object)null) && state != 0 && ___m_nview.IsValid() && ___m_nview.IsOwner())
			{
				((MonoBehaviour)__instance).StartCoroutine(AutoCloseDoor(___m_nview));
			}
		}

		private static IEnumerator AutoCloseDoor(ZNetView nview)
		{
			yield return (object)new WaitForSeconds((float)Plugin.DoorAutoCloseInSeconds);
			if (!((Object)(object)nview == (Object)null) && nview.IsValid() && nview.IsOwner())
			{
				ZDO zDO = nview.GetZDO();
				if (zDO != null && zDO.GetInt(ZDOVars.s_state, 0) != 0)
				{
					nview.InvokeRPC("UseDoor", new object[1] { false });
				}
			}
		}
	}
	[HarmonyPatch(typeof(Fireplace), "Awake")]
	internal static class PatchFireplaceAwake
	{
		[HarmonyPostfix]
		private static void Postfix(Fireplace __instance)
		{
			AutoFuelFireplaces.Register(__instance);
		}
	}
	[HarmonyPatch(typeof(Player), "UpdateBaseValue")]
	internal static class PatchPlayerUpdateBaseValue
	{
		private static readonly FieldInfo BaseValueField = AccessTools.Field(typeof(Player), "m_baseValue");

		private static readonly MethodInfo TryAutoFuelIfInBaseMethod = AccessTools.Method(typeof(PatchPlayerUpdateBaseValue), "TryAutoFuelIfInBase", (Type[])null, (Type[])null);

		[HarmonyTranspiler]
		internal static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions)
		{
			//IL_009f: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a5: Expected O, but got Unknown
			//IL_00b1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b7: Expected O, but got Unknown
			List<CodeInstruction> list = instructions.ToList();
			List<int> list2 = (from x in list.Select((CodeInstruction instruction, int index2) => new
				{
					instruction = instruction,
					index = index2
				})
				where x.instruction.opcode == OpCodes.Stfld && object.Equals(x.instruction.operand, BaseValueField)
				select x.index).ToList();
			if (list2.Count != 1)
			{
				return list;
			}
			int index = list2[0] + 1;
			list.InsertRange(index, (IEnumerable<CodeInstruction>)(object)new CodeInstruction[2]
			{
				new CodeInstruction(OpCodes.Ldarg_0, (object)null),
				new CodeInstruction(OpCodes.Call, (object)TryAutoFuelIfInBaseMethod)
			});
			return list;
		}

		private static void TryAutoFuelIfInBase(Player player)
		{
			if (!((Object)(object)player == (Object)null) && !(BaseValueField == null) && (int)BaseValueField.GetValue(player) > 0)
			{
				AutoFuelFireplaces.TryAutoFuel(player);
			}
		}
	}
	[HarmonyPatch(typeof(Player), "UpdateCover")]
	internal static class PatchPlayerUpdateCover
	{
		private const float NearFireTimeout = 0.25f;

		private static readonly FieldInfo NearFireTimerField = AccessTools.Field(typeof(Player), "m_nearFireTimer");

		private static readonly MethodInfo GetCoverForPointMethod = AccessTools.Method(typeof(Cover), "GetCoverForPoint", (Type[])null, (Type[])null);

		private static readonly MethodInfo ApplyBaseEnhancementsMethod = AccessTools.Method(typeof(PatchPlayerUpdateCover), "ApplyBaseEnhancements", (Type[])null, (Type[])null);

		[HarmonyTranspiler]
		internal static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions)
		{
			//IL_00be: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c4: Expected O, but got Unknown
			//IL_00d0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d6: Expected O, but got Unknown
			List<CodeInstruction> list = instructions.ToList();
			List<int> list2 = (from x in list.Select((CodeInstruction instruction, int index2) => new
				{
					instruction = instruction,
					index = index2
				})
				where CodeInstructionExtensions.Calls(x.instruction, GetCoverForPointMethod)
				select x.index).ToList();
			if (list2.Count != 1)
			{
				Plugin.Log.LogError((object)$"Player.UpdateCover transpiler expected 1 call to Cover.GetCoverForPoint, but found {list2.Count}. Patch not applied.");
				return list;
			}
			int index = list2[0] + 1;
			list.InsertRange(index, (IEnumerable<CodeInstruction>)(object)new CodeInstruction[2]
			{
				new CodeInstruction(OpCodes.Ldarg_0, (object)null),
				new CodeInstruction(OpCodes.Call, (object)ApplyBaseEnhancementsMethod)
			});
			return list;
		}

		private static void ApplyBaseEnhancements(Player player)
		{
			if (!((Object)(object)player == (Object)null) && !(NearFireTimerField == null) && player.InShelter() && !((float)NearFireTimerField.GetValue(player) >= 0.25f))
			{
				RemoveWetDebuff(player);
				RestoreHealthAndStamina(player);
				RepairInventory(player);
			}
		}

		private static void RemoveWetDebuff(Player player)
		{
			if (Plugin.IsRemoveWetDebuffEnabled)
			{
				SEMan sEMan = ((Character)player).GetSEMan();
				if (sEMan != null && sEMan.HaveStatusEffect(SEMan.s_statusEffectWet))
				{
					sEMan.RemoveStatusEffect(SEMan.s_statusEffectWet, false);
				}
			}
		}

		private static void RestoreHealthAndStamina(Player player)
		{
			if (Plugin.IsRapidHealthAndStaminaRegenEnabled)
			{
				((Character)player).Heal(((Character)player).GetMaxHealth(), false);
				((Character)player).AddStamina(((Character)player).GetMaxStamina());
			}
		}

		private static void RepairInventory(Player player)
		{
			//IL_00a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a6: Unknown result type (might be due to invalid IL or missing references)
			if (!Plugin.IsAutoRepairEnabled)
			{
				return;
			}
			List<ItemData> allItems = ((Humanoid)player).GetInventory().GetAllItems();
			bool flag = false;
			foreach (ItemData item in allItems)
			{
				if (item.m_shared.m_useDurability)
				{
					float maxDurability = item.GetMaxDurability();
					if (!(item.m_durability >= maxDurability))
					{
						item.m_durability = maxDurability;
						flag = true;
					}
				}
			}
			if (!flag)
			{
				return;
			}
			((Character)player).Message((MessageType)1, "Inventory items repaired", 0, (Sprite)null);
			if (Plugin.IsAutoRepairSoundEnabled)
			{
				GameObject prefab = ZNetScene.instance.GetPrefab("sfx_gui_repairitem_workbench");
				if ((Object)(object)prefab != (Object)null)
				{
					Object.Instantiate<GameObject>(prefab, ((Component)player).transform.position, Quaternion.identity);
				}
			}
		}
	}
	[HarmonyPatch(typeof(SE_Cozy), "Setup")]
	internal static class PatchSECozySetup
	{
		private const float VanillaRestedDelay = 10f;

		private static SE_Cozy _currentCozy;

		[HarmonyPostfix]
		private static void Postfix(SE_Cozy __instance)
		{
			if (!((Object)(object)__instance == (Object)null) && !(__instance.m_statusEffect != "Rested"))
			{
				_currentCozy = __instance;
				ApplyRestedDelay();
			}
		}

		internal static void ApplyRestedDelay()
		{
			if (!((Object)(object)_currentCozy == (Object)null))
			{
				_currentCozy.m_delay = (Plugin.IsCustomRestedDelayEnabled ? ((float)Plugin.RestedDelayInSeconds) : 10f);
			}
		}
	}
	[HarmonyPatch(typeof(SE_Rested), "GetNearbyComfortPieces")]
	internal static class PatchSERestedGetNearbyComfortPieces
	{
		private const float VanillaComfortRadius = 10f;

		private static readonly FieldInfo TempPiecesField = AccessTools.Field(typeof(SE_Rested), "s_tempPieces");

		private static readonly MethodInfo GetAllComfortPiecesInRadiusMethod = AccessTools.Method(typeof(Piece), "GetAllComfortPiecesInRadius", (Type[])null, (Type[])null);

		private static readonly MethodInfo GetComfortRadiusMethod = AccessTools.Method(typeof(PatchSERestedGetNearbyComfortPieces), "GetComfortRadius", (Type[])null, (Type[])null);

		[HarmonyTranspiler]
		internal static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: Expected O, but got Unknown
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_002d: Expected O, but got Unknown
			//IL_003f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0045: Expected O, but got Unknown
			//IL_0067: Unknown result type (might be due to invalid IL or missing references)
			//IL_006d: Expected O, but got Unknown
			CodeMatcher val = new CodeMatcher(instructions, (ILGenerator)null);
			val.MatchForward(false, (CodeMatch[])(object)new CodeMatch[3]
			{
				new CodeMatch((OpCode?)OpCodes.Ldc_R4, (object)10f, (string)null),
				new CodeMatch((OpCode?)OpCodes.Ldsfld, (object)TempPiecesField, (string)null),
				new CodeMatch((Func<CodeInstruction, bool>)((CodeInstruction instruction) => CodeInstructionExtensions.Calls(instruction, GetAllComfortPiecesInRadiusMethod)), (string)null)
			});
			if (!val.IsValid)
			{
				Plugin.Log.LogError((object)"SE_Rested.GetNearbyComfortPieces transpiler could not locate the comfort radius call. Patch not applied.");
				return val.InstructionEnumeration();
			}
			val.Instruction.opcode = OpCodes.Call;
			val.Instruction.operand = GetComfortRadiusMethod;
			return val.InstructionEnumeration();
		}

		private static float GetComfortRadius()
		{
			if (!Plugin.IsIncreasedComfortRadiusEnabled)
			{
				return 10f;
			}
			return Plugin.ComfortRadiusInMeters;
		}
	}
}
namespace HexBaseEnhancements.Features
{
	internal static class AutoFuelFireplaces
	{
		private const float AutoFuelThreshold = 1f;

		private const float MissingFuelMessageCooldown = 10f;

		private static float _nextMissingFuelMessageTime;

		private static int _autoFuelScanMask;

		private static readonly Collider[] ScanColliders = (Collider[])(object)new Collider[8192];

		private static readonly HashSet<Fireplace> Fireplaces = new HashSet<Fireplace>();

		private static readonly FieldInfo NViewField = AccessTools.Field(typeof(Fireplace), "m_nview");

		internal static void TryAutoFuel(Player player)
		{
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_0087: Unknown result type (might be due to invalid IL or missing references)
			//IL_008c: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ba: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c0: Unknown result type (might be due to invalid IL or missing references)
			if (!Plugin.IsAutoFuelFireplacesEnabled || (Object)(object)player == (Object)null)
			{
				return;
			}
			int num = Physics.OverlapSphereNonAlloc(((Component)player).transform.position, (float)Plugin.FireplaceDetectionRadiusInMeters, ScanColliders, GetAutoFuelScanMask(), (QueryTriggerInteraction)2);
			HashSet<Container> hashSet = new HashSet<Container>();
			for (int i = 0; i < num; i++)
			{
				Collider val = ScanColliders[i];
				if (!((Object)(object)val == (Object)null))
				{
					Container componentInParent = ((Component)val).GetComponentInParent<Container>();
					if ((Object)(object)componentInParent != (Object)null)
					{
						hashSet.Add(componentInParent);
					}
				}
			}
			int fireplaceDetectionRadiusInMeters = Plugin.FireplaceDetectionRadiusInMeters;
			int num2 = fireplaceDetectionRadiusInMeters * fireplaceDetectionRadiusInMeters;
			Vector3 position = ((Component)player).transform.position;
			foreach (Fireplace fireplace in Fireplaces)
			{
				if (!((Object)(object)fireplace == (Object)null))
				{
					Vector3 val2 = ((Component)fireplace).transform.position - position;
					if (!(((Vector3)(ref val2)).sqrMagnitude > (float)num2))
					{
						TryFuelFireplace(player, fireplace, hashSet);
					}
				}
			}
		}

		internal static void Register(Fireplace fireplace)
		{
			if (!((Object)(object)fireplace == (Object)null))
			{
				Fireplaces.Add(fireplace);
				object? obj = NViewField?.GetValue(fireplace);
				object? obj2 = ((obj is ZNetView) ? obj : null);
				float? obj3;
				if (obj2 == null)
				{
					obj3 = null;
				}
				else
				{
					ZDO zDO = ((ZNetView)obj2).GetZDO();
					obj3 = ((zDO != null) ? new float?(zDO.GetFloat(ZDOVars.s_fuel, -1f)) : ((float?)null));
				}
				_ = obj3 ?? (-1f);
			}
		}

		private static void TryFuelFireplace(Player player, Fireplace fireplace, IEnumerable<Container> containers)
		{
			if ((Object)(object)fireplace == (Object)null || fireplace.m_infiniteFuel || !fireplace.m_canRefill || (Object)(object)fireplace.m_fuelItem == (Object)null)
			{
				return;
			}
			object? obj = NViewField?.GetValue(fireplace);
			ZNetView val = (ZNetView)((obj is ZNetView) ? obj : null);
			if ((Object)(object)val == (Object)null || !val.IsValid() || !val.IsOwner())
			{
				return;
			}
			ZDO zDO = val.GetZDO();
			if (zDO == null)
			{
				return;
			}
			float num = zDO.GetFloat(ZDOVars.s_fuel, 0f);
			if (num > 1f)
			{
				return;
			}
			string name = fireplace.m_fuelItem.m_itemData.m_shared.m_name;
			int num2 = Mathf.CeilToInt(fireplace.m_maxFuel - num);
			if (num2 <= 0)
			{
				return;
			}
			Inventory inventory = ((Humanoid)player).GetInventory();
			if (inventory == null)
			{
				return;
			}
			int num3 = inventory.CountItems(name, -1, true);
			int num4 = CountFuelInContainers(containers, name);
			int num5 = num3 + num4;
			if (num5 <= 0)
			{
				ShowMissingFuelMessage(player, name);
				return;
			}
			int num6 = Mathf.Min(num2, num5);
			int num7 = 0;
			int num8 = Mathf.Min(num3, num6);
			if (num8 > 0)
			{
				int num9 = inventory.CountItems(name, -1, true);
				inventory.RemoveItem(name, num8, -1, true);
				int num10 = inventory.CountItems(name, -1, true);
				int num11 = num9 - num10;
				num7 += num11;
				num6 -= num11;
			}
			if (num6 > 0)
			{
				num7 += RemoveFuelFromContainers(containers, name, num6);
			}
			if (num7 > 0)
			{
				float fuel = Mathf.Min(fireplace.m_maxFuel, num + (float)num7);
				fireplace.SetFuel(fuel);
			}
		}

		private static int CountFuelInContainers(IEnumerable<Container> containers, string fuelName)
		{
			int num = 0;
			foreach (Container container in containers)
			{
				if (!((Object)(object)container == (Object)null))
				{
					Inventory inventory = container.GetInventory();
					if (inventory != null)
					{
						int num2 = inventory.CountItems(fuelName, -1, true);
						num += num2;
					}
				}
			}
			return num;
		}

		private static int RemoveFuelFromContainers(IEnumerable<Container> containers, string fuelName, int amount)
		{
			int num = amount;
			int num2 = 0;
			foreach (Container container in containers)
			{
				if (num <= 0)
				{
					break;
				}
				if ((Object)(object)container == (Object)null)
				{
					continue;
				}
				Inventory inventory = container.GetInventory();
				if (inventory != null)
				{
					int num3 = inventory.CountItems(fuelName, -1, true);
					if (num3 > 0)
					{
						int num4 = Mathf.Min(num3, num);
						inventory.RemoveItem(fuelName, num4, -1, true);
						int num5 = inventory.CountItems(fuelName, -1, true);
						int num6 = num3 - num5;
						num2 += num6;
						num -= num6;
					}
				}
			}
			return num2;
		}

		private static void ShowMissingFuelMessage(Player player, string fuelName)
		{
			if (!(Time.time < _nextMissingFuelMessageTime))
			{
				_nextMissingFuelMessageTime = Time.time + 10f;
				((Character)player).Message((MessageType)1, "$msg_outof " + fuelName, 0, (Sprite)null);
			}
		}

		private static int GetAutoFuelScanMask()
		{
			if (_autoFuelScanMask == 0)
			{
				_autoFuelScanMask = LayerMask.GetMask(new string[2] { "piece", "piece_nonsolid" });
			}
			return _autoFuelScanMask;
		}
	}
}

Plugins/HexNowYouRest.dll

Decompiled 7 hours ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Reflection.Emit;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using HexBaseEnhancements.Patches;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyTitle("HexNowYouRest")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("HexNowYouRest")]
[assembly: AssemblyCopyright("Copyright ©  2026")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("2f19ccf3-f7b4-4290-8797-0a4a4d8f585b")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: AssemblyVersion("1.0.0.0")]
namespace HexBaseEnhancements
{
	[BepInPlugin("com.hex.baseenhancements", "HexBaseEnhancements", "1.1.0")]
	public class Plugin : BaseUnityPlugin
	{
		private const string PluginGuid = "com.hex.baseenhancements";

		private const string PluginName = "HexBaseEnhancements";

		private const string PluginVersion = "1.1.0";

		private Harmony _harmonyInstance;

		private ConfigEntry<bool> _isRemoveWetDebuffEnabled;

		private ConfigEntry<bool> _isCustomRestedDelayEnabled;

		private ConfigEntry<int> _restedDelayInSeconds;

		private ConfigEntry<bool> _isRapidHealthAndStaminaRegenEnabled;

		private ConfigEntry<bool> _isAutoRepairEnabled;

		private ConfigEntry<bool> _isDoorOpenFaster;

		private ConfigEntry<bool> _isDoorsAutoClose;

		private ConfigEntry<int> _doorAutoCloseInSeconds;

		private ConfigEntry<bool> _isIncreasedComfortRadiusEnabled;

		private ConfigEntry<bool> _isAutoRepairSoundEnabled;

		private ConfigEntry<int> _comfortRadiusInMeters;

		internal static ManualLogSource Log;

		internal static Plugin Instance;

		internal static bool IsRemoveWetDebuffEnabled => Instance?._isRemoveWetDebuffEnabled?.Value == true;

		internal static bool IsCustomRestedDelayEnabled => Instance?._isCustomRestedDelayEnabled?.Value == true;

		internal static int RestedDelayInSeconds => Instance?._restedDelayInSeconds?.Value ?? 2;

		internal static bool IsRapidHealthAndStaminaRegenEnabled => Instance?._isRapidHealthAndStaminaRegenEnabled?.Value == true;

		internal static bool IsAutoRepairEnabled => Instance?._isAutoRepairEnabled?.Value == true;

		internal static bool DoorsOpensFaster => Instance?._isDoorOpenFaster?.Value == true;

		internal static bool DoorsAutoClose => Instance?._isDoorsAutoClose?.Value == true;

		internal static int DoorAutoCloseInSeconds => Instance?._doorAutoCloseInSeconds?.Value ?? 1;

		internal static bool IsIncreasedComfortRadiusEnabled => Instance?._isIncreasedComfortRadiusEnabled?.Value == true;

		internal static int ComfortRadiusInMeters => Instance?._comfortRadiusInMeters?.Value ?? 10;

		internal static bool IsAutoRepairSoundEnabled => Instance?._isAutoRepairSoundEnabled?.Value == true;

		private void Awake()
		{
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_002d: Expected O, but got Unknown
			Instance = this;
			Log = ((BaseUnityPlugin)this).Logger;
			BindConfig();
			Assembly executingAssembly = Assembly.GetExecutingAssembly();
			_harmonyInstance = new Harmony("com.hex.baseenhancements");
			_harmonyInstance.PatchAll(executingAssembly);
			Log.LogInfo((object)"HexBaseEnhancements v1.1.0 loaded.");
		}

		private void OnDestroy()
		{
			if (_isCustomRestedDelayEnabled != null)
			{
				_isCustomRestedDelayEnabled.SettingChanged -= OnCustomRestedDelayEnabledChanged;
			}
			if (_restedDelayInSeconds != null)
			{
				_restedDelayInSeconds.SettingChanged -= OnRestedDelaySecondsChanged;
			}
			Log.LogInfo((object)"HexBaseEnhancements v1.1.0 unloaded.");
			Harmony harmonyInstance = _harmonyInstance;
			if (harmonyInstance != null)
			{
				harmonyInstance.UnpatchSelf();
			}
			_harmonyInstance = null;
			Instance = null;
			Log = null;
		}

		private void BindConfig()
		{
			//IL_014e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0158: Expected O, but got Unknown
			_isRemoveWetDebuffEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "RemoveWetDebuff", true, "Removes the Wet status effect when the player is sheltered and near a fire.");
			_isCustomRestedDelayEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "CustomRestedDelay", true, "Enables a custom delay before the player receives the Rested status effect.");
			_restedDelayInSeconds = ((BaseUnityPlugin)this).Config.Bind<int>("General", "RestedDelayInSeconds", 2, "The number of seconds the player must rest before receiving the Rested status effect. Only used when CustomRestedDelay is enabled.");
			_isRapidHealthAndStaminaRegenEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "EnableRapidHealthAndStaminaRegen", true, "Rapidly restores health and stamina while the player is resting.");
			_isAutoRepairEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "EnableAutoRepair", true, "Automatically repairs all repairable items in the player's inventory when the player is sheltered and near a fire.");
			_isDoorOpenFaster = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "EnableDoorOpenFaster", true, "Makes doors open really fast.");
			_isDoorsAutoClose = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "EnableDoorsAutoClose", true, "Automatically closes doors after a short delay when opened.");
			_doorAutoCloseInSeconds = ((BaseUnityPlugin)this).Config.Bind<int>("General", "DoorAutoCloseInSeconds", 1, "The number of seconds after which doors will automatically close when opened. Only used when EnableDoorsAutoClose is enabled.");
			_isIncreasedComfortRadiusEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "EnableIncreasedComfortRadius", true, "Increases the radius used to detect nearby comfort-providing pieces.");
			_comfortRadiusInMeters = ((BaseUnityPlugin)this).Config.Bind<int>("General", "ComfortRadiusInMeters", 20, new ConfigDescription("The radius in meters used to detect nearby comfort-providing pieces. Only used when EnableIncreasedComfortRadius is enabled.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 50), Array.Empty<object>()));
			_isAutoRepairSoundEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "EnableAutoRepairSound", true, "Plays a sound when auto-repairing items. Only used when EnableAutoRepair is enabled.");
			_isCustomRestedDelayEnabled.SettingChanged += OnCustomRestedDelayEnabledChanged;
			_restedDelayInSeconds.SettingChanged += OnRestedDelaySecondsChanged;
		}

		private void OnCustomRestedDelayEnabledChanged(object sender, EventArgs e)
		{
			PatchSECozySetup.ApplyRestedDelay();
		}

		private void OnRestedDelaySecondsChanged(object sender, EventArgs e)
		{
			PatchSECozySetup.ApplyRestedDelay();
		}
	}
}
namespace HexBaseEnhancements.Patches
{
	[HarmonyPatch(typeof(Door), "SetState")]
	internal static class PatchDoorSetState
	{
		private const float VanillaAnimationSpeed = 1f;

		private const float FastOpenAnimationSpeed = 50f;

		[HarmonyPrefix]
		private static void Prefix(int state, Animator ___m_animator)
		{
			if (!((Object)(object)___m_animator == (Object)null))
			{
				___m_animator.speed = ((Plugin.DoorsOpensFaster && state != 0) ? 50f : 1f);
			}
		}

		[HarmonyPostfix]
		private static void Postfix(Door __instance, int state, ZNetView ___m_nview)
		{
			if (Plugin.DoorsAutoClose && !((Object)(object)__instance == (Object)null) && !((Object)(object)___m_nview == (Object)null) && state != 0 && ___m_nview.IsValid() && ___m_nview.IsOwner())
			{
				((MonoBehaviour)__instance).StartCoroutine(AutoCloseDoor(___m_nview));
			}
		}

		private static IEnumerator AutoCloseDoor(ZNetView nview)
		{
			yield return (object)new WaitForSeconds((float)Plugin.DoorAutoCloseInSeconds);
			if (!((Object)(object)nview == (Object)null) && nview.IsValid() && nview.IsOwner())
			{
				ZDO zDO = nview.GetZDO();
				if (zDO != null && zDO.GetInt(ZDOVars.s_state, 0) != 0)
				{
					nview.InvokeRPC("UseDoor", new object[1] { false });
				}
			}
		}
	}
	[HarmonyPatch(typeof(Player), "UpdateCover")]
	internal static class PatchPlayerUpdateCover
	{
		private const float NearFireTimeout = 0.25f;

		private static readonly FieldInfo NearFireTimerField = AccessTools.Field(typeof(Player), "m_nearFireTimer");

		private static readonly MethodInfo GetCoverForPointMethod = AccessTools.Method(typeof(Cover), "GetCoverForPoint", (Type[])null, (Type[])null);

		private static readonly MethodInfo ApplyShelterEnhancementsMethod = AccessTools.Method(typeof(PatchPlayerUpdateCover), "ApplyShelterEnhancements", (Type[])null, (Type[])null);

		[HarmonyTranspiler]
		internal static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions)
		{
			//IL_00be: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c4: Expected O, but got Unknown
			//IL_00d0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d6: Expected O, but got Unknown
			List<CodeInstruction> list = instructions.ToList();
			List<int> list2 = (from x in list.Select((CodeInstruction instruction, int index2) => new
				{
					instruction = instruction,
					index = index2
				})
				where CodeInstructionExtensions.Calls(x.instruction, GetCoverForPointMethod)
				select x.index).ToList();
			if (list2.Count != 1)
			{
				Plugin.Log.LogError((object)$"Player.UpdateCover transpiler expected 1 call to Cover.GetCoverForPoint, but found {list2.Count}. Patch not applied.");
				return list;
			}
			int index = list2[0] + 1;
			list.InsertRange(index, (IEnumerable<CodeInstruction>)(object)new CodeInstruction[2]
			{
				new CodeInstruction(OpCodes.Ldarg_0, (object)null),
				new CodeInstruction(OpCodes.Call, (object)ApplyShelterEnhancementsMethod)
			});
			return list;
		}

		private static void ApplyShelterEnhancements(Player player)
		{
			if (!((Object)(object)player == (Object)null) && !(NearFireTimerField == null) && player.InShelter() && !((float)NearFireTimerField.GetValue(player) >= 0.25f))
			{
				RemoveWetDebuff(player);
				RepairInventory(player);
			}
		}

		private static void RemoveWetDebuff(Player player)
		{
			if (Plugin.IsRemoveWetDebuffEnabled)
			{
				SEMan sEMan = ((Character)player).GetSEMan();
				if (sEMan != null && sEMan.HaveStatusEffect(SEMan.s_statusEffectWet))
				{
					sEMan.RemoveStatusEffect(SEMan.s_statusEffectWet, false);
				}
			}
		}

		private static void RepairInventory(Player player)
		{
			//IL_00a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a6: Unknown result type (might be due to invalid IL or missing references)
			if (!Plugin.IsAutoRepairEnabled)
			{
				return;
			}
			List<ItemData> allItems = ((Humanoid)player).GetInventory().GetAllItems();
			bool flag = false;
			foreach (ItemData item in allItems)
			{
				if (item.m_shared.m_useDurability)
				{
					float maxDurability = item.GetMaxDurability();
					if (!(item.m_durability >= maxDurability))
					{
						item.m_durability = maxDurability;
						flag = true;
					}
				}
			}
			if (!flag)
			{
				return;
			}
			((Character)player).Message((MessageType)1, "Inventory items repaired", 0, (Sprite)null);
			if (Plugin.IsAutoRepairSoundEnabled)
			{
				GameObject prefab = ZNetScene.instance.GetPrefab("sfx_gui_repairitem_workbench");
				if ((Object)(object)prefab != (Object)null)
				{
					Object.Instantiate<GameObject>(prefab, ((Component)player).transform.position, Quaternion.identity);
				}
			}
		}
	}
	[HarmonyPatch(typeof(SE_Cozy), "Setup")]
	internal static class PatchSECozySetup
	{
		private const float VanillaRestedDelay = 10f;

		private static SE_Cozy _currentCozy;

		[HarmonyPostfix]
		private static void Postfix(SE_Cozy __instance)
		{
			if (!((Object)(object)__instance == (Object)null) && !(__instance.m_statusEffect != "Rested"))
			{
				_currentCozy = __instance;
				ApplyRestedDelay();
				RestoreHealthAndStamina(__instance);
			}
		}

		internal static void ApplyRestedDelay()
		{
			if (!((Object)(object)_currentCozy == (Object)null))
			{
				_currentCozy.m_delay = (Plugin.IsCustomRestedDelayEnabled ? ((float)Plugin.RestedDelayInSeconds) : 10f);
			}
		}

		private static void RestoreHealthAndStamina(SE_Cozy cozy)
		{
			if (Plugin.IsRapidHealthAndStaminaRegenEnabled)
			{
				Character character = ((StatusEffect)cozy).m_character;
				Player val = (Player)(object)((character is Player) ? character : null);
				if (!((Object)(object)val == (Object)null))
				{
					((Character)val).Heal(((Character)val).GetMaxHealth(), false);
					((Character)val).AddStamina(((Character)val).GetMaxStamina());
				}
			}
		}
	}
	[HarmonyPatch(typeof(SE_Rested), "GetNearbyComfortPieces")]
	internal static class PatchSERestedGetNearbyComfortPieces
	{
		private const float VanillaComfortRadius = 10f;

		private static readonly FieldInfo TempPiecesField = AccessTools.Field(typeof(SE_Rested), "s_tempPieces");

		private static readonly MethodInfo GetAllComfortPiecesInRadiusMethod = AccessTools.Method(typeof(Piece), "GetAllComfortPiecesInRadius", (Type[])null, (Type[])null);

		private static readonly MethodInfo GetComfortRadiusMethod = AccessTools.Method(typeof(PatchSERestedGetNearbyComfortPieces), "GetComfortRadius", (Type[])null, (Type[])null);

		[HarmonyTranspiler]
		internal static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: Expected O, but got Unknown
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_002d: Expected O, but got Unknown
			//IL_003f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0045: Expected O, but got Unknown
			//IL_0067: Unknown result type (might be due to invalid IL or missing references)
			//IL_006d: Expected O, but got Unknown
			CodeMatcher val = new CodeMatcher(instructions, (ILGenerator)null);
			val.MatchForward(false, (CodeMatch[])(object)new CodeMatch[3]
			{
				new CodeMatch((OpCode?)OpCodes.Ldc_R4, (object)10f, (string)null),
				new CodeMatch((OpCode?)OpCodes.Ldsfld, (object)TempPiecesField, (string)null),
				new CodeMatch((Func<CodeInstruction, bool>)((CodeInstruction instruction) => CodeInstructionExtensions.Calls(instruction, GetAllComfortPiecesInRadiusMethod)), (string)null)
			});
			if (!val.IsValid)
			{
				Plugin.Log.LogError((object)"SE_Rested.GetNearbyComfortPieces transpiler could not locate the comfort radius call. Patch not applied.");
				return val.InstructionEnumeration();
			}
			val.Instruction.opcode = OpCodes.Call;
			val.Instruction.operand = GetComfortRadiusMethod;
			return val.InstructionEnumeration();
		}

		private static float GetComfortRadius()
		{
			if (!Plugin.IsIncreasedComfortRadiusEnabled)
			{
				return 10f;
			}
			return Plugin.ComfortRadiusInMeters;
		}
	}
}