Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
d64eadd
Added remove self method for modifiers
TheDavSmasher Jun 19, 2026
388b6ec
Added TryRemoveModifier methods to simplify get and remove modifiers
TheDavSmasher Jun 19, 2026
29779f3
Added similar extensions with new try remove methods
TheDavSmasher Jun 19, 2026
34c172b
Added methods to get modifiers from an interface type
TheDavSmasher Jun 19, 2026
01fe88e
Added equivalent extensions of Modifier OfType methods
TheDavSmasher Jun 19, 2026
690b1b2
Added generic Enum Option attribute
TheDavSmasher Jun 19, 2026
42eba62
Created interface for sets of equal/comparable modded options
TheDavSmasher Jun 20, 2026
6125975
Created abstract class for Option list
TheDavSmasher Jun 20, 2026
71a3461
Created subclass with generic values
TheDavSmasher Jun 20, 2026
f9a33ce
Created concrete class for nested IModdedOptions that aren't the conc…
TheDavSmasher Jun 20, 2026
b0be071
Removed middleman classes and fields that can be handled much easier
TheDavSmasher Jun 20, 2026
be1d77b
Removed readonly properties that can be more easily replicated with t…
TheDavSmasher Jun 20, 2026
beb7443
Extended from IReadOnlyList for potential easier iteration
TheDavSmasher Jun 20, 2026
f9f7b7e
Expanded setters to set the inner options values as well
TheDavSmasher Jun 20, 2026
007c202
Changed properties to init instead of set to allow using object initi…
TheDavSmasher Jun 20, 2026
93d5ebf
Removed Preset fields from interface that won't be used
TheDavSmasher Jun 20, 2026
ad6ca6f
Simplified property setters and getter
TheDavSmasher Jun 20, 2026
6a899ba
Removed properties that aren't required
TheDavSmasher Jun 20, 2026
e115317
Removed generic from interface for easier manager registering alongsi…
TheDavSmasher Jun 20, 2026
bea37d8
Applied Modded option list into options manager
TheDavSmasher Jun 20, 2026
b5e35e2
Added constructor overload
TheDavSmasher Jun 21, 2026
39a43f5
Removed unnecessary private get
TheDavSmasher Jun 21, 2026
604d2f3
Added interface to error logger check
TheDavSmasher Jun 21, 2026
11fa958
Added abstract option list attribute
TheDavSmasher Jun 21, 2026
887be87
Changed abstract methods to handle casting and calling abstract overload
TheDavSmasher Jun 22, 2026
e5658df
Created parent attribute class to share methods
TheDavSmasher Jun 22, 2026
80b8af8
Added IList cast and null check
TheDavSmasher Jun 22, 2026
68fb1d2
Added patches to the list's getter and setter
TheDavSmasher Jun 22, 2026
6772794
Changed to store a reference to the property's value instance
TheDavSmasher Jun 22, 2026
edeec4c
Implemented list value patches
TheDavSmasher Jun 22, 2026
3fd3c68
Removed propertyinfo field
TheDavSmasher Jun 22, 2026
c3384ef
Changed parent attribute method signatures
TheDavSmasher Jun 22, 2026
25794b1
Created attribute versions for option list
TheDavSmasher Jun 22, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 30 additions & 0 deletions MiraAPI/GameOptions/Attributes/ModdedEnumOptionAttribute.cs
Original file line number Diff line number Diff line change
Expand Up @@ -32,3 +32,33 @@ public override object GetValue()
: throw new InvalidOperationException($"HolderOption for option \"{Title}\" with EnumType ${enumType.FullName} is not a ModdedEnumOption");
}
}

/// <summary>
/// Attribute for creating an enum option.
/// </summary>
/// <typeparam name="T">The enum type.</typeparam>
[AttributeUsage(AttributeTargets.Property)]
public class ModdedEnumOptionAttribute<T>(string title, string[]? values = null)
: ModdedOptionAttribute(title) where T : Enum
{
internal override IModdedOption CreateOption(object? value, PropertyInfo property)
{
var opt = new ModdedEnumOption<T>(Title, (T)(value ?? 0), values);
return opt;
}

/// <inheritdoc />
public override void SetValue(object value)
{
var opt = HolderOption as ModdedEnumOption<T>;
opt?.SetValue((T)value);
}

/// <inheritdoc />
public override object GetValue()
{
return HolderOption is ModdedEnumOption<T> opt
? opt.Value
: throw new InvalidOperationException($"HolderOption for option \"{Title}\" with EnumType ${typeof(T).FullName} is not a ModdedEnumOption");
}
}
67 changes: 67 additions & 0 deletions MiraAPI/GameOptions/Attributes/ModdedEnumOptionListAttribute.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
using MiraAPI.GameOptions.OptionTypes;
using System;
using System.Collections;
using System.Reflection;

