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