Created subclass with generic values

This commit is contained in:
David Higueros committed 2026-06-19 22:23:35 -06:00
1 parent 612597566b
commit 71a3461432
1 file changed
+146 -1
@@ -34,8 +34,10 @@ public abstract class ModdedOptionList : IModdedOptionList
/// <inheritdoc />
public IReadOnlyList<StringNames> StringNames { get; }
protected readonly BaseGameSetting[] _data;
/// <inheritdoc />
public IReadOnlyList<BaseGameSetting> Data { get; protected set; } = [];
public IReadOnlyList<BaseGameSetting> Data => _data;
/// <inheritdoc />
public IMiraPlugin? ParentMod
@@ -118,3 +120,146 @@ public abstract class ModdedOptionList : IModdedOptionList
PlayerOption playerOpt,
Transform container);
}
/// <summary>
/// Represents a modded option list.
/// </summary>
/// <typeparam name="T">The value type.</typeparam>
public abstract class ModdedOptionList<T> : ModdedOptionList
{
protected override void OnParentModChange()
{
var configFile = _parentMod!.GetConfigFile();
for (int i = 0; i < Count; i++)
{
var entry = configFile.Bind(ConfigDefinitions[i], DefaultValue(i));
Values[i] = entry.Value;
}
}
/// <summary>
/// Gets the list of values of the options.
/// </summary>
public T[] Values { get; }
/// <summary>
/// Gets the list of default value of the options.
/// </summary>
public Func<int, T> DefaultValue { get; }
/// <summary>
/// Gets or sets the event that is invoked when the value of an option changes.
/// </summary>
public Action<int, T>? ChangedEvent { get; set; }
/// <summary>
/// Initializes a new instance of the <see cref="ModdedOptionList{T}"/> class.
/// </summary>
/// <param name="title">The options' title.</param>
/// <param name="count">The option list's length.</param>
/// <param name="defaultValues">The default values.</param>
/// <param name="includeInPreset">Whether to include the options in the preset.</param>
/// <param name="zeroIndexTitle">Whether the first option's title index is 0, else 1.</param>
protected ModdedOptionList(string title, int count, Func<int, T> defaultValues, bool includeInPreset = true, bool zeroIndexTitle = false)
: base(title, count, includeInPreset, zeroIndexTitle)
{
DefaultValue = defaultValues;
Values = Enumerable.Range(0, Count).Select(defaultValues).ToArray();
}
internal void ValueChanged(int idx, OptionBehaviour optionBehaviour)
{
SetValue(idx, GetValueFromOptionBehaviour(idx, optionBehaviour));
}
/// <summary>
/// Sets the value of the option.
/// </summary>
/// <param name="idx">The option's index.</param>
/// <param name="newValue">The new value.</param>
/// <param name="sendRpc">Whether to send the value to other players.</param>
public void SetValue(int idx, T newValue, bool sendRpc = true)
{
var oldVal = Values[idx];
Values[idx] = newValue;
if (Values[idx]?.Equals(oldVal) == false)
{
ChangedEvent?.Invoke(idx, Values[idx]);
}
if (sendRpc && AmongUsClient.Instance.AmHost)
{
if (ParentMod?.GetConfigFile().TryGetEntry<T>(ConfigDefinitions[idx], out var entry) == true)
{
entry.Value = Values[idx];
}
Rpc<SyncOptionsRpc>.Instance.Send(PlayerControl.LocalPlayer, [GetNetData(idx)], true); // This might not work
}
OnValueChanged(idx, newValue);
}
/// <inheritdoc/>
public override void SaveToPreset(ConfigFile presetConfig, bool saveDefault = false)
{
if (ConfigDefinitions.Any(d => d is null))
{
Error($"Attempted to save {Title} to preset, but some ConfigDefinitions are null.");
return;
}
Bind(presetConfig);
for (int i = 0; i < Count; i++)
{
presetConfig[ConfigDefinitions[i]].BoxedValue = saveDefault ? DefaultValue(i) : Values[i];
}
}
/// <inheritdoc />
public override void Bind(ConfigFile config)
{
for (int i = 0; i < Count; i++)
{
config.Bind(ConfigDefinitions[i], DefaultValue(i));
}
}
/// <inheritdoc />
public override void LoadFromPreset(ConfigFile presetConfig)
{
for (int i = 0; i < Count; i++)
{
if (presetConfig.TryGetEntry(ConfigDefinitions[i], out ConfigEntry<T> entry))
{
SetValue(i, entry.Value, false);
}
else
{
Error($"Attempted to load {Title} from preset, but ConfigDefinition {i} is not found in preset.");
}
}
}
/// <summary>
/// Handles the value changed event.
/// </summary>
/// <param name="idx">The option's index.</param>
/// <param name="newValue">The new value.</param>
protected abstract void OnValueChanged(int idx, T newValue);
/// <summary>
/// Gets the value from the option behaviour.
/// </summary>
/// <param name="idx">The option's index.</param>
/// <param name="optionBehaviour">The OptionBehaviour.</param>
/// <returns>The value.</returns>
public abstract T GetValueFromOptionBehaviour(int idx, OptionBehaviour optionBehaviour);
/// <summary>
/// Indexes the option for its value of type <typeparamref name="T"/>.
/// </summary>
/// <param name="idx">The option's index.</param>
/// <returns>value of type <typeparamref name="T"/>.</returns>
public T this[int idx] => Values[idx];
}