optimise code + add new example option

This commit is contained in:
Az committed 2026-10-15 23:21:09 -04:00
1 parent aa69fafcf1
commit ca587ebb18
6 files changed
+37 -15

No files matched your search

@@ -45,6 +45,9 @@ public class ExampleOptions : AbstractOptionGroup
public List<ValueState> ValueStates { get; set; } = public List<ValueState> ValueStates { get; set; } =
[ValueState.Primary, ValueState.Secondary, ValueState.None, ValueState.None, ValueState.None]; [ValueState.Primary, ValueState.Secondary, ValueState.None, ValueState.None, ValueState.None];
[ModdedPlayerOption("options.exampleOptions1.players")]
public NetworkedPlayerInfo PlayerSelected { get; set; }
public bool ToggleOpt1Visibility() public bool ToggleOpt1Visibility()
{ {
return true; return true;
@@ -48,6 +48,7 @@ Eliminate every other faction.</string>
<string name="options.exampleOptions1.numberOpt">Number Opt</string> <string name="options.exampleOptions1.numberOpt">Number Opt</string>
<string name="options.exampleOptions1.bestApi">Best API</string> <string name="options.exampleOptions1.bestApi">Best API</string>
<string name="options.exampleOptions1.worstApi">Worst API</string> <string name="options.exampleOptions1.worstApi">Worst API</string>
<string name="options.exampleOptions1.players">Choose A Player</string>
<string name="options.exampleOptions2">Example Options 2</string> <string name="options.exampleOptions2">Example Options 2</string>
<string name="options.exampleOptions2.youMustChoseAPlayer">YOU MUST CHOSE A PLAYER</string> <string name="options.exampleOptions2.youMustChoseAPlayer">YOU MUST CHOSE A PLAYER</string>
<string name="options.exampleOptions2.ehWhatever">Eh whatever</string> <string name="options.exampleOptions2.ehWhatever">Eh whatever</string>
@@ -41,7 +41,7 @@ public class ModdedPlayerOptionAttribute(
var final = value switch var final = value switch
{ {
NetworkedPlayerInfo info => opt.Values.IndexOf(info), NetworkedPlayerInfo info => info ? opt.Values.IndexOf(info) : (allowNone ? -1 : 0),
_ => (int)value, _ => (int)value,
}; };
opt?.SetValue(final); opt?.SetValue(final);
@@ -32,7 +32,7 @@ public class ModdedPlayerOptionListAttribute(
var final = value switch var final = value switch
{ {
NetworkedPlayerInfo info => opt.Values.IndexOf(info), NetworkedPlayerInfo info => info ? opt.Values.IndexOf(info) : (allowNone ? -1 : 0),
_ => (int)value, _ => (int)value,
}; };
opt?.SetValue(final); opt?.SetValue(final);
+27 -12
View File
@@ -4,6 +4,7 @@ using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis; using System.Diagnostics.CodeAnalysis;
using System.Linq; using System.Linq;
using System.Reflection; using System.Reflection;
using System.Runtime.CompilerServices;
using BepInEx.Configuration; using BepInEx.Configuration;
using HarmonyLib; using HarmonyLib;
using MiraAPI.GameModes; using MiraAPI.GameModes;
@@ -24,7 +25,10 @@ namespace MiraAPI.GameOptions;
/// </summary> /// </summary>
public static class ModdedOptionsManager public static class ModdedOptionsManager
{ {
private static readonly ConditionalWeakTable<object, ModdedOptionListAttribute> ListInstanceCache = [];
private static readonly Dictionary<PropertyInfo, PropertyOptionAttribute> OptionAttributes = []; private static readonly Dictionary<PropertyInfo, PropertyOptionAttribute> OptionAttributes = [];
private static readonly Dictionary<MethodBase, PropertyOptionAttribute> GetterLookups = [];
private static readonly Dictionary<MethodBase, PropertyOptionAttribute> SetterLookups = [];
private static readonly Dictionary<Type, AbstractOptionGroup> TypeToGroup = []; private static readonly Dictionary<Type, AbstractOptionGroup> TypeToGroup = [];
private static readonly HashSet<Type> PatchedListTypes = []; private static readonly HashSet<Type> PatchedListTypes = [];
@@ -168,12 +172,16 @@ public static class ModdedOptionsManager
var getterPatch = typeof(ModdedOptionsManager).GetMethod(nameof(PropertyGetterPatch)); var getterPatch = typeof(ModdedOptionsManager).GetMethod(nameof(PropertyGetterPatch));
PluginSingleton<MiraApiPlugin>.Instance.Harmony.Patch(getterOriginal, prefix: new HarmonyMethod(getterPatch)); PluginSingleton<MiraApiPlugin>.Instance.Harmony.Patch(getterOriginal, prefix: new HarmonyMethod(getterPatch));
GetterLookups[getterOriginal!] = attribute;
var setterOriginal = property.GetSetMethod(true); var setterOriginal = property.GetSetMethod(true);
if (setterOriginal != null) if (setterOriginal != null)
{ {
var setterPatch = typeof(ModdedOptionsManager).GetMethod(nameof(PropertySetterPatch)); var setterPatch = typeof(ModdedOptionsManager).GetMethod(nameof(PropertySetterPatch));
PluginSingleton<MiraApiPlugin>.Instance.Harmony.Patch(setterOriginal, postfix: new HarmonyMethod(setterPatch)); PluginSingleton<MiraApiPlugin>.Instance.Harmony.Patch(setterOriginal, postfix: new HarmonyMethod(setterPatch));
SetterLookups[setterOriginal] = attribute;
} }
OptionAttributes.Add(property, attribute); OptionAttributes.Add(property, attribute);
@@ -278,12 +286,16 @@ public static class ModdedOptionsManager
var getterPatch = typeof(ModdedOptionsManager).GetMethod(nameof(PropertyGetterPatch)); var getterPatch = typeof(ModdedOptionsManager).GetMethod(nameof(PropertyGetterPatch));
PluginSingleton<MiraApiPlugin>.Instance.Harmony.Patch(getterOriginal, prefix: new HarmonyMethod(getterPatch)); PluginSingleton<MiraApiPlugin>.Instance.Harmony.Patch(getterOriginal, prefix: new HarmonyMethod(getterPatch));
GetterLookups[getterOriginal!] = attribute;
var setterOriginal = property.GetSetMethod(true); var setterOriginal = property.GetSetMethod(true);
if (setterOriginal != null) if (setterOriginal != null)
{ {
var setterPatch = typeof(ModdedOptionsManager).GetMethod(nameof(PropertySetterPatch)); var setterPatch = typeof(ModdedOptionsManager).GetMethod(nameof(PropertySetterPatch));
PluginSingleton<MiraApiPlugin>.Instance.Harmony.Patch(setterOriginal, postfix: new HarmonyMethod(setterPatch)); PluginSingleton<MiraApiPlugin>.Instance.Harmony.Patch(setterOriginal, postfix: new HarmonyMethod(setterPatch));
SetterLookups[setterOriginal] = attribute;
} }
var listType = propertyList.GetType(); var listType = propertyList.GetType();
@@ -307,9 +319,11 @@ public static class ModdedOptionsManager
OptionAttributes.Add(property, attribute); OptionAttributes.Add(property, attribute);
attribute.HolderOptionList = optionList; attribute.HolderOptionList = optionList;
attribute.Value = (IList)propertyVal; attribute.Value = propertyList;
attribute.ValueType = listType.GetGenericArguments()[0]; attribute.ValueType = listType.GetGenericArguments()[0];
ListInstanceCache.Add(propertyVal, attribute);
var valueType = property.PropertyType.GetGenericArguments()[0]; var valueType = property.PropertyType.GetGenericArguments()[0];
var visibilityAttr = property.GetCustomAttribute<ModdedOptionVisibilityAttribute>(); var visibilityAttr = property.GetCustomAttribute<ModdedOptionVisibilityAttribute>();
@@ -422,8 +436,13 @@ public static class ModdedOptionsManager
[SuppressMessage("Naming", "CA1707:Identifiers should not contain underscores", Justification = "Read above.")] [SuppressMessage("Naming", "CA1707:Identifiers should not contain underscores", Justification = "Read above.")]
public static void PropertySetterPatch(MethodBase __originalMethod, object value) public static void PropertySetterPatch(MethodBase __originalMethod, object value)
{ {
var attribute = OptionAttributes.First(pair => pair.Key.GetSetMethod() == __originalMethod).Value; if (!SetterLookups.TryGetValue(__originalMethod, out var attribute))
return;
attribute.SetValue(value); attribute.SetValue(value);
if (attribute is ModdedOptionListAttribute listAttribute && value != null)
ListInstanceCache.AddOrUpdate(value, listAttribute);
} }
/// <summary> /// <summary>
@@ -436,7 +455,9 @@ public static class ModdedOptionsManager
[SuppressMessage("Naming", "CA1707:Identifiers should not contain underscores", Justification = "Read above.")] [SuppressMessage("Naming", "CA1707:Identifiers should not contain underscores", Justification = "Read above.")]
public static bool PropertyGetterPatch(MethodBase __originalMethod, ref object __result) public static bool PropertyGetterPatch(MethodBase __originalMethod, ref object __result)
{ {
var attribute = OptionAttributes.First(pair => pair.Key.GetGetMethod() == __originalMethod).Value; if (!GetterLookups.TryGetValue(__originalMethod, out var attribute))
return true;
__result = attribute.GetValue(); __result = attribute.GetValue();
return false; return false;
} }
@@ -451,10 +472,8 @@ public static class ModdedOptionsManager
[SuppressMessage("Naming", "CA1707:Identifiers should not contain underscores", Justification = "Read above.")] [SuppressMessage("Naming", "CA1707:Identifiers should not contain underscores", Justification = "Read above.")]
public static void PropertyListSetterPatch(object __instance, int index, object value) public static void PropertyListSetterPatch(object __instance, int index, object value)
{ {
var match = OptionAttributes.Values if (ListInstanceCache.TryGetValue(__instance, out var match))
.OfType<ModdedOptionListAttribute>() match.SetValue(index, value);
.FirstOrDefault(list => ReferenceEquals(list.Value, __instance));
match?.SetValue(index, value);
} }
/// <summary> /// <summary>
@@ -468,11 +487,7 @@ public static class ModdedOptionsManager
[SuppressMessage("Naming", "CA1707:Identifiers should not contain underscores", Justification = "Read above.")] [SuppressMessage("Naming", "CA1707:Identifiers should not contain underscores", Justification = "Read above.")]
public static bool PropertyListGetterPatch(object __instance, int index, ref object __result) public static bool PropertyListGetterPatch(object __instance, int index, ref object __result)
{ {
var match = OptionAttributes.Values if (!ListInstanceCache.TryGetValue(__instance, out var match))
.OfType<ModdedOptionListAttribute>()
.FirstOrDefault(list => ReferenceEquals(list.Value, __instance));
if (match is null)
return true; return true;
__result = match.GetValue(index); __result = match.GetValue(index);
+4 -1
View File
@@ -313,7 +313,10 @@ public sealed class MiraPluginManager
foreach (var property in type.GetProperties()) foreach (var property in type.GetProperties())
{ {
if (property.GetMethod?.IsStatic == true && property.GetCustomAttribute<MiraIgnoreAttribute>() == null) if (property.GetCustomAttribute<MiraIgnoreAttribute>() != null)
continue;
if (property.GetMethod?.IsStatic == true)
{ {
Error($"Non-ignored option property {property.Name} in {type.Name} must not be static."); Error($"Non-ignored option property {property.Name} in {type.Name} must not be static.");
continue; continue;