Find the latest role options collection at start

This should help avoid the api breaking from additional roles and additional settings.
This commit is contained in:
Atony committed 2026-09-24 17:08:56 -05:00
1 parent 2cfdbea51f
commit f89ffb0d86
2 files changed
+63 -10

No files matched your search

+5
View File
@@ -1,10 +1,14 @@
global using static Reactor.Utilities.Logger<MiraAPI.MiraApiPlugin>; global using static Reactor.Utilities.Logger<MiraAPI.MiraApiPlugin>;
using System; using System;
using System.Globalization; using System.Globalization;
using System.Linq;
using System.Reflection;
using AmongUs.GameOptions;
using BepInEx; using BepInEx;
using BepInEx.Configuration; using BepInEx.Configuration;
using BepInEx.Unity.IL2CPP; using BepInEx.Unity.IL2CPP;
using HarmonyLib; using HarmonyLib;
using MiraAPI.Patches.Roles;
using MiraAPI.PluginLoading; using MiraAPI.PluginLoading;
using MiraAPI.Translation; using MiraAPI.Translation;
using MiraAPI.VanillaEvents; using MiraAPI.VanillaEvents;
@@ -70,6 +74,7 @@ public partial class MiraApiPlugin : BasePlugin, IMiraPlugin
public override void Load() public override void Load()
{ {
Harmony.PatchAll(); Harmony.PatchAll();
RoleOptionsCollectionPatch.PatchRoleMethods(Harmony);
UiResetEvents.Initialize(); UiResetEvents.Initialize();
JudgeEvents.Initialize(); JudgeEvents.Initialize();
@@ -1,4 +1,7 @@
using AmongUs.GameOptions; using System;
using System.Linq;
using System.Reflection;
using AmongUs.GameOptions;
using HarmonyLib; using HarmonyLib;
using Il2CppSystem.Collections.Generic; using Il2CppSystem.Collections.Generic;
using MiraAPI.Roles; using MiraAPI.Roles;
@@ -8,17 +11,66 @@ namespace MiraAPI.Patches.Roles;
/// <summary> /// <summary>
/// Patches to return the correct role counts. /// Patches to return the correct role counts.
/// </summary> /// </summary>
[HarmonyPatch(typeof(RoleOptionsCollectionV11))]
public static class RoleOptionsCollectionPatch public static class RoleOptionsCollectionPatch
{ {
internal static Assembly BaseAssembly { get; private set; }
internal static Type[] BaseTypes { get; private set; }
internal static Type CollectionsType { get; private set; }
public static void PatchRoleMethods(Harmony harmony)
{
var assembly = Array.Find(
AppDomain.CurrentDomain.GetAssemblies(),
ass => ass.GetName().Name == "Assembly-CSharp"
);
if (assembly != null)
{
var compatType = typeof(RoleOptionsCollectionPatch);
BaseAssembly = assembly;
BaseTypes = AccessTools.GetTypesFromAssembly(assembly);
var collections = BaseTypes.Where(x => x.Name.Contains("RoleOptionsCollectionV")).ToArray();
var pairings = new System.Collections.Generic.Dictionary<int, Type>();
var newestId = 0;
foreach (var collection in collections)
{
var remainer = collection.Name.Replace("RoleOptionsCollectionV", string.Empty);
if (int.TryParse(remainer, out var id))
{
pairings.Add(id, collection);
if (newestId < id)
{
newestId = id;
}
}
}
if (pairings.TryGetValue(newestId, out var typeToGet))
{
CollectionsType = typeToGet;
}
var anyRolesEnabledMethod = AccessTools.Method(CollectionsType, "AnyRolesEnabled");
harmony.Patch(
anyRolesEnabledMethod,
new HarmonyMethod(AccessTools.Method(compatType, nameof(AnyRolesEnabledPrefix))));
var chancePerGameMethod = AccessTools.Method(CollectionsType, "GetChancePerGame");
harmony.Patch(
chancePerGameMethod,
new HarmonyMethod(AccessTools.Method(compatType, nameof(GetChancePrefix))));
var numPerGameMethod = AccessTools.Method(CollectionsType, "GetNumPerGame");
harmony.Patch(
numPerGameMethod,
new HarmonyMethod(AccessTools.Method(compatType, nameof(GetNumPrefix))));
Info($"Patched methods for RoleOptionsCollectionV{newestId}");
}
}
/// <summary> /// <summary>
/// This patch fixes <see cref="RoleOptionsCollectionV11.GetNumPerGame(RoleTypes)"/> being inlined (2025.9.9) in the original code. /// This patch fixes <see cref="RoleOptionsCollectionV11.GetNumPerGame(RoleTypes)"/> being inlined (2025.9.9) in the original code.
/// </summary> /// </summary>
[HarmonyPrefix] public static bool AnyRolesEnabledPrefix(dynamic __instance, ref bool __result)
[HarmonyPatch(nameof(RoleOptionsCollectionV11.AnyRolesEnabled))]
public static bool AnyRolesEnabledPrefix(RoleOptionsCollectionV11 __instance, ref bool __result)
{ {
foreach (KeyValuePair<RoleTypes, RoleDataV11> keyValuePair in __instance.roles) foreach (KeyValuePair<RoleTypes, dynamic> keyValuePair in __instance.roles)
{ {
if (__instance.GetNumPerGame(keyValuePair.Key) > 0) if (__instance.GetNumPerGame(keyValuePair.Key) > 0)
{ {
@@ -32,8 +84,6 @@ public static class RoleOptionsCollectionPatch
/// Set the role chance for custom Launchpad roles based on config. /// Set the role chance for custom Launchpad roles based on config.
/// </summary> /// </summary>
/// <returns>Return <see langword="false"/> to skip original method, <see langword="true"/> to not.</returns> /// <returns>Return <see langword="false"/> to skip original method, <see langword="true"/> to not.</returns>
[HarmonyPrefix]
[HarmonyPatch(nameof(RoleOptionsCollectionV11.GetChancePerGame))]
public static bool GetChancePrefix(RoleTypes role, ref int __result) public static bool GetChancePrefix(RoleTypes role, ref int __result)
{ {
if (!CustomRoleManager.GetCustomRoleBehaviour(role, out var customRole) || customRole == null) if (!CustomRoleManager.GetCustomRoleBehaviour(role, out var customRole) || customRole == null)
@@ -62,8 +112,6 @@ public static class RoleOptionsCollectionPatch
/// Set the amount for custom Launchpad roles based on config. /// Set the amount for custom Launchpad roles based on config.
/// </summary> /// </summary>
/// <returns>Return <see langword="false"/> to skip original method, <see langword="true"/> to not.</returns> /// <returns>Return <see langword="false"/> to skip original method, <see langword="true"/> to not.</returns>
[HarmonyPrefix]
[HarmonyPatch(nameof(RoleOptionsCollectionV11.GetNumPerGame))]
public static bool GetNumPrefix(RoleTypes role, ref int __result) public static bool GetNumPrefix(RoleTypes role, ref int __result)
{ {
if (!CustomRoleManager.GetCustomRoleBehaviour(role, out var customRole) || customRole == null) if (!CustomRoleManager.GetCustomRoleBehaviour(role, out var customRole) || customRole == null)