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 Regen v2.8.7
HealthRegenMod.dll
Decompiled 10 months agousing System; using System.Diagnostics; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; using Microsoft.CodeAnalysis; using Photon.Pun; using UnityEngine; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)] [assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = "")] [assembly: AssemblyCompany("HealthRegenMod")] [assembly: AssemblyConfiguration("Debug")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0")] [assembly: AssemblyProduct("HealthRegenMod")] [assembly: AssemblyTitle("HealthRegenMod")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.0.0.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; } } } [BepInPlugin("Xmods.healthregen", "HealthRegen", "2.8.7")] public class HealthRegenMod : BaseUnityPlugin { [HarmonyPatch(typeof(PlayerHealth), "Start")] public class RegenPatch { private static void Postfix(PlayerHealth __instance) { if ((Object)(object)__instance != (Object)null && (Object)(object)((Component)__instance).gameObject.GetComponent<RegenUpdater>() == (Object)null) { ((Component)__instance).gameObject.AddComponent<RegenUpdater>().Init(__instance); Log.LogInfo((object)$"[{DateTime.Now:HH:mm:ss}] [Patch] RegenUpdater attached to {((Object)__instance).name}."); } } } public class RegenUpdater : MonoBehaviour { private bool isRegenActive = false; private int lastKnownLocalHealth; private PlayerHealth playerHealth; private FieldInfo healthField; private FieldInfo maxHealthField; private FieldInfo playerAvatarField; private PhotonView playerPhotonView; private int currentRegenInterval; public void Init(PlayerHealth instance) { playerHealth = instance; Type type = ((object)playerHealth).GetType(); healthField = type.GetField("health", BindingFlags.Instance | BindingFlags.NonPublic); maxHealthField = type.GetField("maxHealth", BindingFlags.Instance | BindingFlags.NonPublic); playerAvatarField = type.GetField("playerAvatar", BindingFlags.Instance | BindingFlags.NonPublic); playerPhotonView = ((Component)playerHealth).GetComponent<PhotonView>(); if (healthField != null) { lastKnownLocalHealth = (int)healthField.GetValue(playerHealth); } currentRegenInterval = BaseRegenIntervalSeconds.Value; LogInfo("[Init] Reflection setup complete for " + GetNickname(playerAvatarField?.GetValue(playerHealth)) + "."); } private void Start() { LogInfo("[Start] RegenUpdater Start() called for " + ((Object)playerHealth).name + "."); } private void Update() { if ((Object)(object)playerPhotonView != (Object)null && !playerPhotonView.IsMine) { return; } int num = (int)healthField.GetValue(playerHealth); int num2 = (int)maxHealthField.GetValue(playerHealth); if (num <= 0) { if (isRegenActive) { StopRegenCycle(); LogInfo("[Regen] " + GetNickname(playerAvatarField?.GetValue(playerHealth)) + " has 0 HP. Regen stopped."); } return; } if (num < num2 && !isRegenActive) { isRegenActive = true; ((MonoBehaviour)this).CancelInvoke("PerformRegenTick"); ((MonoBehaviour)this).InvokeRepeating("PerformRegenTick", (float)currentRegenInterval, (float)currentRegenInterval); LogInfo("[Regen] " + GetNickname(playerAvatarField?.GetValue(playerHealth)) + " is alive and not full HP. Starting regen."); } if (isRegenActive && num >= num2) { StopRegenCycle(); LogInfo($"[Regen] {GetNickname(playerAvatarField?.GetValue(playerHealth))} reached max HP ({num2}). Regen cycle stopped."); } } private void PerformRegenTick() { int num = (int)healthField.GetValue(playerHealth); int num2 = (int)maxHealthField.GetValue(playerHealth); object avatarObj = playerAvatarField?.GetValue(playerHealth); string nickname = GetNickname(avatarObj); if (!isRegenActive || num == 0) { StopRegenCycle(); LogInfo("[Regen] Regen canceled. Reason: " + ((num == 0) ? "Health is 0" : "Regen inactive") + "."); return; } if (num >= num2) { StopRegenCycle(); LogInfo($"[Regen] {nickname} reached max HP ({num2}). Regen cycle stopped."); return; } int value = RegenAmountPerTick.Value; int num3 = Mathf.Min(num + value, num2); if (PhotonNetwork.IsConnected && (Object)(object)playerPhotonView != (Object)null) { playerPhotonView.RPC("UpdateHealthRPC", (RpcTarget)0, new object[3] { num3, num2, false }); } else { healthField.SetValue(playerHealth, num3); } LogInfo($"[Regen] {nickname} → +{value} → {num3}/{num2}"); } private void StopRegenCycle() { isRegenActive = false; ((MonoBehaviour)this).CancelInvoke("PerformRegenTick"); } private string GetNickname(object avatarObj) { try { PlayerAvatar val = (PlayerAvatar)((avatarObj is PlayerAvatar) ? avatarObj : null); if ((Object)(object)val != (Object)null && (Object)(object)val.photonView != (Object)null && val.photonView.Owner != null) { return val.photonView.Owner.NickName; } return "Unknown/Local"; } catch { return "Unknown/Local"; } } private void LogInfo(string msg) { if (DebugLoggingEnabled.Value) { Log.LogInfo((object)$"[{DateTime.Now:HH:mm:ss}] {msg}"); } } } public static ConfigEntry<int> BaseRegenIntervalSeconds; public static ConfigEntry<int> RegenAmountPerTick; public static ConfigEntry<bool> DebugLoggingEnabled; internal static ManualLogSource Log; private void Awake() { //IL_0041: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Expected O, but got Unknown //IL_0073: Unknown result type (might be due to invalid IL or missing references) //IL_007d: Expected O, but got Unknown //IL_00a7: Unknown result type (might be due to invalid IL or missing references) //IL_00ad: Expected O, but got Unknown Log = ((BaseUnityPlugin)this).Logger; ((BaseUnityPlugin)this).Logger.LogInfo((object)"[Init] HealthRegen is loading..."); BaseRegenIntervalSeconds = ((BaseUnityPlugin)this).Config.Bind<int>("Regen Settings", "BaseRegenIntervalSeconds", 20, new ConfigDescription("Time in seconds after damage before regen starts.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 20), Array.Empty<object>())); RegenAmountPerTick = ((BaseUnityPlugin)this).Config.Bind<int>("Regen Settings", "RegenAmountPerTick", 1, new ConfigDescription("Amount of HP restored per regen tick.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 50), Array.Empty<object>())); DebugLoggingEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("Debug Settings", "DebugLoggingEnabled", false, "Enable debug log output."); Harmony val = new Harmony("Xmods.healthregen"); val.PatchAll(); ((BaseUnityPlugin)this).Logger.LogInfo((object)"[Init] Patching complete."); } }