namespace MiraAPI.GameOptions.Attributes;

/// <summary>
/// Attribute for creating a list of enum options.
/// </summary>
[AttributeUsage(AttributeTargets.Property)]
public class ModdedEnumOptionListAttribute(Func<int, string> titler, Type enumType, string[]? values = null)
: ModdedOptionListAttribute(titler)
{
internal override IModdedOptionList CreateOptionList(IList value, PropertyInfo property)
{
var optList = new ModdedOptionList<ModdedEnumOption>(
value.Count, idx => new(Titler(idx), (int)(value[idx] ?? 0), enumType, values));
return optList;
}

/// <inheritdoc />
public override void SetValue(int idx, object value)
{
var opt = HolderOptionList?[idx] as ModdedEnumOption;
opt?.SetValue((int)value);
}

/// <inheritdoc />
public override object GetValue(int idx)
{
return HolderOptionList?[idx] is ModdedEnumOption opt
? Enum.ToObject(enumType, opt.Value)
: throw new InvalidOperationException($"HolderOption for option \"{Titler(idx)}\" with EnumType ${enumType.FullName} is not a ModdedEnumOption");
}
}

/// <summary>
/// Attribute for creating a list of enum options.
/// </summary>
/// <typeparam name="T">The enum type.</typeparam>
[AttributeUsage(AttributeTargets.Property)]
public class ModdedEnumOptionListAttribute<T>(Func<int, string> titler, string[]? values = null)
: ModdedOptionListAttribute(titler) where T : Enum
{
internal override IModdedOptionList CreateOptionList(IList value, PropertyInfo property)
{
var optList = new ModdedOptionList<ModdedEnumOption<T>>(
value.Count, idx => new(Titler(idx), (T)(value[idx] ?? 0), values));
return optList;
}

/// <inheritdoc />
public override void SetValue(int idx, object value)
{
var opt = HolderOptionList?[idx] as ModdedEnumOption<T>;
opt?.SetValue((T)value);
}

/// <inheritdoc />
public override object GetValue(int idx)
{
return HolderOptionList?[idx] is ModdedEnumOption<T> opt
? opt.Value
: throw new InvalidOperationException($"HolderOption for option \"{Titler(idx)}\" with EnumType ${typeof(T).FullName} is not a ModdedEnumOption");
}
}
55 changes: 55 additions & 0 deletions MiraAPI/GameOptions/Attributes/ModdedNumberOptionListAttribute.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
using MiraAPI.GameOptions.OptionTypes;
using MiraAPI.Utilities;
using System;
using System.Collections;
using System.Reflection;

namespace MiraAPI.GameOptions.Attributes;

/// <summary>
/// A number option attribute for the modded options system.
/// </summary>
[AttributeUsage(AttributeTargets.Property)]
public class ModdedNumberOptionListAttribute(
Func<int, string> titler,
float min,
float max,
float increment = 1,
MiraNumberSuffixes suffixType = MiraNumberSuffixes.None,
string? formatString = null,
bool zeroInfinity = false)
: ModdedOptionListAttribute(titler)
{
internal override IModdedOptionList CreateOptionList(IList value, PropertyInfo property)
{
return new ModdedOptionList<ModdedNumberOption>(value.Count, idx =>
{
return new(
Titler(idx),
(float)(value[idx] ?? min + increment),
min,
max,
increment,
suffixType,
formatString,
zeroInfinity);
});
}

/// <inheritdoc />
public override void SetValue(int idx, object value)
{
var opt = HolderOptionList?[idx] as ModdedNumberOption;
opt?.SetValue((float)value);
}

/// <inheritdoc />
public override object GetValue(int idx)
{
if (HolderOptionList?[idx] is ModdedNumberOption opt)
{
return opt.Value;
}
throw new InvalidOperationException($"HolderOption for option \"{Titler(idx)}\" is not a ModdedNumberOption");
}
}
18 changes: 3 additions & 15 deletions MiraAPI/GameOptions/Attributes/ModdedOptionAttribute.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,31 +9,19 @@ namespace MiraAPI.GameOptions.Attributes;
/// <param name="title">The option title.</param>
/// <param name="roleType">Optional parameter to specify a role Type.</param>
[AttributeUsage(AttributeTargets.Property)]
public abstract class ModdedOptionAttribute(string title, Type? roleType = null) : Attribute
public abstract class ModdedOptionAttribute(string title, Type? roleType = null) : PropertyOptionAttribute
{
internal IModdedOption? HolderOption { get; set; }

/// <summary>
/// Gets the title of the option.
/// </summary>
public string Title { get; private set; } = title;
public string Title => title;

/// <summary>
/// Gets the role type of the option.
/// </summary>
protected Type? RoleType { get; private set; } = roleType;

/// <summary>
/// Sets the value of the option.
/// </summary>
/// <param name="value">The new value as an object.</param>
public abstract void SetValue(object value);

/// <summary>
/// Gets the value of the option.
/// </summary>
/// <returns>The value of the option as an object.</returns>
public abstract object GetValue();
protected Type? RoleType => roleType;

internal abstract IModdedOption? CreateOption(object? value, PropertyInfo property);
}
66 changes: 66 additions & 0 deletions MiraAPI/GameOptions/Attributes/ModdedOptionListAttribute.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
using System;
using System.Collections;
using System.Reflection;

