diff --git a/AutoRefillFires.csproj b/AutoRefillFires.csproj
index 5973c22..9241502 100644
--- a/AutoRefillFires.csproj
+++ b/AutoRefillFires.csproj
@@ -6,7 +6,7 @@
AutoRefillFires
latest
- 1.2.1
+ 1.2.2
D:\SteamLibrary\steamapps\common\Valheim
Default
diff --git a/Configuration/ModConfig.cs b/Configuration/ModConfig.cs
index 41bf103..3624fb8 100644
--- a/Configuration/ModConfig.cs
+++ b/Configuration/ModConfig.cs
@@ -1,4 +1,4 @@
-using BepInEx.Configuration;
+using BepInEx.Configuration;
using UnityEngine;
namespace AutoRefillFires
@@ -28,13 +28,18 @@ namespace AutoRefillFires
public ConfigEntry FuelSourcePriority { get; }
public ConfigEntry OnlyRefillOwnPieces { get; }
+
+ public ConfigEntry AutoRepair { get; }
+ public ConfigEntry RepairBelowPercent { get; }
+ public ConfigEntry OnlyRepairOwnPieces { get; }
+
public ConfigEntry ToggleHotkey { get; }
public ConfigEntry LogLevel { get; }
public ModConfig(ConfigFile config)
{
- Radius = config.Bind("General", "Radius", 20f, "Refill fireplaces within this radius around the player.");
- CheckInterval = config.Bind("General", "CheckInterval", 3f, "How often fireplaces are checked, in seconds.");
+ Radius = config.Bind("General", "Radius", 20f, "Refill and repair supported objects within this radius around the player.");
+ CheckInterval = config.Bind("General", "CheckInterval", 3f, "How often supported objects are checked, in seconds.");
RefillBelowPercent = config.Bind("General", "RefillBelowPercent", 0.75f, "Refill when fuel drops below this percentage.");
RefillToMax = config.Bind("General", "RefillToMax", true, "If true, refill fireplaces to maximum fuel. If false, add only RefillAmount fuel.");
RefillAmount = config.Bind("General", "RefillAmount", 5, "Amount of fuel to add when RefillToMax is false.");
@@ -51,10 +56,15 @@ namespace AutoRefillFires
FillHotTubs = config.Bind("Fireplace Types", "FillHotTubs", true, "Automatically refill hot tubs.");
FillOtherFireplaces = config.Bind("Fireplace Types", "FillOtherFireplaces", true, "Automatically refill unknown or modded Fireplace-based objects.");
- ToggleHotkey = config.Bind("General", "ToggleHotkey", new KeyboardShortcut(KeyCode.F7), "Hotkey used to enable or disable automatic refilling.");
+ ToggleHotkey = config.Bind("General", "ToggleHotkey", new KeyboardShortcut(KeyCode.F7), "Hotkey used to enable or disable automatic refilling and repair.");
KeepFuelReserve = config.Bind("Fuel", "KeepFuelReserve", 0, "Minimum amount of fuel to keep in the source inventory. 10 means the last 10 Wood/Resin will not be used.");
FuelSourcePriority = config.Bind("Fuel", "FuelSourcePriority", AutoRefillFires.FuelSourcePriority.PlayerFirst, "Select whether player inventory or nearby containers should be used first.");
OnlyRefillOwnPieces = config.Bind("General", "OnlyRefillOwnPieces", false, "If enabled, only refill fireplaces and torches built by the local player.");
+
+ AutoRepair = config.Bind("Repair", "AutoRepair", false, "Automatically repair supported objects whose corresponding Fill* option is enabled.");
+ RepairBelowPercent = config.Bind("Repair", "RepairBelowPercent", 0.75f, "Repair supported objects when their health drops below this percentage. Example: 0.75 = 75%.");
+ OnlyRepairOwnPieces = config.Bind("Repair", "OnlyRepairOwnPieces", false, "If enabled, only automatically repair supported objects built by the local player.");
+
LogLevel = config.Bind("Logging", "LogLevel", ModLogLevel.Info, "Logging verbosity. Available values: None, Error, Warning, Info, Debug.");
}
}
diff --git a/README.md b/README.md
index b105c34..af7d6fc 100644
--- a/README.md
+++ b/README.md
@@ -3,9 +3,11 @@
A lightweight BepInEx mod for Valheim that automatically refills nearby fireplaces and torches.
-## What's New in 1.2.1
+## What's New in 1.2.2
##### [Full CHANGELOG](https://github.com/LabodiDavid/AutoRefillFires/blob/main/Thunderstore/CHANGELOG.md)
-- Support for Valheim 1.0 Deep North update
+- Added optional automatic repair for all supported refillable object types.
+- Repair follows the existing `Fill*` type toggles.
+- Added configurable repair health threshold and own-piece restriction.
## Features
@@ -14,6 +16,7 @@ A lightweight BepInEx mod for Valheim that automatically refills nearby fireplac
- Configurable refill radius and threshold
- Refill to maximum or by a fixed amount
- Individual enable/disable options for fireplace types
+- Optional automatic repair for supported refillable objects; repair follows the existing `Fill*` type toggles
## Configuration
@@ -31,6 +34,22 @@ Pressing the hotkey toggles Auto Refill Fires on or off.
When disabled, the configuration file is automatically reloaded, allowing most settings to be changed without restarting Valheim.
+### Auto Repair Fires
+
+Automatic repair is disabled by default. Enable it with:
+
+`AutoRepair = true` in the config file.
+
+By default supported objects are repaired when their health falls below 75%:
+
+`RepairBelowPercent = 0.75`
+
+Repair follows the existing `Fill*` type toggles. For example, if `FillHearths = true`, Hearths can also be repaired; if `FillHearths = false`, they are ignored by both refill and repair. The same rule applies to campfires, standing/wall torches, braziers, bonfires, Hot Tubs and compatible `OtherFireplaces`.
+
+Set `OnlyRepairOwnPieces = true` to restrict automatic repair to pieces built by the local player.
+
+The repair logic reuses the existing fireplace and Hot Tub scans, so enabling repair does not add another scene-wide search. Resin candles remain ignored because they are consumable, non-refillable light sources.
+
### Fuel Reserve
Example:
diff --git a/Refill/FireplaceRefiller.cs b/Refill/FireplaceRefiller.cs
index 005f1f9..bb8c82f 100644
--- a/Refill/FireplaceRefiller.cs
+++ b/Refill/FireplaceRefiller.cs
@@ -1,4 +1,4 @@
-using UnityEngine;
+using UnityEngine;
namespace AutoRefillFires
{
@@ -130,55 +130,11 @@ namespace AutoRefillFires
private bool ShouldRefillFireplace(Fireplace fireplace)
{
- string objectName = fireplace.gameObject.name.Replace("(Clone)", "").ToLowerInvariant();
-
- bool result;
- string matchedRule;
-
- if (objectName.Contains("candle"))
- {
- result = false;
- matchedRule = "IgnoredCandle";
- }
- if (objectName.Contains("fire_pit") || objectName.Contains("firepit"))
- {
- result = _config.FillCampfires.Value;
- matchedRule = "FillCampfires";
- }
- else if (objectName.Contains("hearth"))
- {
- result = _config.FillHearths.Value;
- matchedRule = "FillHearths";
- }
- else if (objectName.Contains("groundtorch"))
- {
- result = _config.FillStandingTorches.Value;
- matchedRule = "FillStandingTorches";
- }
- else if (objectName.Contains("walltorch"))
- {
- result = _config.FillWallTorches.Value;
- matchedRule = "FillWallTorches";
- }
- else if (objectName.Contains("brazier"))
- {
- result = _config.FillBraziers.Value;
- matchedRule = "FillBraziers";
- }
- else if (objectName.Contains("bonfire"))
- {
- result = _config.FillBonfires.Value;
- matchedRule = "FillBonfires";
- }
- else
- {
- result = _config.FillOtherFireplaces.Value;
- matchedRule = "FillOtherFireplaces";
- }
+ bool result = FireplaceTypeFilter.IsEnabled(_config, fireplace, out string matchedRule);
_log.Debug(
$"ShouldRefillFireplace: name='{fireplace.gameObject.name}', " +
- $"normalized='{objectName}', matchedRule={matchedRule}, result={result}"
+ $"matchedRule={matchedRule}, result={result}"
);
return result;
diff --git a/Refill/FireplaceTypeFilter.cs b/Refill/FireplaceTypeFilter.cs
new file mode 100644
index 0000000..9395e27
--- /dev/null
+++ b/Refill/FireplaceTypeFilter.cs
@@ -0,0 +1,55 @@
+namespace AutoRefillFires
+{
+ internal static class FireplaceTypeFilter
+ {
+ public static bool IsEnabled(ModConfig config, Fireplace fireplace, out string matchedRule)
+ {
+ string objectName = fireplace.gameObject.name.Replace("(Clone)", "").ToLowerInvariant();
+
+ if (objectName.Contains("candle"))
+ {
+ matchedRule = "IgnoredCandle";
+ return false;
+ }
+
+ if (objectName.Contains("fire_pit") || objectName.Contains("firepit"))
+ {
+ matchedRule = "FillCampfires";
+ return config.FillCampfires.Value;
+ }
+
+ if (objectName.Contains("hearth"))
+ {
+ matchedRule = "FillHearths";
+ return config.FillHearths.Value;
+ }
+
+ if (objectName.Contains("groundtorch"))
+ {
+ matchedRule = "FillStandingTorches";
+ return config.FillStandingTorches.Value;
+ }
+
+ if (objectName.Contains("walltorch"))
+ {
+ matchedRule = "FillWallTorches";
+ return config.FillWallTorches.Value;
+ }
+
+ if (objectName.Contains("brazier"))
+ {
+ matchedRule = "FillBraziers";
+ return config.FillBraziers.Value;
+ }
+
+ if (objectName.Contains("bonfire"))
+ {
+ matchedRule = "FillBonfires";
+ return config.FillBonfires.Value;
+ }
+
+ matchedRule = "FillOtherFireplaces";
+ return config.FillOtherFireplaces.Value;
+ }
+ }
+}
diff --git a/Refill/HotTubRefiller.cs b/Refill/HotTubRefiller.cs
index 8e7bdd3..54ef7be 100644
--- a/Refill/HotTubRefiller.cs
+++ b/Refill/HotTubRefiller.cs
@@ -1,4 +1,4 @@
-using UnityEngine;
+using UnityEngine;
namespace AutoRefillFires
{
@@ -6,12 +6,14 @@ namespace AutoRefillFires
{
private readonly ModConfig _config;
private readonly FuelManager _fuelManager;
+ private readonly RepairManager _repairManager;
private readonly ModLogger _log;
- public HotTubRefiller(ModConfig config, FuelManager fuelManager, ModLogger log)
+ public HotTubRefiller(ModConfig config, FuelManager fuelManager, RepairManager repairManager, ModLogger log)
{
_config = config;
_fuelManager = fuelManager;
+ _repairManager = repairManager;
_log = log;
}
@@ -41,6 +43,7 @@ namespace AutoRefillFires
$"distance={distance:0.0}m"
);
+ _repairManager.TryRepair(player, smelter, "hot tub");
TryRefillHotTub(player, smelter, containers);
}
diff --git a/Refill/RefillManager.cs b/Refill/RefillManager.cs
index 2b4aaf8..fc1f7fa 100644
--- a/Refill/RefillManager.cs
+++ b/Refill/RefillManager.cs
@@ -1,4 +1,4 @@
-using System.Collections.Generic;
+using System.Collections.Generic;
using UnityEngine;
namespace AutoRefillFires
@@ -8,6 +8,7 @@ namespace AutoRefillFires
private readonly ModConfig _config;
private readonly FireplaceRefiller _fireplaceRefiller;
private readonly HotTubRefiller _hotTubRefiller;
+ private readonly RepairManager _repairManager;
private readonly ModLogger _log;
public RefillManager(ModConfig config, ModLogger log)
@@ -17,7 +18,8 @@ namespace AutoRefillFires
FuelManager fuelManager = new FuelManager(_config, _log);
_fireplaceRefiller = new FireplaceRefiller(_config, fuelManager, _log);
- _hotTubRefiller = new HotTubRefiller(_config, fuelManager, _log);
+ _repairManager = new RepairManager(_config, _log);
+ _hotTubRefiller = new HotTubRefiller(_config, fuelManager, _repairManager, _log);
}
public void Run(Player player)
@@ -100,6 +102,9 @@ namespace AutoRefillFires
$"distance={candidate.Distance:0.0}m"
);
+ if (FireplaceTypeFilter.IsEnabled(_config, candidate.Fireplace, out string matchedRule))
+ _repairManager.TryRepair(player, candidate.Fireplace, matchedRule);
+
_fireplaceRefiller.TryRefill(player, candidate.Fireplace, containers);
}
diff --git a/Repair/RepairManager.cs b/Repair/RepairManager.cs
new file mode 100644
index 0000000..baab081
--- /dev/null
+++ b/Repair/RepairManager.cs
@@ -0,0 +1,104 @@
+using UnityEngine;
+
+namespace AutoRefillFires
+{
+ internal class RepairManager
+ {
+ private readonly ModConfig _config;
+ private readonly ModLogger _log;
+
+ public RepairManager(ModConfig config, ModLogger log)
+ {
+ _config = config;
+ _log = log;
+ }
+
+ public void TryRepair(Player player, Component target, string label)
+ {
+ if (!_config.AutoRepair.Value || target == null)
+ return;
+
+ if (_config.OnlyRepairOwnPieces.Value && !IsOwnPiece(player, target))
+ {
+ _log.Debug($"Skipping repair for '{target.gameObject.name}' - not owned by local player.");
+ return;
+ }
+
+ WearNTear wearNTear = target.GetComponent();
+
+ if (wearNTear == null)
+ wearNTear = target.GetComponentInParent();
+
+ if (wearNTear == null)
+ {
+ _log.Debug($"Skipping repair for '{target.gameObject.name}' - no WearNTear found.");
+ return;
+ }
+
+ ZNetView nview = wearNTear.GetComponent();
+
+ if (nview == null)
+ nview = wearNTear.GetComponentInParent();
+
+ if (nview == null || !nview.IsValid())
+ {
+ _log.Debug($"Skipping repair for '{target.gameObject.name}' - invalid ZNetView.");
+ return;
+ }
+
+ ZDO zdo = nview.GetZDO();
+
+ if (zdo == null)
+ {
+ _log.Debug($"Skipping repair for '{target.gameObject.name}' - ZDO is null.");
+ return;
+ }
+
+ float maxHealth = wearNTear.m_health;
+
+ if (maxHealth <= 0f)
+ {
+ _log.Debug($"Skipping repair for '{target.gameObject.name}' - max health <= 0 ({maxHealth}).");
+ return;
+ }
+
+ float currentHealth = zdo.GetFloat(ZDOVars.s_health, maxHealth);
+ float healthPercent = currentHealth / maxHealth;
+ float threshold = Mathf.Clamp01(_config.RepairBelowPercent.Value);
+
+ _log.Debug(
+ $"Repair state: type={label}, name='{target.gameObject.name}', " +
+ $"health={currentHealth:0.0}/{maxHealth:0.0} ({healthPercent * 100f:0.0}%), " +
+ $"threshold={threshold * 100f:0.0}%"
+ );
+
+ if (healthPercent >= threshold)
+ return;
+
+ if (wearNTear.Repair())
+ {
+ _log.Info(
+ $"Repaired {label}: {target.gameObject.name}, " +
+ $"{currentHealth:0.0}/{maxHealth:0.0} ({healthPercent * 100f:0.0}% -> 100%)"
+ );
+ }
+ else
+ {
+ _log.Debug($"Repair request for '{target.gameObject.name}' returned false.");
+ }
+ }
+
+ private static bool IsOwnPiece(Player player, Component target)
+ {
+ Piece piece = target.GetComponent();
+
+ if (piece == null)
+ piece = target.GetComponentInParent();
+
+ if (piece == null)
+ return true;
+
+ return piece.GetCreator() == player.GetPlayerID();
+ }
+ }
+}
diff --git a/Thunderstore/CHANGELOG.md b/Thunderstore/CHANGELOG.md
index 107acf2..6251556 100644
--- a/Thunderstore/CHANGELOG.md
+++ b/Thunderstore/CHANGELOG.md
@@ -2,6 +2,21 @@
All notable changes to Auto Refill Fires will be documented in this file.
+## [1.2.2] - 2026-09-13
+
+### Added
+
+- Added optional automatic repair for all supported refillable object types.
+- Added `AutoRepair` master configuration option.
+- Repair follows the existing `FillCampfires`, `FillHearths`, `FillStandingTorches`, `FillWallTorches`, `FillBraziers`, `FillBonfires`, `FillHotTubs` and `FillOtherFireplaces` toggles.
+- Added `RepairBelowPercent` configuration option to control the health threshold that triggers repair.
+- Added `OnlyRepairOwnPieces` configuration option.
+- Repair reuses the existing fireplace and Hot Tub scans and does not add another scene-wide object search.
+
+### Fixed
+
+- Fixed Resin candles being able to fall through to `FillOtherFireplaces` despite the candle ignore rule.
+
## [1.2.1] - 2026-09-09
### Added
diff --git a/Thunderstore/README.md b/Thunderstore/README.md
index b105c34..ac21fb4 100644
--- a/Thunderstore/README.md
+++ b/Thunderstore/README.md
@@ -3,9 +3,11 @@
A lightweight BepInEx mod for Valheim that automatically refills nearby fireplaces and torches.
-## What's New in 1.2.1
+## What's New in 1.2.2
##### [Full CHANGELOG](https://github.com/LabodiDavid/AutoRefillFires/blob/main/Thunderstore/CHANGELOG.md)
-- Support for Valheim 1.0 Deep North update
+- Added optional automatic repair for all supported refillable object types.
+- Repair follows the existing `Fill*` type toggles, including Hot Tubs.
+- Added configurable repair health threshold and own-piece restriction.
## Features
@@ -14,6 +16,7 @@ A lightweight BepInEx mod for Valheim that automatically refills nearby fireplac
- Configurable refill radius and threshold
- Refill to maximum or by a fixed amount
- Individual enable/disable options for fireplace types
+- Optional automatic repair for supported refillable objects; repair follows the existing `Fill*` type toggles
## Configuration
@@ -31,6 +34,22 @@ Pressing the hotkey toggles Auto Refill Fires on or off.
When disabled, the configuration file is automatically reloaded, allowing most settings to be changed without restarting Valheim.
+### Auto Repair Fires
+
+Automatic repair is disabled by default. Enable it with:
+
+`AutoRepair = true` in the config file.
+
+By default supported objects are repaired when their health falls below 75%:
+
+`RepairBelowPercent = 0.75`
+
+Repair follows the existing `Fill*` type toggles. For example, if `FillHearths = true`, Hearths can also be repaired; if `FillHearths = false`, they are ignored by both refill and repair. The same rule applies to campfires, standing/wall torches, braziers, bonfires, Hot Tubs and compatible `OtherFireplaces`.
+
+Set `OnlyRepairOwnPieces = true` to restrict automatic repair to pieces built by the local player.
+
+The repair logic reuses the existing fireplace and Hot Tub scans, so enabling repair does not add another scene-wide search. Resin candles remain ignored because they are consumable, non-refillable light sources.
+
### Fuel Reserve
Example:
diff --git a/Thunderstore/manifest.json b/Thunderstore/manifest.json
index 172d770..ffb2bd2 100644
--- a/Thunderstore/manifest.json
+++ b/Thunderstore/manifest.json
@@ -2,7 +2,7 @@
"name": "AutoRefillFires",
"version_number": "__VERSION__",
"website_url": "https://github.com/LabodiDavid/AutoRefillFires",
- "description": "Automatically refills nearby campfires, hearths and torches using fuel from the player inventory or optionally nearby containers.",
+ "description": "Automatically refills nearby fires from player or container fuel, with optional automatic repair for supported refillable objects.",
"dependencies": [
"denikson-BepInExPack_Valheim-5.4.2350"
]