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 Comfortable v1.2.3
Comfortable.dll
Decompiled 3 days agousing System; using System.Collections.Generic; using System.Diagnostics; 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 ConditionalConfigSync; using HarmonyLib; using UnityEngine; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: AssemblyTitle("Comfortable")] [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("Crystal")] [assembly: AssemblyProduct("Comfortable")] [assembly: AssemblyCopyright("Copyright © 2026 Crystal Ferrai")] [assembly: AssemblyTrademark("")] [assembly: ComVisible(false)] [assembly: Guid("a9d5f180-5ffb-4854-9a5e-81940e3b5666")] [assembly: AssemblyFileVersion("1.2.3.0")] [assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")] [assembly: AssemblyVersion("1.2.3.0")] namespace Comfortable; [BepInPlugin("dev.crystal.comfortable", "Comfortable", "1.2.3.0")] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInProcess("valheim.exe")] [BepInProcess("valheim_server.exe")] public class ComfortablePlugin : BaseUnityPlugin { [HarmonyPatch(typeof(FejdStartup))] private static class FejdStartup_Patches { [HarmonyPatch("SetupObjectDB")] [HarmonyPostfix] private static void SetupObjectDB_Postfix() { OnObjectDBSetup(); } } [HarmonyPatch(typeof(Player))] private static class Player_Patches { [HarmonyPatch("Awake")] [HarmonyPostfix] private static void Awake_Postfix(Player __instance) { sPlayers.Add(__instance); } [HarmonyPatch("OnDestroy")] [HarmonyPrefix] private static void OnDestroy_Prefix(Player __instance) { sPlayers.Remove(__instance); } } [HarmonyPatch(typeof(SE_Rested))] private static class SE_Rested_Patches { private enum TranspilerState { Searching, Finishing } [HarmonyPatch("GetNearbyComfortPieces")] [HarmonyTranspiler] private static IEnumerable<CodeInstruction> GetNearbyComfortPieces_Transpiler(IEnumerable<CodeInstruction> instructions) { TranspilerState state = TranspilerState.Searching; foreach (CodeInstruction instruction in instructions) { switch (state) { case TranspilerState.Searching: if (instruction.opcode == OpCodes.Ldc_R4 && (float)instruction.operand == sComfortRadiusConstant) { yield return new CodeInstruction(OpCodes.Ldc_R4, (object)ComfortItemRadius.Value); state = TranspilerState.Finishing; } else { yield return instruction; } break; case TranspilerState.Finishing: yield return instruction; break; } } } } [HarmonyPatch(typeof(EffectArea))] private static class EffectArea_Patches { [HarmonyPatch("Awake")] [HarmonyPostfix] private static void Awake_Postfix(EffectArea __instance) { UpdateFireEffectRadius(__instance, 1f, FireItemRadiusMultiplier.Value); } } public const string ModId = "dev.crystal.comfortable"; public const string ModName = "Comfortable"; public const string ModVersion = "1.2.3.0"; internal static readonly ConfigSync ConfigSync; public static ConfigEntry<float> BaseRestTime; public static ConfigEntry<float> RestTimePerComfort; public static ConfigEntry<float> ComfortItemRadius; public static ConfigEntry<float> FireItemRadiusMultiplier; private static Harmony sFejdStartupHarmony; private static Harmony sPlayerHarmony; private static Harmony sSERestedHarmony; private static Harmony sEffectAreaHarmony; private static readonly List<Player> sPlayers; private static readonly float sComfortRadiusConstant; private float mFireRadiusMultiplier; static ComfortablePlugin() { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_0015: 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_002b: 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_003e: Expected O, but got Unknown ConfigSync = new ConfigSync("dev.crystal.comfortable") { DisplayName = "Comfortable", CurrentVersion = "1.2.3.0", MinimumRequiredVersion = "1.2.3.0", ModRequired = true, ModRequirementMode = (ModRequirementMode)1 }; sPlayers = new List<Player>(); sComfortRadiusConstant = (float)typeof(SE_Rested).GetField("c_ComfortRadius", BindingFlags.Static | BindingFlags.NonPublic).GetValue(null); } private void Awake() { //IL_0146: Unknown result type (might be due to invalid IL or missing references) //IL_0150: Expected O, but got Unknown //IL_0155: Unknown result type (might be due to invalid IL or missing references) //IL_015f: Expected O, but got Unknown //IL_0164: Unknown result type (might be due to invalid IL or missing references) //IL_016e: Expected O, but got Unknown //IL_0173: Unknown result type (might be due to invalid IL or missing references) //IL_017d: Expected O, but got Unknown BaseRestTime = ((BaseUnityPlugin)this).Config.Bind<float>("Comfort", "BaseRestTime", 480f, "The base time of the rested buff, in seconds. Game default 480. [The value will be enforced on a server.]"); BaseRestTime.SettingChanged += BaseRestTime_SettingChanged; ((ConditionalConfigSync)ConfigSync).AddConfigEntry<float>(BaseRestTime, (ConfigSyncMode)0); RestTimePerComfort = ((BaseUnityPlugin)this).Config.Bind<float>("Comfort", "RestTimePerComfort", 60f, "The time to add to the rested buff, in seconds, for each comfort level beyond 1. Game default 60. [The value will be enforced on a server.]"); RestTimePerComfort.SettingChanged += RestTimePerComfort_SettingChanged; ((ConditionalConfigSync)ConfigSync).AddConfigEntry<float>(RestTimePerComfort, (ConfigSyncMode)0); ComfortItemRadius = ((BaseUnityPlugin)this).Config.Bind<float>("Comfort", "ComfortItemRadius", 10f, "The range at which comforting items will affect the comfort level of players. Game default 10. [The value will be enforced on a server.]"); ComfortItemRadius.SettingChanged += ComfortItemRadius_SettingChanged; ((ConditionalConfigSync)ConfigSync).AddConfigEntry<float>(ComfortItemRadius, (ConfigSyncMode)0); FireItemRadiusMultiplier = ((BaseUnityPlugin)this).Config.Bind<float>("Comfort", "FireItemRadiusMultiplier", 1f, "A multiplier to apply to the range at which items provide the \"Fire\" buff. Game default 1. Very high values may cause performance issues. [The value will be enforced on a server.]"); FireItemRadiusMultiplier.SettingChanged += FireItemRadiusMultiplier_SettingChanged; ((ConditionalConfigSync)ConfigSync).AddConfigEntry<float>(FireItemRadiusMultiplier, (ConfigSyncMode)0); ClampConfig(); mFireRadiusMultiplier = FireItemRadiusMultiplier.Value; sFejdStartupHarmony = new Harmony("dev.crystal.comfortable_FejdStartup"); sPlayerHarmony = new Harmony("dev.crystal.comfortable_Player"); sSERestedHarmony = new Harmony("dev.crystal.comfortable_SE_Rested"); sEffectAreaHarmony = new Harmony("dev.crystal.comfortable_EffectArea"); sFejdStartupHarmony.PatchAll(typeof(FejdStartup_Patches)); sPlayerHarmony.PatchAll(typeof(Player_Patches)); sSERestedHarmony.PatchAll(typeof(SE_Rested_Patches)); sEffectAreaHarmony.PatchAll(typeof(EffectArea_Patches)); } private void OnDestroy() { sFejdStartupHarmony.UnpatchSelf(); sPlayerHarmony.UnpatchSelf(); sSERestedHarmony.UnpatchSelf(); sEffectAreaHarmony.UnpatchSelf(); } private void BaseRestTime_SettingChanged(object sender, EventArgs e) { ClampConfig(); foreach (SE_Rested allRestedEffect in GetAllRestedEffects()) { allRestedEffect.m_baseTTL = BaseRestTime.Value; } } private void RestTimePerComfort_SettingChanged(object sender, EventArgs e) { ClampConfig(); foreach (SE_Rested allRestedEffect in GetAllRestedEffects()) { allRestedEffect.m_TTLPerComfortLevel = RestTimePerComfort.Value; } } private void ComfortItemRadius_SettingChanged(object sender, EventArgs e) { ClampConfig(); sSERestedHarmony.UnpatchSelf(); sSERestedHarmony.PatchAll(typeof(SE_Rested_Patches)); } private void FireItemRadiusMultiplier_SettingChanged(object sender, EventArgs e) { ClampConfig(); foreach (EffectArea allArea in EffectArea.GetAllAreas()) { UpdateFireEffectRadius(allArea, mFireRadiusMultiplier, FireItemRadiusMultiplier.Value); } mFireRadiusMultiplier = FireItemRadiusMultiplier.Value; } private static void ClampConfig() { if (BaseRestTime.Value < 0f) { BaseRestTime.Value = 0f; } if (BaseRestTime.Value > 36000f) { BaseRestTime.Value = 36000f; } if (RestTimePerComfort.Value < 0f) { RestTimePerComfort.Value = 0f; } if (RestTimePerComfort.Value > 3600f) { RestTimePerComfort.Value = 3600f; } if (ComfortItemRadius.Value < 0f) { ComfortItemRadius.Value = 0f; } if (ComfortItemRadius.Value > 1000f) { ComfortItemRadius.Value = 1000f; } if (FireItemRadiusMultiplier.Value < 0.01f) { FireItemRadiusMultiplier.Value = 0.01f; } if (FireItemRadiusMultiplier.Value > 10f) { FireItemRadiusMultiplier.Value = 10f; } } private static void OnObjectDBSetup() { SE_Rested restedEffect = GetRestedEffect(); if ((Object)(object)restedEffect != (Object)null) { restedEffect.m_baseTTL = BaseRestTime.Value; restedEffect.m_TTLPerComfortLevel = RestTimePerComfort.Value; } else { Debug.LogError((object)"[Comfortable] Could not locate SE_Rested effect object. This mod will not function properly."); } } private static IEnumerable<SE_Rested> GetAllRestedEffects() { SE_Rested restedEffect = GetRestedEffect(); if ((Object)(object)restedEffect != (Object)null) { yield return restedEffect; } foreach (Player sPlayer in sPlayers) { SE_Rested restedEffect2 = GetRestedEffect(sPlayer); if ((Object)(object)restedEffect2 != (Object)null) { yield return restedEffect2; } } } private static SE_Rested GetRestedEffect() { //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Expected O, but got Unknown ObjectDB instance = ObjectDB.instance; return (SE_Rested)((instance != null) ? instance.GetStatusEffect(SEMan.s_statusEffectRested) : null); } private static SE_Rested GetRestedEffect(Player player) { //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Expected O, but got Unknown return (SE_Rested)((Character)player).GetSEMan().GetStatusEffect(SEMan.s_statusEffectRested); } private static void UpdateFireEffectRadius(EffectArea area, float oldMultiplier, float newMultiplier) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Unknown result type (might be due to invalid IL or missing references) if ((area.m_type & 1) != 0) { Collider component = ((Component)area).GetComponent<Collider>(); SphereCollider val = (SphereCollider)(object)((component is SphereCollider) ? component : null); if ((Object)(object)val != (Object)null) { val.radius = val.radius / oldMultiplier * newMultiplier; } } } }