Refactored into separated components

This commit is contained in:
2026-09-06 14:32:27 +02:00
parent 6519ec5d97
commit 073d20ff28
12 changed files with 761 additions and 1059 deletions
+195
View File
@@ -0,0 +1,195 @@
using UnityEngine;
namespace AutoRefillFires
{
internal class FireplaceRefiller
{
private readonly ModConfig _config;
private readonly FuelManager _fuelManager;
private readonly ModLogger _log;
public FireplaceRefiller(ModConfig config, FuelManager fuelManager, ModLogger log)
{
_config = config;
_fuelManager = fuelManager;
_log = log;
}
public void TryRefill(Player player, Fireplace fireplace, Container[] containers)
{
_log.Debug($"TryRefillFireplace START: '{fireplace.gameObject.name}'");
if (!ShouldRefillFireplace(fireplace))
{
_log.Debug($"Skipping '{fireplace.gameObject.name}' - type/config filter returned false.");
return;
}
if (_config.OnlyRefillOwnPieces.Value && !IsOwnPiece(player, fireplace))
{
_log.Debug($"Skipping '{fireplace.gameObject.name}' - not owned by local player.");
return;
}
ZNetView nview = fireplace.GetComponent<ZNetView>();
if (nview == null)
nview = fireplace.GetComponentInParent<ZNetView>();
if (nview == null)
{
_log.Debug($"Skipping '{fireplace.gameObject.name}' - no ZNetView found.");
return;
}
if (!nview.IsValid())
{
_log.Debug($"Skipping '{fireplace.gameObject.name}' - ZNetView is not valid.");
return;
}
ZDO zdo = nview.GetZDO();
if (zdo == null)
{
_log.Debug($"Skipping '{fireplace.gameObject.name}' - ZDO is null.");
return;
}
if (fireplace.m_fuelItem == null || fireplace.m_fuelItem.m_itemData == null || fireplace.m_fuelItem.m_itemData.m_shared == null)
{
_log.Debug($"Skipping '{fireplace.gameObject.name}' - fuel item is null.");
return;
}
float currentFuel = zdo.GetFloat(ZDOVars.s_fuel, 0f);
float maxFuel = fireplace.m_maxFuel;
if (maxFuel <= 0f)
{
_log.Debug($"Skipping '{fireplace.gameObject.name}' - maxFuel <= 0 ({maxFuel}).");
return;
}
float fuelPercent = currentFuel / maxFuel;
_log.Debug(
$"Fuel state for '{fireplace.gameObject.name}': " +
$"currentFuel={currentFuel:0.0}, maxFuel={maxFuel:0.0}, " +
$"fuelPercent={fuelPercent:0.00}, threshold={_config.RefillBelowPercent.Value:0.00}"
);
if (fuelPercent >= _config.RefillBelowPercent.Value)
{
_log.Debug($"Skipping '{fireplace.gameObject.name}' - fuelPercent >= threshold.");
return;
}
string fuelName = fireplace.m_fuelItem.m_itemData.m_shared.m_name;
int missingFuel = Mathf.CeilToInt(maxFuel - currentFuel);
if (missingFuel <= 0)
{
_log.Debug($"Skipping '{fireplace.gameObject.name}' - missingFuel <= 0 ({missingFuel}).");
return;
}
int requestedFuel = _config.RefillToMax.Value
? missingFuel
: Mathf.Min(Mathf.Max(_config.RefillAmount.Value, 0), missingFuel);
_log.Debug(
$"Refill request for '{fireplace.gameObject.name}': " +
$"fuel='{fuelName}', missingFuel={missingFuel}, requestedFuel={requestedFuel}, " +
$"refillMode={(_config.RefillToMax.Value ? "max" : "fixed")}"
);
if (requestedFuel <= 0)
{
_log.Debug($"Skipping '{fireplace.gameObject.name}' - requestedFuel <= 0.");
return;
}
int fuelConsumed = _fuelManager.ConsumeFuel(player, fireplace.transform, fuelName, requestedFuel, containers);
if (fuelConsumed <= 0)
{
_log.Debug($"No usable fuel found for '{fireplace.gameObject.name}'.");
return;
}
for (int i = 0; i < fuelConsumed; i++)
nview.InvokeRPC("RPC_AddFuel", new object[0]);
_log.Info(
$"Refilled {fireplace.name}: {currentFuel:0.0}/{maxFuel:0.0}, " +
$"fuel={fuelName}, added={fuelConsumed}, " +
$"mode={(_config.RefillToMax.Value ? "max" : "fixed")}"
);
}
private bool ShouldRefillFireplace(Fireplace fireplace)
{
string objectName = fireplace.gameObject.name.Replace("(Clone)", "").ToLowerInvariant();
bool result;
string matchedRule;
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";
}
_log.Debug(
$"ShouldRefillFireplace: name='{fireplace.gameObject.name}', " +
$"normalized='{objectName}', matchedRule={matchedRule}, result={result}"
);
return result;
}
private bool IsOwnPiece(Player player, Fireplace fireplace)
{
Piece piece = fireplace.GetComponent<Piece>();
if (piece == null)
piece = fireplace.GetComponentInParent<Piece>();
if (piece == null)
return true;
return piece.GetCreator() == player.GetPlayerID();
}
}
}
+127
View File
@@ -0,0 +1,127 @@
using UnityEngine;
namespace AutoRefillFires
{
internal class HotTubRefiller
{
private readonly ModConfig _config;
private readonly FuelManager _fuelManager;
private readonly ModLogger _log;
public HotTubRefiller(ModConfig config, FuelManager fuelManager, ModLogger log)
{
_config = config;
_fuelManager = fuelManager;
_log = log;
}
public void RefillNearby(Player player, Smelter[] smelters, Container[] containers)
{
int hotTubsInRange = 0;
foreach (Smelter smelter in smelters)
{
if (smelter == null)
continue;
string objectName = smelter.gameObject.name.Replace("(Clone)", "").ToLowerInvariant();
if (objectName != "piece_bathtub")
continue;
float distance = Vector3.Distance(player.transform.position, smelter.transform.position);
if (distance > _config.Radius.Value)
continue;
hotTubsInRange++;
_log.Debug(
$"Hot tub in range: name='{smelter.gameObject.name}', " +
$"distance={distance:0.0}m"
);
TryRefillHotTub(player, smelter, containers);
}
_log.Debug($"Hot tub scan end: inRange={hotTubsInRange}");
}
private void TryRefillHotTub(Player player, Smelter smelter, Container[] containers)
{
if (smelter == null)
return;
ZNetView nview = smelter.GetComponent<ZNetView>();
if (nview == null)
nview = smelter.GetComponentInParent<ZNetView>();
if (nview == null || !nview.IsValid())
{
_log.Debug("Hot tub: invalid ZNetView.");
return;
}
ZDO zdo = nview.GetZDO();
if (zdo == null)
{
_log.Debug("Hot tub: ZDO is null.");
return;
}
if (smelter.m_fuelItem == null || smelter.m_fuelItem.m_itemData == null || smelter.m_fuelItem.m_itemData.m_shared == null)
{
_log.Debug("Hot tub: fuel item is null.");
return;
}
string fuelName = smelter.m_fuelItem.m_itemData.m_shared.m_name;
float currentFuel = zdo.GetFloat(ZDOVars.s_fuel, 0f);
float maxFuel = smelter.m_maxFuel;
if (maxFuel <= 0f)
return;
float fuelPercent = currentFuel / maxFuel;
_log.Debug(
$"Hot tub fuel state: fuel='{fuelName}', " +
$"current={currentFuel:0.00}, max={maxFuel:0.00}, " +
$"percent={fuelPercent * 100f:0.0}%, threshold={_config.RefillBelowPercent.Value * 100f:0.0}%"
);
if (fuelPercent >= _config.RefillBelowPercent.Value)
{
_log.Debug("Skipping hot tub - fuelPercent >= threshold.");
return;
}
int missingFuel = Mathf.CeilToInt(maxFuel - currentFuel);
int requestedFuel = _config.RefillToMax.Value ? missingFuel : Mathf.Min(_config.RefillAmount.Value, missingFuel);
if (requestedFuel <= 0)
return;
_log.Debug($"Hot tub refill requested: missing={missingFuel}, requested={requestedFuel}");
int fuelConsumed = _fuelManager.ConsumeFuel(player, smelter.transform, fuelName, requestedFuel, containers);
if (fuelConsumed <= 0)
{
_log.Debug("Hot tub refill stopped: no usable fuel.");
return;
}
for (int i = 0; i < fuelConsumed; i++)
nview.InvokeRPC("RPC_AddFuel", new object[0]);
_log.Info(
$"Refilled hot tub: {currentFuel:0.0}/{maxFuel:0.0}, " +
$"fuel={fuelName}, added={fuelConsumed}, " +
$"mode={(_config.RefillToMax.Value ? "max" : "fixed")}"
);
}
}
}
+112
View File
@@ -0,0 +1,112 @@
using System.Collections.Generic;
using UnityEngine;
namespace AutoRefillFires
{
internal class RefillManager
{
private readonly ModConfig _config;
private readonly FireplaceRefiller _fireplaceRefiller;
private readonly HotTubRefiller _hotTubRefiller;
private readonly ModLogger _log;
public RefillManager(ModConfig config, ModLogger log)
{
_config = config;
_log = log;
FuelManager fuelManager = new FuelManager(_config, _log);
_fireplaceRefiller = new FireplaceRefiller(_config, fuelManager, _log);
_hotTubRefiller = new HotTubRefiller(_config, fuelManager, _log);
}
public void Run(Player player)
{
Fireplace[] fireplaces = Object.FindObjectsByType<Fireplace>(FindObjectsInactive.Exclude, FindObjectsSortMode.None);
Smelter[] smelters = null;
if (_config.FillHotTubs.Value)
smelters = Object.FindObjectsByType<Smelter>(FindObjectsInactive.Exclude, FindObjectsSortMode.None);
Container[] containers = null;
if (_config.UseNearbyContainers.Value)
containers = Object.FindObjectsByType<Container>(FindObjectsInactive.Exclude, FindObjectsSortMode.None);
List<FireplaceCandidate> candidates = new List<FireplaceCandidate>();
foreach (Fireplace fireplace in fireplaces)
{
if (fireplace == null)
continue;
float distance = Vector3.Distance(player.transform.position, fireplace.transform.position);
if (distance > _config.Radius.Value)
continue;
ZNetView nview = fireplace.GetComponent<ZNetView>();
if (nview == null)
nview = fireplace.GetComponentInParent<ZNetView>();
if (nview == null || !nview.IsValid())
continue;
ZDO zdo = nview.GetZDO();
if (zdo == null)
continue;
float maxFuel = fireplace.m_maxFuel;
if (maxFuel <= 0f)
continue;
float currentFuel = zdo.GetFloat(ZDOVars.s_fuel, 0f);
float fuelPercent = currentFuel / maxFuel;
candidates.Add(new FireplaceCandidate
{
Fireplace = fireplace,
Distance = distance,
FuelPercent = fuelPercent
});
}
// Priority: lowest fuel percentage first, then nearest fireplace.
candidates.Sort((a, b) =>
{
int fuelCompare = a.FuelPercent.CompareTo(b.FuelPercent);
if (fuelCompare != 0)
return fuelCompare;
return a.Distance.CompareTo(b.Distance);
});
_log.Debug(
$"Scan start: loadedFireplaces={fireplaces.Length}, " +
$"inRange={candidates.Count}, " +
$"loadedContainers={(containers != null ? containers.Length : 0)}, " +
$"radius={_config.Radius.Value:0.0}m"
);
foreach (FireplaceCandidate candidate in candidates)
{
_log.Debug(
$"Priority: name='{candidate.Fireplace.gameObject.name}', " +
$"fuel={candidate.FuelPercent * 100f:0.0}%, " +
$"distance={candidate.Distance:0.0}m"
);
_fireplaceRefiller.TryRefill(player, candidate.Fireplace, containers);
}
if (_config.FillHotTubs.Value && smelters != null)
_hotTubRefiller.RefillNearby(player, smelters, containers);
_log.Debug("Scan end.");
}
}
}