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 RhythmicRepairs v1.0.0
RhythmicRepairs.dll
Decompiled 3 days agousing System; using System.Collections; using System.Diagnostics; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Versioning; using BepInEx; using BepInEx.Configuration; using HarmonyLib; using UnityEngine; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)] [assembly: AssemblyTitle("Rhythmic Repairs")] [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("")] [assembly: AssemblyProduct("Rhythmic Repairs")] [assembly: AssemblyCopyright("Copyright © 2026")] [assembly: AssemblyTrademark("")] [assembly: ComVisible(false)] [assembly: Guid("69840b67-9e2e-4e40-97a6-bfcd82234ddf")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")] [assembly: AssemblyVersion("1.0.0.0")] namespace RhythmicRepairs { [BepInPlugin("petri.valheim.rhythmicrepairs", "Rhythmic Repairs", "1.0.0")] public class Plugin : BaseUnityPlugin { internal enum RepairTriggerMode { OnClick, OnOpen, Both } public const string ModGuid = "petri.valheim.rhythmicrepairs"; public const string ModName = "Rhythmic Repairs"; public const string ModVersion = "1.0.0"; internal static ConfigEntry<bool> EnableMod; internal static ConfigEntry<RepairTriggerMode> RepairTrigger; internal static ConfigEntry<float> RepairDelaySeconds; internal static ConfigEntry<int> MaxRepairsPerClick; internal static ConfigEntry<bool> DebugLogging; private static MethodInfo haveRepairableItemsMethod; private static MethodInfo repairOneItemMethod; private Harmony harmony; private Coroutine repairRoutine; internal static Plugin Instance { get; private set; } internal static bool IsVanillaRepairCallInProgress { get; private set; } internal static bool IsRepairSequenceRunning => (Object)(object)Instance != (Object)null && Instance.repairRoutine != null; private void Awake() { //IL_012d: Unknown result type (might be due to invalid IL or missing references) //IL_0137: Expected O, but got Unknown Instance = this; EnableMod = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "EnableMod", true, "Enable or disable the mod."); RepairTrigger = ((BaseUnityPlugin)this).Config.Bind<RepairTriggerMode>("Repair", "RepairTrigger", RepairTriggerMode.OnClick, "Controls when repair-all is triggered."); RepairDelaySeconds = ((BaseUnityPlugin)this).Config.Bind<float>("Repair", "RepairDelaySeconds", 0.12f, "Delay in seconds between each repaired item. Higher values preserve a clearer repair rhythm."); MaxRepairsPerClick = ((BaseUnityPlugin)this).Config.Bind<int>("Repair", "MaxRepairsPerClick", 100, "Safety limit for how many items can be repaired from one repair action."); DebugLogging = ((BaseUnityPlugin)this).Config.Bind<bool>("Debug", "DebugLogging", false, "Enable debug logging."); haveRepairableItemsMethod = AccessTools.Method(typeof(InventoryGui), "HaveRepairableItems", (Type[])null, (Type[])null); repairOneItemMethod = AccessTools.Method(typeof(InventoryGui), "RepairOneItem", (Type[])null, (Type[])null); if (haveRepairableItemsMethod == null) { ((BaseUnityPlugin)this).Logger.LogWarning((object)"Rhythmic Repairs: could not find InventoryGui.HaveRepairableItems."); } if (repairOneItemMethod == null) { ((BaseUnityPlugin)this).Logger.LogWarning((object)"Rhythmic Repairs: could not find InventoryGui.RepairOneItem."); } harmony = new Harmony("petri.valheim.rhythmicrepairs"); harmony.PatchAll(); ((BaseUnityPlugin)this).Logger.LogInfo((object)"Rhythmic Repairs 1.0.0 loaded."); } private void OnDestroy() { Harmony obj = harmony; if (obj != null) { obj.UnpatchSelf(); } if ((Object)(object)Instance == (Object)(object)this) { Instance = null; } } internal void StartRepairSequence(InventoryGui inventoryGui) { if (!((Object)(object)inventoryGui == (Object)null)) { if (repairRoutine != null) { DebugLog("Repair sequence already running."); } else { repairRoutine = ((MonoBehaviour)this).StartCoroutine(RepairAllRoutine(inventoryGui)); } } } private IEnumerator RepairAllRoutine(InventoryGui inventoryGui) { int repairedCount = 0; int maxRepairs = Mathf.Max(1, MaxRepairsPerClick.Value); DebugLog("Repair sequence started."); while (EnableMod.Value && (Object)(object)inventoryGui != (Object)null && repairedCount < maxRepairs && HaveRepairableItems(inventoryGui) && InvokeVanillaRepairOneItem(inventoryGui)) { repairedCount++; float delay = Mathf.Max(0f, RepairDelaySeconds.Value); if (delay > 0f) { yield return (object)new WaitForSeconds(delay); } else { yield return null; } } if (repairedCount >= maxRepairs) { ((BaseUnityPlugin)this).Logger.LogWarning((object)$"Rhythmic Repairs: stopped after safety limit of {maxRepairs} repair(s)."); } DebugLog($"Repair sequence finished. Repaired {repairedCount} item(s)."); repairRoutine = null; } private static bool HaveRepairableItems(InventoryGui inventoryGui) { if ((Object)(object)inventoryGui == (Object)null || haveRepairableItemsMethod == null) { return false; } try { return (bool)haveRepairableItemsMethod.Invoke(inventoryGui, null); } catch (Exception arg) { Plugin instance = Instance; if (instance != null) { ((BaseUnityPlugin)instance).Logger.LogError((object)$"Rhythmic Repairs: HaveRepairableItems failed: {arg}"); } return false; } } private static bool InvokeVanillaRepairOneItem(InventoryGui inventoryGui) { if ((Object)(object)inventoryGui == (Object)null || repairOneItemMethod == null) { return false; } try { IsVanillaRepairCallInProgress = true; repairOneItemMethod.Invoke(inventoryGui, null); return true; } catch (Exception arg) { Plugin instance = Instance; if (instance != null) { ((BaseUnityPlugin)instance).Logger.LogError((object)$"Rhythmic Repairs: RepairOneItem failed: {arg}"); } return false; } finally { IsVanillaRepairCallInProgress = false; } } internal void TryStartAutoRepairOnStationOpen(InventoryGui inventoryGui) { if (!((Object)(object)inventoryGui == (Object)null) && EnableMod.Value && ShouldRepairOnOpen() && !IsVanillaRepairCallInProgress && !IsRepairSequenceRunning && HaveRepairableItems(inventoryGui)) { DebugLog("Auto repair trigger detected from station UI."); StartRepairSequence(inventoryGui); } } internal static void DebugLog(string message) { ConfigEntry<bool> debugLogging = DebugLogging; if (debugLogging != null && debugLogging.Value) { Plugin instance = Instance; if (instance != null) { ((BaseUnityPlugin)instance).Logger.LogInfo((object)("Rhythmic Repairs: " + message)); } } } internal static bool ShouldRepairOnClick() { return RepairTrigger.Value == RepairTriggerMode.OnClick || RepairTrigger.Value == RepairTriggerMode.Both; } internal static bool ShouldRepairOnOpen() { return RepairTrigger.Value == RepairTriggerMode.OnOpen || RepairTrigger.Value == RepairTriggerMode.Both; } } } namespace RhythmicRepairs.Patches { [HarmonyPatch(typeof(InventoryGui), "RepairOneItem")] public static class InventoryGuiRepairOneItemPatch { private static bool Prefix(InventoryGui __instance) { if ((Object)(object)Plugin.Instance == (Object)null) { return true; } if (!Plugin.EnableMod.Value) { return true; } if (!Plugin.ShouldRepairOnClick()) { return true; } if (Plugin.IsVanillaRepairCallInProgress) { return true; } if (Plugin.IsRepairSequenceRunning) { Plugin.DebugLog("Ignored repair click because repair sequence is already running."); return false; } Plugin.Instance.StartRepairSequence(__instance); return false; } } [HarmonyPatch(typeof(InventoryGui), "UpdateRepair")] public static class InventoryGuiUpdateRepairPatch { private static void Postfix(InventoryGui __instance) { if (!((Object)(object)Plugin.Instance == (Object)null)) { Plugin.Instance.TryStartAutoRepairOnStationOpen(__instance); } } } }