Added repair fires feature - v1.2.2

This commit is contained in:
2026-09-13 21:39:38 +02:00
parent c12dcceaf7
commit 0c58db1f62
11 changed files with 247 additions and 61 deletions
+1 -1
View File
@@ -6,7 +6,7 @@
<RootNamespace>AutoRefillFires</RootNamespace>
<LangVersion>latest</LangVersion>
<PluginVersion>1.2.1</PluginVersion>
<PluginVersion>1.2.2</PluginVersion>
<ValheimPath>D:\SteamLibrary\steamapps\common\Valheim</ValheimPath>
<R2ProfileName>Default</R2ProfileName>
+14 -4
View File
@@ -1,4 +1,4 @@
using BepInEx.Configuration;
using BepInEx.Configuration;
using UnityEngine;
namespace AutoRefillFires
@@ -28,13 +28,18 @@ namespace AutoRefillFires
public ConfigEntry<FuelSourcePriority> FuelSourcePriority { get; }
public ConfigEntry<bool> OnlyRefillOwnPieces { get; }
public ConfigEntry<bool> AutoRepair { get; }
public ConfigEntry<float> RepairBelowPercent { get; }
public ConfigEntry<bool> OnlyRepairOwnPieces { get; }
public ConfigEntry<KeyboardShortcut> ToggleHotkey { get; }
public ConfigEntry<ModLogLevel> 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.");
}
}
+21 -2
View File
@@ -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:
+3 -47
View File
@@ -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;
+55
View File
@@ -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;
}
}
}
+5 -2
View File
@@ -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);
}
+7 -2
View File
@@ -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);
}
+104
View File
@@ -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<WearNTear>();
if (wearNTear == null)
wearNTear = target.GetComponentInParent<WearNTear>();
if (wearNTear == null)
{
_log.Debug($"Skipping repair for '{target.gameObject.name}' - no WearNTear found.");
return;
}
ZNetView nview = wearNTear.GetComponent<ZNetView>();
if (nview == null)
nview = wearNTear.GetComponentInParent<ZNetView>();
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<Piece>();
if (piece == null)
piece = target.GetComponentInParent<Piece>();
if (piece == null)
return true;
return piece.GetCreator() == player.GetPlayerID();
}
}
}
+15
View File
@@ -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
+21 -2
View File
@@ -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:
+1 -1
View File
@@ -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"
]