Make both the multiplier and field generic
This commit is contained in:
@@ -5,43 +5,51 @@ using BepInEx.Configuration;
|
|||||||
using HarmonyLib;
|
using HarmonyLib;
|
||||||
|
|
||||||
namespace TerraTech {
|
namespace TerraTech {
|
||||||
|
public interface IMultipliedField {
|
||||||
|
void CaptureOriginal();
|
||||||
|
void Apply();
|
||||||
|
void Restore();
|
||||||
|
void LogValue(string prefix);
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Represents a field that can be multiplied by a configurable value
|
/// Represents a field that can be multiplied by a configurable value
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <typeparam name="TValue">The type of the field value</typeparam>
|
/// <typeparam name="TField">The type of the field value</typeparam>
|
||||||
public class FieldConfiguration<TValue> {
|
/// <typeparam name="TMul">The type of the multiplier</typeparam>
|
||||||
|
public class FieldConfiguration<TField, TMul> {
|
||||||
private string _fieldName;
|
private string _fieldName;
|
||||||
private ConfigEntry<TValue> _defaultMultiplier;
|
private ConfigEntry<TMul> _defaultMultiplier;
|
||||||
private Func<object, ConfigEntry<TValue>> _conditionalMultiplier;
|
private Func<object, ConfigEntry<TMul>> _conditionalMultiplier;
|
||||||
|
|
||||||
public string FieldName {
|
public string FieldName {
|
||||||
get { return _fieldName; }
|
get { return _fieldName; }
|
||||||
set { _fieldName = value; }
|
set { _fieldName = value; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public ConfigEntry<TValue> DefaultMultiplier {
|
public ConfigEntry<TMul> DefaultMultiplier {
|
||||||
get { return _defaultMultiplier; }
|
get { return _defaultMultiplier; }
|
||||||
set { _defaultMultiplier = value; }
|
set { _defaultMultiplier = value; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public Func<object, ConfigEntry<TValue>> ConditionalMultiplier {
|
public Func<object, ConfigEntry<TMul>> ConditionalMultiplier {
|
||||||
get { return _conditionalMultiplier; }
|
get { return _conditionalMultiplier; }
|
||||||
set { _conditionalMultiplier = value; }
|
set { _conditionalMultiplier = value; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public FieldConfiguration(string fieldName, ConfigEntry<TValue> defaultMultiplier) {
|
public FieldConfiguration(string fieldName, ConfigEntry<TMul> defaultMultiplier) {
|
||||||
_fieldName = fieldName;
|
_fieldName = fieldName;
|
||||||
_defaultMultiplier = defaultMultiplier;
|
_defaultMultiplier = defaultMultiplier;
|
||||||
}
|
}
|
||||||
|
|
||||||
public FieldConfiguration(string fieldName, ConfigEntry<TValue> defaultMultiplier,
|
public FieldConfiguration(string fieldName, ConfigEntry<TMul> defaultMultiplier,
|
||||||
Func<object, ConfigEntry<TValue>> conditionalMultiplier) {
|
Func<object, ConfigEntry<TMul>> conditionalMultiplier) {
|
||||||
_fieldName = fieldName;
|
_fieldName = fieldName;
|
||||||
_defaultMultiplier = defaultMultiplier;
|
_defaultMultiplier = defaultMultiplier;
|
||||||
_conditionalMultiplier = conditionalMultiplier;
|
_conditionalMultiplier = conditionalMultiplier;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ConfigEntry<TValue> GetMultiplier(object instance) {
|
public ConfigEntry<TMul> GetMultiplier(object instance) {
|
||||||
if (_conditionalMultiplier == null) {
|
if (_conditionalMultiplier == null) {
|
||||||
return _defaultMultiplier;
|
return _defaultMultiplier;
|
||||||
}
|
}
|
||||||
@@ -49,17 +57,17 @@ namespace TerraTech {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public class MultipliedField<TValue> {
|
public class MultipliedField<TField, TMul> : IMultipliedField {
|
||||||
private readonly string _fieldName;
|
private readonly string _fieldName;
|
||||||
private readonly ConfigEntry<TValue> _multiplier;
|
private readonly ConfigEntry<TMul> _multiplier;
|
||||||
private readonly Traverse _parentTraverse;
|
private readonly Traverse _parentTraverse;
|
||||||
private TValue _originalValue;
|
private TField _originalValue;
|
||||||
|
|
||||||
public string FieldName {
|
public string FieldName {
|
||||||
get { return _fieldName; }
|
get { return _fieldName; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public MultipliedField(string fieldName, ConfigEntry<TValue> multiplier, Traverse parentTraverse) {
|
public MultipliedField(string fieldName, ConfigEntry<TMul> multiplier, Traverse parentTraverse) {
|
||||||
_fieldName = fieldName;
|
_fieldName = fieldName;
|
||||||
_multiplier = multiplier;
|
_multiplier = multiplier;
|
||||||
_parentTraverse = parentTraverse;
|
_parentTraverse = parentTraverse;
|
||||||
@@ -69,9 +77,16 @@ namespace TerraTech {
|
|||||||
string.Format("Field {0} does not exist on {1}", fieldName, parentTraverse));
|
string.Format("Field {0} does not exist on {1}", fieldName, parentTraverse));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Verify TValue is a numeric type
|
// Verify TField is a numeric type
|
||||||
if (!IsNumericType(typeof(TValue))) {
|
if (!IsNumericType(typeof(TField))) {
|
||||||
throw new ArgumentException(string.Format("Type {0} must be a numeric type", typeof(TValue).Name));
|
throw new ArgumentException(
|
||||||
|
string.Format("Field type {0} must be a numeric type", typeof(TField).Name));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Verify TMul is a numeric type
|
||||||
|
if (!IsNumericType(typeof(TMul))) {
|
||||||
|
throw new ArgumentException(
|
||||||
|
string.Format("Multiplier type {0} must be a numeric type", typeof(TMul).Name));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -81,21 +96,23 @@ namespace TerraTech {
|
|||||||
type == typeof(float) || type == typeof(double) || type == typeof(decimal);
|
type == typeof(float) || type == typeof(double) || type == typeof(decimal);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static TValue MultiplyValues(TValue a, TValue b) {
|
private TField MultiplyValues(TField fieldValue, TMul multiplierValue) {
|
||||||
// Convert to double for the multiplication
|
// Convert both to double for the multiplication
|
||||||
double result = Convert.ToDouble(a) * Convert.ToDouble(b);
|
double fieldDouble = Convert.ToDouble(fieldValue);
|
||||||
// Convert back to TValue
|
double multiplierDouble = Convert.ToDouble(multiplierValue);
|
||||||
return (TValue)Convert.ChangeType(result, typeof(TValue));
|
double result = fieldDouble * multiplierDouble;
|
||||||
|
// Convert back to TField
|
||||||
|
return (TField)Convert.ChangeType(result, typeof(TField));
|
||||||
}
|
}
|
||||||
|
|
||||||
public TValue GetValue() {
|
public TField 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 (TField)value;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void SetValue(TValue value) {
|
public void SetValue(TField 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))
|
||||||
@@ -146,17 +163,18 @@ namespace TerraTech {
|
|||||||
public class MultipliedObject<T> {
|
public class MultipliedObject<T> {
|
||||||
private readonly T _instance;
|
private readonly T _instance;
|
||||||
private readonly Traverse _objectTraverse;
|
private readonly Traverse _objectTraverse;
|
||||||
private readonly Dictionary<string, MultipliedField<float>> _fields;
|
private readonly Dictionary<string, IMultipliedField> _fields;
|
||||||
|
|
||||||
public MultipliedObject(T instance) {
|
public MultipliedObject(T instance) {
|
||||||
_instance = instance;
|
_instance = instance;
|
||||||
_objectTraverse = Traverse.Create(instance);
|
_objectTraverse = Traverse.Create(instance);
|
||||||
_fields = new Dictionary<string, MultipliedField<float>>();
|
_fields = new Dictionary<string, IMultipliedField>();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void AddField(FieldConfiguration<float> config) {
|
public void AddField<TField, TMul>(FieldConfiguration<TField, TMul> config) {
|
||||||
var multiplier = config.GetMultiplier(_instance);
|
var multiplier = config.GetMultiplier(_instance);
|
||||||
_fields[config.FieldName] = new MultipliedField<float>(config.FieldName, multiplier, _objectTraverse);
|
_fields[config.FieldName] =
|
||||||
|
new MultipliedField<TField, TMul>(config.FieldName, multiplier, _objectTraverse);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void CaptureFrom() {
|
public void CaptureFrom() {
|
||||||
@@ -166,28 +184,16 @@ namespace TerraTech {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void ApplyTo(IEnumerable<string> fieldNames = null) {
|
public void ApplyTo(IEnumerable<string> fieldNames = null) {
|
||||||
IEnumerable<MultipliedField<float>> fieldsToApply;
|
IEnumerable<string> fieldsToApply = fieldNames ?? _fields.Keys;
|
||||||
if (fieldNames != null) {
|
foreach (var fieldName in fieldsToApply.Where(name => _fields.ContainsKey(name))) {
|
||||||
fieldsToApply = fieldNames.Where(name => _fields.ContainsKey(name)).Select(name => _fields[name]);
|
_fields[fieldName].Apply();
|
||||||
} else {
|
|
||||||
fieldsToApply = _fields.Values;
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach (var field in fieldsToApply) {
|
|
||||||
field.Apply();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void RestoreTo(IEnumerable<string> fieldNames = null) {
|
public void RestoreTo(IEnumerable<string> fieldNames = null) {
|
||||||
IEnumerable<MultipliedField<float>> fieldsToRestore;
|
IEnumerable<string> fieldsToRestore = fieldNames ?? _fields.Keys;
|
||||||
if (fieldNames != null) {
|
foreach (var fieldName in fieldsToRestore.Where(name => _fields.ContainsKey(name))) {
|
||||||
fieldsToRestore = fieldNames.Where(name => _fields.ContainsKey(name)).Select(name => _fields[name]);
|
_fields[fieldName].Restore();
|
||||||
} else {
|
|
||||||
fieldsToRestore = _fields.Values;
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach (var field in fieldsToRestore) {
|
|
||||||
field.Restore();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -247,7 +253,8 @@ namespace TerraTech {
|
|||||||
public void ApplyAll(IEnumerable<string> fieldNames = null) {
|
public void ApplyAll(IEnumerable<string> fieldNames = null) {
|
||||||
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
|
||||||
|
.ToList()) { // ToList to avoid modification during enumeration
|
||||||
RestoreTo(instance, fieldNames);
|
RestoreTo(instance, fieldNames);
|
||||||
ApplyTo(instance, fieldNames);
|
ApplyTo(instance, fieldNames);
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user