namespace MiraAPI.GameOptions.Attributes;

/// <summary>
/// Represents an attribute that is used to define a list of modded options.
/// </summary>
/// <param name="titler">A function to title of the options.</param>
[AttributeUsage(AttributeTargets.Property)]
public abstract class ModdedOptionListAttribute(Func<int, string> titler) : PropertyOptionAttribute
{
internal IModdedOptionList? HolderOptionList { get; set; }

internal object? Value { get; set; }

/// <summary>
/// Gets the function to title of the options.
/// </summary>
public Func<int, string> Titler => titler;

/// <summary>
/// Sets the value of all the options.
/// </summary>
/// <param name="value">The new values as an object.</param>
public override void SetValue(object value)
{
Value = value;
var list = (IList)value;
if (list.Count != HolderOptionList!.Count)
{
throw new InvalidOperationException($"Value set to option list cannot change the list's length.");
}

for (int i = 0; i < list!.Count; i++)
{
SetValue(i, list[i]!);
}
}

/// <summary>
/// Sets the value of the specific option.
/// </summary>
/// <param name="idx">The option to set.</param>
/// <param name="value">The new value as an object.</param>
public abstract void SetValue(int idx, object value);

/// <summary>
/// Gets the value of all the options.
/// </summary>
/// <returns>The value of the options as an object.</returns>
public override object GetValue()
{
return Value!;
}

/// <summary>
/// Gets the value of the specific option.
/// </summary>
/// <param name="idx">The option to set.</param>
/// <returns>The value of the option as an object.</returns>
public abstract object GetValue(int idx);

internal abstract IModdedOptionList? CreateOptionList(IList value, PropertyInfo property);
}
38 changes: 38 additions & 0 deletions MiraAPI/GameOptions/Attributes/ModdedToggleOptionListAttribute.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
using MiraAPI.GameOptions.OptionTypes;
using System;
using System.Collections;
using System.Reflection;

namespace MiraAPI.GameOptions.Attributes;

/// <summary>
/// Attribute for a list of toggle options.
/// </summary>
/// <param name="titler">The function to get each option's title.</param>
[AttributeUsage(AttributeTargets.Property)]
public class ModdedToggleOptionListAttribute(Func<int, string> titler) : ModdedOptionListAttribute(titler)
{
internal override IModdedOptionList CreateOptionList(IList value, PropertyInfo property)
{
var optList = new ModdedOptionList<ModdedToggleOption>(
value.Count, idx => new(Titler(idx), (bool)(value[idx] ?? false)));
return optList;
}

/// <inheritdoc />
public override void SetValue(int idx, object value)
{
var opt = HolderOptionList?[idx] as ModdedToggleOption;
opt?.SetValue((bool)value);
}

/// <inheritdoc />
public override object GetValue(int idx)
{
if (HolderOptionList?[idx] is ModdedToggleOption opt)
{
return opt.Value;
}
throw new InvalidOperationException($"Holder option for {Titler(idx)} is not a ModdedToggleOption.");
}
}
22 changes: 22 additions & 0 deletions MiraAPI/GameOptions/Attributes/PropertyOptionAttribute.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
using System;

namespace MiraAPI.GameOptions.Attributes;

/// <summary>
/// Represents an attribute that is used to intercept a property's getter and setter.
/// </summary>
[AttributeUsage(AttributeTargets.Property)]
public abstract class PropertyOptionAttribute : Attribute
{
/// <summary>
/// Sets the value of the option.
/// </summary>
/// <param name="value">The new value as an object.</param>
public abstract void SetValue(object value);

/// <summary>
/// Gets the value of the option.
/// </summary>
/// <returns>The value of the option as an object.</returns>
public abstract object GetValue();
}
8 changes: 8 additions & 0 deletions MiraAPI/GameOptions/IModdedOption.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System;
using System.Collections.Generic;
using BepInEx.Configuration;
using MiraAPI.Networking;
using MiraAPI.PluginLoading;
Expand Down Expand Up @@ -104,3 +105,10 @@ public interface IModdedOption
/// <param name="presetConfig">The ConfigFile representing the preset configuration.</param>
void LoadFromPreset(ConfigFile presetConfig);
}

/// <summary>
/// Interface for list of modded options.
/// </summary>
public interface IModdedOptionList : IReadOnlyList<IModdedOption>
{
}
Loading