Removed middleman classes and fields that can be handled much easier

This commit is contained in:
David Higueros committed 2026-06-19 23:12:08 -06:00
1 parent f9a33ce109
commit b0be07192e
2 files changed
+39 -326

No files matched your search

+4 -45
View File
@@ -1,9 +1,7 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using BepInEx.Configuration; using BepInEx.Configuration;
using MiraAPI.Networking;
using MiraAPI.PluginLoading; using MiraAPI.PluginLoading;
using UnityEngine;
namespace MiraAPI.GameOptions; namespace MiraAPI.GameOptions;
@@ -23,15 +21,9 @@ public interface IModdedOptionList
IReadOnlyList<uint> Ids { get; } IReadOnlyList<uint> Ids { get; }
/// <summary> /// <summary>
/// Gets or sets the titles of the options. /// Gets the titles of the options.
/// The end title will equal this value with its index appended (e.g., Title1).
/// </summary> /// </summary>
string Title { get; set; } IReadOnlyList<string> Titles { get; }
/// <summary>
/// Gets or sets a value indicating whether the first option's title has a 0, else starts with 1.
/// </summary>
bool ZeroIndexTitle { get; set; }
/// <summary> /// <summary>
/// Gets the StringName for the options, used for localization. /// Gets the StringName for the options, used for localization.
@@ -64,42 +56,9 @@ public interface IModdedOptionList
bool IncludeInPreset { get; set; } bool IncludeInPreset { get; set; }
/// <summary> /// <summary>
/// Gets the array of ConfigDefinition for the options, used for BepInEx configuration. /// Gets the set of ConfigDefinition for the options, used for BepInEx configuration.
/// </summary> /// </summary>
ConfigDefinition?[] ConfigDefinitions { get; } IReadOnlyList<ConfigDefinition?> ConfigDefinitions { get; }
/// <summary>
/// Creates the option behaviour for the modded option at index <paramref name="idx"/>.
/// </summary>
/// <param name="idx">The option's index.</param>
/// <param name="toggleOpt">The ToggleOption template.</param>
/// <param name="numberOpt">The NumberOption template.</param>
/// <param name="stringOpt">The StringOption template.</param>
/// <param name="playerOpt">The PlayerOption template.</param>
/// <param name="container">>The Transform container for the option.</param>
/// <returns>The created OptionBehaviour object.</returns>
OptionBehaviour CreateOption(int idx, ToggleOption toggleOpt, NumberOption numberOpt, StringOption stringOpt, PlayerOption playerOpt, Transform container);
/// <summary>
/// Gets the value at index <paramref name="idx"/> as a float.
/// </summary>
/// <param name="idx">The option's index.</param>
/// <returns>The value of the option as a float.</returns>
float GetFloatData(int idx);
/// <summary>
/// Gets the NetData for the option at index <paramref name="idx"/>, used for network synchronization.
/// </summary>
/// <param name="idx">The option's index.</param>
/// <returns>Returns the NetData object for the option.</returns>
NetData GetNetData(int idx);
/// <summary>
/// Handles incoming network data for the option at index <paramref name="idx"/>.
/// </summary>
/// <param name="idx">The option's index.</param>
/// <param name="data">The byte array representing the network data.</param>
void HandleNetData(int idx, byte[] data);
/// <summary> /// <summary>
/// Saves the options to a preset configuration file. /// Saves the options to a preset configuration file.
@@ -1,43 +1,33 @@
using System; using System;
using System.Collections;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using BepInEx.Configuration; using BepInEx.Configuration;
using MiraAPI.Networking;
using MiraAPI.PluginLoading; using MiraAPI.PluginLoading;
using Reactor.Localization.Utilities;
using Reactor.Networking.Rpc;
using Reactor.Utilities;
using UnityEngine;
namespace MiraAPI.GameOptions.OptionTypes; namespace MiraAPI.GameOptions.OptionTypes;
/// <summary> /// <summary>
/// Represents a modded option list. /// Represents a modded option list.
/// </summary> /// </summary>
public abstract class ModdedOptionList : IModdedOptionList /// <typeparam name="T">The type of options.</typeparam>
public class ModdedOptionList<T> : IModdedOptionList where T : IModdedOption
{ {
protected IMiraPlugin? _parentMod; private IMiraPlugin? _parentMod;
/// <inheritdoc/> /// <inheritdoc/>
public int Count { get; } public int Count { get; }
/// <inheritdoc /> /// <inheritdoc />
public IReadOnlyList<uint> Ids { get; } public IReadOnlyList<uint> Ids => FromOptions(o => o.Id);
/// <inheritdoc /> /// <inheritdoc />
public string Title { get; set; } public IReadOnlyList<string> Titles => FromOptions(o => o.Title);
/// <inheritdoc/>
public bool ZeroIndexTitle { get; set; }
/// <inheritdoc /> /// <inheritdoc />
public IReadOnlyList<StringNames> StringNames { get; } public IReadOnlyList<StringNames> StringNames => FromOptions(o => o.StringName);
protected readonly BaseGameSetting[] _data;
/// <inheritdoc /> /// <inheritdoc />
public IReadOnlyList<BaseGameSetting> Data => _data; public IReadOnlyList<BaseGameSetting> Data => FromOptions(o => o.Data);
/// <inheritdoc /> /// <inheritdoc />
public IMiraPlugin? ParentMod public IMiraPlugin? ParentMod
@@ -48,233 +38,10 @@ public abstract class ModdedOptionList : IModdedOptionList
if (_parentMod != null || value == null) return; if (_parentMod != null || value == null) return;
_parentMod = value; _parentMod = value;
OnParentModChange(); foreach (var option in Options)
}
}
protected abstract void OnParentModChange();
/// <inheritdoc />
public Func<int, bool> Visible { get; set; }
/// <inheritdoc />
public bool IncludeInPreset { get; set; }
protected readonly OptionBehaviour?[] _optionBehaviours;
/// <inheritdoc />
public IReadOnlyList<OptionBehaviour?> OptionBehaviours => _optionBehaviours;
/// <inheritdoc />
public ConfigDefinition?[] ConfigDefinitions { get; set; }
/// <summary>
/// Initializes a new instance of the <see cref="ModdedOptionList"/> class.
/// </summary>
/// <param name="title">The options' title.</param>
/// <param name="count">The option list's length.</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, bool includeInPreset = true, bool zeroIndexTitle = false)
{
Count = count;
ZeroIndexTitle = zeroIndexTitle;
var range = Enumerable.Range(0, Count);
var titleOffset = ZeroIndexTitle ? 0 : 1;
Ids = range.Select(_ => ModdedOptionsManager.NextId).ToList();
Title = title;
StringNames = range.Select(i => CustomStringName.CreateAndRegister($"{Title}{i + titleOffset}")).ToList();
Visible = _ => true;
IncludeInPreset = includeInPreset;
_optionBehaviours = range.Select<int, OptionBehaviour?>(_ => null).ToArray();
ConfigDefinitions = range.Select<int, ConfigDefinition?>(_ => null).ToArray();
}
/// <inheritdoc/>
public abstract void SaveToPreset(ConfigFile presetConfig, bool saveDefault = false);
/// <inheritdoc/>
public abstract void Bind(ConfigFile config);
/// <inheritdoc/>
public abstract void LoadFromPreset(ConfigFile presetConfig);
/// <inheritdoc/>
public abstract float GetFloatData(int idx);
/// <inheritdoc/>
public abstract NetData GetNetData(int idx);
/// <inheritdoc/>
public abstract void HandleNetData(int idx, byte[] data);
/// <inheritdoc/>
public abstract OptionBehaviour CreateOption(
int idx,
ToggleOption toggleOpt,
NumberOption numberOpt,
StringOption stringOpt,
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]; option.ParentMod = _parentMod!;
} }
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];
}
/// <summary>
/// Represents a modded option list.
/// </summary>
/// <typeparam name="T">The option's type.</typeparam>
public class ModdedOptionsList<T> : ModdedOptionList where T : IModdedOption
{
protected override void OnParentModChange()
{
foreach (var option in Options)
{
option.ParentMod = _parentMod!;
} }
} }
@@ -283,28 +50,39 @@ public class ModdedOptionsList<T> : ModdedOptionList where T : IModdedOption
/// </summary> /// </summary>
public T[] Options { get; } public T[] Options { get; }
/// <summary> /// <inheritdoc />
/// Gets the default option from its index. public Func<int, bool> Visible { get; set; }
/// </summary>
public Func<int, T> DefaultOption { get; } /// <inheritdoc />
public bool IncludeInPreset { get; set; }
/// <inheritdoc />
public IReadOnlyList<OptionBehaviour?> OptionBehaviours => FromOptions(o => o.OptionBehaviour);
/// <inheritdoc />
public IReadOnlyList<ConfigDefinition?> ConfigDefinitions => FromOptions(o => o.ConfigDefinition);
/// <summary> /// <summary>
/// Initializes a new instance of the <see cref="ModdedOptionsList{T}"/> class. /// Initializes a new instance of the <see cref="ModdedOptionList{T}"/> class.
/// </summary> /// </summary>
/// <param name="title">The options' title.</param>
/// <param name="count">The option list's length.</param> /// <param name="count">The option list's length.</param>
/// <param name="defaultOption">The default option.</param> /// <param name="optionFactory">The option factory to instantiate the options from.</param>
/// <param name="includeInPreset">Whether to include the options in the preset.</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> public ModdedOptionList(int count, Func<int, T> optionFactory, bool includeInPreset = true)
protected ModdedOptionsList(string title, int count, Func<int, T> defaultOption, bool includeInPreset = true, bool zeroIndexTitle = false)
: base(title, count, includeInPreset, zeroIndexTitle)
{ {
DefaultOption = defaultOption; Count = count;
Options = Enumerable.Range(0, Count).Select(defaultOption).ToArray(); Visible = _ => true;
IncludeInPreset = includeInPreset;
Options = Enumerable.Range(0, Count).Select(optionFactory).ToArray();
}
internal IReadOnlyList<TVal> FromOptions<TVal>(Func<T, TVal> getter)
{
return Options.Select(getter).ToArray();
} }
/// <inheritdoc/> /// <inheritdoc/>
public override void SaveToPreset(ConfigFile presetConfig, bool saveDefault = false) public void SaveToPreset(ConfigFile presetConfig, bool saveDefault = false)
{ {
foreach (var option in Options) foreach (var option in Options)
{ {
@@ -313,7 +91,7 @@ public class ModdedOptionsList<T> : ModdedOptionList where T : IModdedOption
} }
/// <inheritdoc/> /// <inheritdoc/>
public override void Bind(ConfigFile config) public void Bind(ConfigFile config)
{ {
foreach (var option in Options) foreach (var option in Options)
{ {
@@ -322,7 +100,7 @@ public class ModdedOptionsList<T> : ModdedOptionList where T : IModdedOption
} }
/// <inheritdoc/> /// <inheritdoc/>
public override void LoadFromPreset(ConfigFile presetConfig) public void LoadFromPreset(ConfigFile presetConfig)
{ {
foreach (var option in Options) foreach (var option in Options)
{ {
@@ -330,30 +108,6 @@ public class ModdedOptionsList<T> : ModdedOptionList where T : IModdedOption
} }
} }
/// <inheritdoc/>
public override float GetFloatData(int idx)
{
return Options[idx].GetFloatData();
}
/// <inheritdoc/>
public override NetData GetNetData(int idx)
{
return Options[idx].GetNetData();
}
/// <inheritdoc/>
public override void HandleNetData(int idx, byte[] data)
{
Options[idx].HandleNetData(data);
}
/// <inheritdoc/>
public override OptionBehaviour CreateOption(int idx, ToggleOption toggleOpt, NumberOption numberOpt, StringOption stringOpt, PlayerOption playerOpt, Transform container)
{
return _optionBehaviours[idx] = Options[idx].CreateOption(toggleOpt, numberOpt, stringOpt, playerOpt, container);
}
/// <summary> /// <summary>
/// Indexes the option of type <typeparamref name="T"/>. /// Indexes the option of type <typeparamref name="T"/>.
/// </summary> /// </summary>