Improve ObjectFieldMultiplier with naming conventions and documentation

This commit is contained in:
2025-02-24 00:26:12 +01:00
parent c8302ea177
commit fd8ce5c59e

View File

@@ -4,101 +4,111 @@ using BepInEx.Configuration;
using HarmonyLib; using HarmonyLib;
namespace TerraTech { namespace TerraTech {
public class MultipliedField<TObject, TValue> { /// <summary>
private readonly string fieldName; /// Represents a field that can be multiplied by a configurable value
private readonly ConfigEntry<TValue> multiplier; /// </summary>
private readonly Traverse parentTraverse; /// <typeparam name="TValue">The type of the field value</typeparam>
private TValue originalValue; public class MultipliedField<TValue> {
private readonly string _fieldName;
private readonly ConfigEntry<TValue> _multiplier;
private readonly Traverse _parentTraverse;
private TValue _originalValue;
public MultipliedField(string fieldName, ConfigEntry<TValue> multiplier, Traverse parentTraverse) { public MultipliedField(string fieldName, ConfigEntry<TValue> multiplier, Traverse parentTraverse) {
this.fieldName = fieldName; _fieldName = fieldName;
this.multiplier = multiplier; _multiplier = multiplier;
this.parentTraverse = parentTraverse; _parentTraverse = parentTraverse;
if (!parentTraverse.Field(fieldName).FieldExists()) { if (!parentTraverse.Field(fieldName).FieldExists()) {
throw new ArgumentException( throw new ArgumentException(
string.Format("Field {0} does not exist on {1}", fieldName, parentTraverse.ToString())); string.Format("Field {0} does not exist on {1}", fieldName, parentTraverse));
} }
} }
public TValue GetValue() { public TValue GetValue() {
var value = parentTraverse.Field(fieldName).GetValue(); var value = _parentTraverse.Field(_fieldName).GetValue();
if (value == null) if (value == null)
throw new InvalidOperationException(string.Format("Field {0} returned null", fieldName)); throw new InvalidOperationException(string.Format("Field {0} returned null", _fieldName));
return (TValue)value; return (TValue)value;
} }
public void SetValue(TValue value) { public void SetValue(TValue value) {
parentTraverse.Field(fieldName).SetValue(value); _parentTraverse.Field(_fieldName).SetValue(value);
var verifyValue = GetValue(); var verifyValue = GetValue();
if (!verifyValue.Equals(value)) if (!verifyValue.Equals(value))
throw new InvalidOperationException( throw new InvalidOperationException(
string.Format("Field {0} set to {1} but read back as {2}", fieldName, value, verifyValue)); string.Format("Field {0} set to {1} but read back as {2}", _fieldName, value, verifyValue));
} }
public void CaptureOriginal() { public void CaptureOriginal() {
originalValue = GetValue(); _originalValue = GetValue();
if (Main.debug.Value) if (Main.debug.Value)
Console.WriteLine("Captured original value for {0}: {1}", fieldName, originalValue); Console.WriteLine("Captured original value for {0}: {1}", _fieldName, _originalValue);
} }
public void Apply() { public void Apply() {
try { try {
dynamic originalDynamic = originalValue; dynamic originalDynamic = _originalValue;
dynamic multiplierDynamic = multiplier.Value; dynamic multiplierDynamic = _multiplier.Value;
var newValue = (TValue)(originalDynamic * multiplierDynamic); var newValue = (TValue)(originalDynamic * multiplierDynamic);
if (Main.debug.Value) if (Main.debug.Value)
Console.WriteLine("Applying to {0}: {1} * {2} = {3}", fieldName, originalValue, multiplier.Value, newValue); Console.WriteLine("Applying to {0}: {1} * {2} = {3}", _fieldName, _originalValue, _multiplier.Value,
newValue);
SetValue(newValue); SetValue(newValue);
} catch (Exception e) { } catch (Exception e) {
throw new InvalidOperationException(string.Format("Failed to apply multiplication to {0}", fieldName), throw new InvalidOperationException(string.Format("Failed to apply multiplication to {0}", _fieldName),
e); e);
} }
} }
public void Restore() { public void Restore() {
if (Main.debug.Value) if (Main.debug.Value)
Console.WriteLine("Restoring {0} to original value: {1}", fieldName, originalValue); Console.WriteLine("Restoring {0} to original value: {1}", _fieldName, _originalValue);
SetValue(originalValue); SetValue(_originalValue);
} }
public void LogValue(string prefix) { public void LogValue(string prefix) {
if (!Main.debug.Value) if (!Main.debug.Value)
return; return;
var currentValue = GetValue(); var currentValue = GetValue();
Console.WriteLine("{0} {1}; {2}: {3} (original: {4}, multiplier: {5})", prefix, parentTraverse, fieldName, currentValue, originalValue, multiplier.Value); Console.WriteLine("{0} {1}; {2}: {3} (original: {4}, multiplier: {5})", prefix, _parentTraverse, _fieldName,
currentValue, _originalValue, _multiplier.Value);
} }
} }
/// <summary>
/// Represents an object with multiple fields that can be multiplied
/// </summary>
/// <typeparam name="T">The type of the object being managed</typeparam>
public class MultipliedObject<T> { public class MultipliedObject<T> {
private readonly Traverse objectTraverse; private readonly Traverse _objectTraverse;
private readonly List<MultipliedField<T, float>> fields; private readonly List<MultipliedField<float>> _fields;
public MultipliedObject(T instance) { public MultipliedObject(T instance) {
objectTraverse = Traverse.Create(instance); _objectTraverse = Traverse.Create(instance);
fields = new List<MultipliedField<T, float>>(); _fields = new List<MultipliedField<float>>();
} }
public void AddField(string fieldName, ConfigEntry<float> multiplier) { public void AddField(string fieldName, ConfigEntry<float> multiplier) {
fields.Add(new MultipliedField<T, float>(fieldName, multiplier, objectTraverse)); _fields.Add(new MultipliedField<float>(fieldName, multiplier, _objectTraverse));
} }
public void CaptureFrom() { public void CaptureFrom() {
foreach (var field in fields) { foreach (var field in _fields) {
field.CaptureOriginal(); field.CaptureOriginal();
} }
} }
public void ApplyTo() { public void ApplyTo() {
foreach (var field in fields) { foreach (var field in _fields) {
field.Apply(); field.Apply();
} }
} }
public void RestoreTo() { public void RestoreTo() {
foreach (var field in fields) { foreach (var field in _fields) {
field.Restore(); field.Restore();
} }
} }
@@ -106,31 +116,35 @@ namespace TerraTech {
public void LogValues(string prefix) { public void LogValues(string prefix) {
if (!Main.debug.Value) if (!Main.debug.Value)
return; return;
foreach (var field in fields) { foreach (var field in _fields) {
field.LogValue(prefix); field.LogValue(prefix);
} }
} }
} }
/// <summary>
/// Manages a collection of objects whose fields can be multiplied
/// </summary>
/// <typeparam name="T">The type of objects being managed</typeparam>
public class MultipliedObjectManager<T> public class MultipliedObjectManager<T>
where T : class { where T : class {
private readonly Dictionary<T, MultipliedObject<T>> managedObjects; private readonly Dictionary<T, MultipliedObject<T>> _managedObjects;
private readonly Action<MultipliedObject<T>> configureObject; private readonly Action<MultipliedObject<T>> _configureObject;
public MultipliedObjectManager(Action<MultipliedObject<T>> configureObject) { public MultipliedObjectManager(Action<MultipliedObject<T>> configureObject) {
this.configureObject = configureObject; _configureObject = configureObject;
managedObjects = new Dictionary<T, MultipliedObject<T>>(); _managedObjects = new Dictionary<T, MultipliedObject<T>>();
} }
public void OnObjectAttached(T instance) { public void OnObjectAttached(T instance) {
if (!managedObjects.ContainsKey(instance)) { if (!_managedObjects.ContainsKey(instance)) {
if (Main.debug.Value) if (Main.debug.Value)
Console.WriteLine("{0}.OnAttached", typeof(T).Name); Console.WriteLine("{0}.OnAttached", typeof(T).Name);
var multipliedObject = new MultipliedObject<T>(instance); var multipliedObject = new MultipliedObject<T>(instance);
configureObject(multipliedObject); _configureObject(multipliedObject);
multipliedObject.CaptureFrom(); multipliedObject.CaptureFrom();
managedObjects.Add(instance, multipliedObject); _managedObjects.Add(instance, multipliedObject);
multipliedObject.LogValues("Patching"); multipliedObject.LogValues("Patching");
ApplyTo(instance); ApplyTo(instance);
@@ -140,7 +154,7 @@ namespace TerraTech {
public void OnObjectDetached(T instance) { public void OnObjectDetached(T instance) {
MultipliedObject<T> multipliedObject; MultipliedObject<T> multipliedObject;
if (managedObjects.TryGetValue(instance, out multipliedObject)) { if (_managedObjects.TryGetValue(instance, out multipliedObject)) {
if (Main.debug.Value) { if (Main.debug.Value) {
Console.WriteLine("{0}.OnDetaching", typeof(T).Name); Console.WriteLine("{0}.OnDetaching", typeof(T).Name);
multipliedObject.LogValues("Restoring"); multipliedObject.LogValues("Restoring");
@@ -148,14 +162,14 @@ namespace TerraTech {
RestoreTo(instance); RestoreTo(instance);
multipliedObject.LogValues("Restored"); multipliedObject.LogValues("Restored");
managedObjects.Remove(instance); _managedObjects.Remove(instance);
} }
} }
public void ApplyAll() { public void ApplyAll() {
if (Main.debug.Value) if (Main.debug.Value)
Console.WriteLine("Modifying {0} {1}", managedObjects.Count, typeof(T).Name); Console.WriteLine("Modifying {0} {1}", _managedObjects.Count, typeof(T).Name);
foreach (var instance in managedObjects.Keys) { foreach (var instance in _managedObjects.Keys) {
RestoreTo(instance); RestoreTo(instance);
ApplyTo(instance); ApplyTo(instance);
} }
@@ -163,13 +177,13 @@ namespace TerraTech {
private void ApplyTo(T instance) { private void ApplyTo(T instance) {
MultipliedObject<T> obj; MultipliedObject<T> obj;
if (managedObjects.TryGetValue(instance, out obj)) if (_managedObjects.TryGetValue(instance, out obj))
obj.ApplyTo(); obj.ApplyTo();
} }
private void RestoreTo(T instance) { private void RestoreTo(T instance) {
MultipliedObject<T> obj; MultipliedObject<T> obj;
if (managedObjects.TryGetValue(instance, out obj)) if (_managedObjects.TryGetValue(instance, out obj))
obj.RestoreTo(); obj.RestoreTo();
} }
} }