Merge pull request #96 from All-Of-Us-Mods/dev

MiraAPI 0.4.2
This commit is contained in:
Atony authored and GitHub committed 2026-08-02 20:11:59 -05:00
commit 83e550c1f2
82 files changed
+591 -252

No files matched your search

+1 -2
View File
@@ -1,5 +1,4 @@
using System.Linq;
using BepInEx;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Unity.IL2CPP;
using HarmonyLib;
@@ -9,7 +9,7 @@ public class GeneralModifierOptions : AbstractOptionGroup
public override uint GroupPriority => 0;
public override bool ShowInModifiersMenu => true;
public override MenuCategory ParentMenu => MenuCategory.Modifiers;
[ModdedToggleOption("Some Boolean Option")]
public bool SomeBooleanOption { get; set; } = true;
@@ -2,11 +2,17 @@
using MiraAPI.GameOptions;
using MiraAPI.GameOptions.Attributes;
using MiraAPI.Utilities;
using MiraAPI.Utilities.Assets;
namespace MiraAPI.Example.Options.Roles;
public class FreezerRoleSettings : AbstractOptionGroup<FreezerRole>
{
public override OptionNotifConfiguration Configuration => new(
Palette.Blue,
TmpSpriteUtils.CreateSpriteAsset(
MiraAssets.ImpostorFile.LoadAsset(),
"ApiExample.Role.Impostor.FreezerRole"));
public override string GroupName => "Custom Role";
[ModdedNumberOption("Freeze Duration", 1, 15, 1, MiraNumberSuffixes.Seconds)]
@@ -6,7 +6,7 @@ using MiraAPI.Utilities;
namespace MiraAPI.Example.Options.Roles;
public class TeleporterOptions : AbstractOptionGroup<TeleporterRole>
public class TeleporterOptions : AbstractRoleOptionGroup<TeleporterRole>
{
public override string GroupName => "Teleporter";
+3
View File
@@ -1,6 +1,7 @@
using AmongUs.GameOptions;
using MiraAPI.Patches.Stubs;
using MiraAPI.Roles;
using MiraAPI.Utilities.Assets;
using Reactor.Utilities;
using TMPro;
using UnityEngine;
@@ -20,6 +21,8 @@ public class ChameloenRole : CrewmateRole, ICustomRole
public CustomRoleConfiguration Configuration => new(this)
{
OptionsScreenshot = ExampleAssets.Banner,
Icon = MiraAssets.CrewmateFile,
IconTmp = TmpSpriteUtils.CreateSpriteAsset(MiraAssets.CrewmateFile.LoadAsset(), "ApiExample.Role.Impostor.ChameleonRole"),
IntroSound = CustomRoleUtils.GetIntroSound(RoleTypes.Shapeshifter),
};
+3
View File
@@ -1,4 +1,5 @@
using MiraAPI.Roles;
using MiraAPI.Utilities.Assets;
using UnityEngine;
namespace MiraAPI.Example.Roles;
@@ -13,6 +14,8 @@ public class FreezerRole : ImpostorRole, ICustomRole
public CustomRoleConfiguration Configuration => new CustomRoleConfiguration(this)
{
Icon = MiraAssets.ImpostorFile,
IconTmp = TmpSpriteUtils.CreateSpriteAsset(MiraAssets.ImpostorFile.LoadAsset(), "ApiExample.Role.Impostor.FreezerRole"),
OptionsScreenshot = ExampleAssets.Banner,
MaxRoleCount = 2,
};
-1
View File
@@ -1,7 +1,6 @@
using System;
using System.Collections.Generic;
using System.Reflection;
using Reactor.Utilities;
namespace MiraAPI.Events;
@@ -1,6 +1,4 @@
using MiraAPI.Voting;
namespace MiraAPI.Events.Vanilla.Meeting.Voting;
namespace MiraAPI.Events.Vanilla.Meeting.Voting;
/// <summary>
/// Event that is invoked after the local player successfully votes a player or skips. This event is not cancelable.
@@ -1,6 +1,4 @@
using MiraAPI.Voting;
namespace MiraAPI.Events.Vanilla.Meeting.Voting;
namespace MiraAPI.Events.Vanilla.Meeting.Voting;
/// <summary>
/// Event that is invoked before the local player confirms a vote on a player or when skipping. This event is cancelable.
-1
View File
@@ -1,7 +1,6 @@
using System;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using Reactor.Utilities;
namespace MiraAPI.GameEnd;
@@ -1,7 +1,6 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Reactor.Utilities;
namespace MiraAPI.GameModes;
+38 -4
View File
@@ -1,7 +1,9 @@
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using MiraAPI.Modifiers;
using MiraAPI.Roles;
using UnityEngine;
namespace MiraAPI.GameOptions;
@@ -40,7 +42,7 @@ public abstract class AbstractOptionGroup
/// <summary>
/// Gets a value indicating which menu the group is in.
/// </summary>
public virtual MenuCategory ParentMenu => MenuCategory.Roles;
public virtual MenuCategory ParentMenu => MenuCategory.Game;
/// <summary>
/// Gets the function that determines whether the group should be visible or not.
@@ -58,9 +60,16 @@ public abstract class AbstractOptionGroup
/// </summary>
public virtual uint GroupPriority => uint.MaxValue;
/// <summary>
/// Gets the default notification settings for the group.
/// </summary>
public virtual OptionNotifConfiguration Configuration => new(new Color(0.7333f, 0.7333f, 0.7333f, 1));
internal bool AllOptionsHidden { get; set; }
internal CategoryHeaderMasked? Header { get; set; }
internal Coroutine? CreationCoroutine { get; set; }
}
/// <summary>
@@ -72,9 +81,7 @@ public abstract class AbstractOptionGroup<T> : AbstractOptionGroup where T : IOp
/// <inheritdoc />
public override Type OptionableType => typeof(T);
/// <summary>
/// Gets a value indicating which menu the group is in.
/// </summary>
/// <inheritdoc />
public override MenuCategory ParentMenu
{
get
@@ -93,6 +100,33 @@ public abstract class AbstractOptionGroup<T> : AbstractOptionGroup where T : IOp
}
}
/// <summary>
/// Base class for option groups. An option group is a collection of options that are displayed together in the options menu.
/// </summary>
/// <typeparam name="T">The custom role that the group is for.</typeparam>
public abstract class AbstractRoleOptionGroup<T>() : AbstractOptionGroup<T> where T : ICustomRole
{
/// <inheritdoc />
public override Type OptionableType => typeof(T);
/// <inheritdoc />
public override MenuCategory ParentMenu => MenuCategory.Roles;
/// <inheritdoc />
public override OptionNotifConfiguration Configuration
{
get
{
var role = CustomRoleManager.CustomMiraRoles.FirstOrDefault(x => x.GetType() == OptionableType);
if (role == null)
{
return new(new Color(0.7333f, 0.7333f, 0.7333f, 1));
}
return new(role.RoleColor, role.Configuration.IconTmp);
}
}
}
/// <summary>
/// Menu categories for option groups.
/// </summary>
+10
View File
@@ -21,6 +21,16 @@ public interface IModdedOption
/// </summary>
string Title { get; set; }
/// <summary>
/// Gets or sets the parent <see cref="AbstractOptionGroup"/> of the option.
/// </summary>
AbstractOptionGroup ParentGroup { get; set; }
/// <summary>
/// Gets the notification settings for the option.
/// </summary>
OptionNotifConfiguration Configuration { get; }
/// <summary>
/// Gets the <see cref="StringNames"/> for the option, used for localization.
/// </summary>
@@ -12,6 +12,8 @@ using MiraAPI.PluginLoading;
using MiraAPI.Utilities;
using Reactor.Networking.Rpc;
using Reactor.Utilities;
using TMPro;
using UnityEngine;
namespace MiraAPI.GameOptions;
@@ -30,6 +32,36 @@ public static class ModdedOptionsManager
internal static uint NextId => _nextId++;
private static uint _nextId = 1;
public static void AddSettingsChangeMessage(NotificationPopper notif, StringNames key, string value, Color textColor, TMP_SpriteAsset? sprite, bool playSound = true)
{
var item = string.Empty;
var text = textColor.ToTextColor();
if (sprite != null)
{
item = TranslationController.Instance.GetString(
StringNames.LobbyChangeSettingNotification,
string.Concat(
"<sprite name=\"",
sprite.name,
"\"><font=\"Barlow-Black SDF\" material=\"Barlow-Black Outline\">",
text,
TranslationController.Instance.GetString(key),
"</color></font>"),
"<font=\"Barlow-Black SDF\" material=\"Barlow-Black Outline\">" + value + "</font>"
);
}
else
{
item = TranslationController.Instance.GetString(
StringNames.LobbyChangeSettingNotification,
"<font=\"Barlow-Black SDF\" material=\"Barlow-Black Outline\">" +
text +
TranslationController.Instance.GetString(key) + "</color></font>",
"<font=\"Barlow-Black SDF\" material=\"Barlow-Black Outline\">" + value + "</font>");
}
notif.SettingsChangeMessageLogic(key, item, playSound);
}
internal static bool RegisterGroup(Type type, MiraPluginInfo pluginInfo)
{
if (Activator.CreateInstance(type) is not AbstractOptionGroup group)
@@ -123,6 +155,7 @@ public static class ModdedOptionsManager
option.ConfigDefinition = new ConfigDefinition(groupName, propertyName);
option.ParentGroup = group;
option.ParentMod = pluginInfo.MiraPlugin;
pluginInfo.InternalOptions.Add(option);
ModdedOptions.Add(option.Id, option);
@@ -0,0 +1,53 @@
using System;
using Il2CppInterop.Runtime.Attributes;
using TMPro;
using UnityEngine;
namespace MiraAPI.GameOptions;
/// <summary>
/// Used to configure the specific visuals for option notifications.
/// </summary>
public record struct OptionNotifConfiguration
{
#pragma warning disable S1133
[Obsolete("Default constructor is not supported")]
#pragma warning restore S1133
#pragma warning disable CS1591 // Missing XML comment for publicly visible type or member
public OptionNotifConfiguration()
#pragma warning restore CS1591 // Missing XML comment for publicly visible type or member
{
throw new NotImplementedException("Default constructor is not supported.");
}
/// <summary>
/// Initializes a new instance of the <see cref="OptionNotifConfiguration"/> struct based on a group.
/// </summary>
/// <param name="group">The <see cref="AbstractOptionGroup"/> in which you are configuring.</param>
public OptionNotifConfiguration(AbstractOptionGroup group)
{
PopUpIconTmp = group.Configuration.PopUpIconTmp;
PopUpTextColor = group.Configuration.PopUpTextColor;
}
/// <summary>
/// Initializes a new instance of the <see cref="OptionNotifConfiguration"/> struct from scratch.
/// </summary>
/// <param name="color">The text <see cref="Color"/> for the configuration.</param>
/// <param name="asset">The <see cref="TMP_SpriteAsset"/> icon for the configuration.</param>
public OptionNotifConfiguration(Color color, TMP_SpriteAsset asset = null!)
{
PopUpIconTmp = asset;
PopUpTextColor = color;
}
/// <summary>
/// Gets or sets the <see cref="TMP_SpriteAsset"/> for the icon on the options pop-up.
/// </summary>
public TMP_SpriteAsset PopUpIconTmp { get; set; }
/// <summary>
/// Gets or sets the <see cref="Color"/> for the text on the options pop-up.
/// </summary>
[HideFromIl2Cpp]
public Color PopUpTextColor { get; set; }
}
@@ -90,7 +90,13 @@ public class ModdedEnumOption : ModdedOption<int>
/// <inheritdoc />
protected override void OnValueChanged(int newValue)
{
HudManager.Instance.Notifier.AddSettingsChangeMessage(StringName, Data.GetValueString(newValue), false);
ModdedOptionsManager.AddSettingsChangeMessage(
HudManager.Instance.Notifier,
StringName,
Data.GetValueString(newValue),
Configuration.PopUpTextColor,
Configuration.PopUpIconTmp,
false);
if (!OptionBehaviour)
{
return;
@@ -183,7 +189,13 @@ public class ModdedEnumOption<T> : ModdedOption<T> where T : Enum
/// <inheritdoc />
protected override void OnValueChanged(T newValue)
{
HudManager.Instance.Notifier.AddSettingsChangeMessage(StringName, Data.GetValueString(Convert.ToInt32(newValue, NumberFormatInfo.InvariantInfo)), false);
ModdedOptionsManager.AddSettingsChangeMessage(
HudManager.Instance.Notifier,
StringName,
Data.GetValueString(Convert.ToInt32(newValue, NumberFormatInfo.InvariantInfo)),
Configuration.PopUpTextColor,
Configuration.PopUpIconTmp,
false);
if (!OptionBehaviour)
{
return;
@@ -225,9 +225,12 @@ public class ModdedNumberOption : ModdedOption<float>
protected override void OnValueChanged(float newValue)
{
Value = Mathf.Clamp(newValue, Min, Max);
HudManager.Instance.Notifier.AddSettingsChangeMessage(
ModdedOptionsManager.AddSettingsChangeMessage(
HudManager.Instance.Notifier,
StringName,
Data.GetValueString(Value),
Data.GetValueString(newValue),
Configuration.PopUpTextColor,
Configuration.PopUpIconTmp,
false);
if (OptionBehaviour is NumberOption opt)
@@ -4,7 +4,6 @@ using MiraAPI.Networking;
using MiraAPI.PluginLoading;
using Reactor.Localization.Utilities;
using Reactor.Networking.Rpc;
using Reactor.Utilities;
using UnityEngine;
namespace MiraAPI.GameOptions.OptionTypes;
@@ -190,4 +189,10 @@ public abstract class ModdedOption<T> : IModdedOption
{
return option.Value;
}
/// <inheritdoc />
public AbstractOptionGroup ParentGroup { get; set; }
/// <inheritdoc />
public virtual OptionNotifConfiguration Configuration => new(ParentGroup);
}
@@ -126,7 +126,13 @@ public class ModdedPlayerOption : ModdedOption<int>
/// <inheritdoc />
protected override void OnValueChanged(int newValue)
{
HudManager.Instance.Notifier.AddSettingsChangeMessage(StringName, Data.GetValueString(newValue), false);
ModdedOptionsManager.AddSettingsChangeMessage(
HudManager.Instance.Notifier,
StringName,
Data.GetValueString(newValue),
Configuration.PopUpTextColor,
Configuration.PopUpIconTmp,
false);
if (!OptionBehaviour)
{
return;
@@ -71,7 +71,13 @@ public class ModdedToggleOption : ModdedOption<bool>
/// <inheritdoc />
protected override void OnValueChanged(bool newValue)
{
HudManager.Instance.Notifier.AddSettingsChangeMessage(StringName, newValue ? "On" : "Off", false);
ModdedOptionsManager.AddSettingsChangeMessage(
HudManager.Instance.Notifier,
StringName,
newValue ? "On" : "Off",
Configuration.PopUpTextColor,
Configuration.PopUpIconTmp,
false);
if (!OptionBehaviour)
{
return;
-1
View File
@@ -7,7 +7,6 @@ using MiraAPI.LocalSettings;
using MiraAPI.Patches;
using MiraAPI.Utilities;
using MiraAPI.Utilities.Assets;
using Reactor.Utilities;
using Rewired;
using TMPro;
using UnityEngine;
-1
View File
@@ -4,7 +4,6 @@ using System.Collections.ObjectModel;
using System.Reflection;
using MiraAPI.Events.Mira;
using MiraAPI.PluginLoading;
using UnityEngine;
namespace MiraAPI.Hud;
-1
View File
@@ -1,6 +1,5 @@
using System.Linq;
using HarmonyLib;
using Reactor.Utilities.Extensions;
using UnityEngine;
namespace MiraAPI.Hud;
-1
View File
@@ -3,7 +3,6 @@ using System.Collections.Generic;
using System.Linq;
using Il2CppInterop.Runtime.Attributes;
using MiraAPI.Utilities;
using Reactor.Utilities;
using Rewired;
namespace MiraAPI.Keybinds;
-1
View File
@@ -1,5 +1,4 @@
using System.Globalization;
using Rewired;
namespace MiraAPI.Keybinds;
@@ -1,5 +1,4 @@
using System;
using BepInEx.Configuration;
namespace MiraAPI.LocalSettings.Attributes;
@@ -1,6 +1,5 @@
using System;
using MiraAPI.Utilities;
using Reactor.Localization.Utilities;
using Reactor.Utilities.Extensions;
using TMPro;
using UnityEngine;
@@ -2,8 +2,6 @@
using System.Collections.Generic;
using System.Reflection;
using BepInEx.Unity.IL2CPP;
using MiraAPI.GameOptions;
using Reactor.Utilities;
namespace MiraAPI.LocalSettings;
@@ -14,6 +12,7 @@ public static class LocalSettingsManager
{
internal static readonly Dictionary<Type, LocalSettingsTab> TypeToTab = [];
internal static readonly List<LocalSettingsTab> Tabs = [];
internal static readonly List<LocalSettingsTab> AvailableTabs = [];
internal static bool RegisterTab(Type type, BasePlugin pluginInfo)
{
@@ -29,6 +28,10 @@ public static class LocalSettingsManager
}
Tabs.Add(tab);
if (tab.ShouldCreateButton)
{
AvailableTabs.Add(tab);
}
TypeToTab.Add(type, tab);
typeof(LocalSettingsTabSingleton<>).MakeGenericType(type)
-1
View File
@@ -8,7 +8,6 @@ using MiraAPI.LocalSettings;
using MiraAPI.Modifiers.ModifierDisplay;
using MiraAPI.Modifiers.Types;
using MiraAPI.Patches.Roles;
using Reactor.Utilities;
using Reactor.Utilities.Attributes;
using UnityEngine;
@@ -4,7 +4,6 @@ using System.Linq;
using HarmonyLib;
using Il2CppInterop.Runtime.Attributes;
using MiraAPI.LocalSettings;
using MiraAPI.Utilities;
using MiraAPI.Utilities.Assets;
using Reactor.Utilities.Attributes;
using Reactor.Utilities.Extensions;
@@ -138,7 +137,7 @@ public class ModifierDisplayComponent(nint cppPtr) : MonoBehaviour(cppPtr)
internal void DestroyComponent(ModifierUiComponent component)
{
_modifiers.Remove(component.Modifier!);
component.gameObject.DeepDestroy();
component.gameObject.Destroy();
RefreshModifiers();
}
@@ -208,7 +207,7 @@ public class ModifierDisplayComponent(nint cppPtr) : MonoBehaviour(cppPtr)
continue;
}
mod.Value.gameObject.DeepDestroy();
mod.Value.gameObject.Destroy();
_modifiers.Remove(mod.Key);
}
-1
View File
@@ -5,7 +5,6 @@ using MiraAPI.Networking;
using MiraAPI.Networking.Modifiers;
using Reactor.Networking.Attributes;
using Reactor.Networking.Rpc;
using Reactor.Utilities;
namespace MiraAPI.Modifiers;
+7 -3
View File
@@ -6,7 +6,6 @@ using MiraAPI.Modifiers.Types;
using MiraAPI.PluginLoading;
using MiraAPI.Roles;
using MiraAPI.Utilities;
using Reactor.Utilities;
using Reactor.Utilities.Extensions;
using Random = System.Random;
@@ -153,7 +152,7 @@ public static class ModifierManager
}
var candidates = availablePlayers
.Where(x => IsGameModifierValid(x, modifier, modifier.TypeId))
.Where(x => IsGameModifierPostCheck(x, modifier, modifier.TypeId))
.ToList();
if (candidates.Count == 0)
@@ -179,7 +178,12 @@ public static class ModifierManager
private static bool IsGameModifierValid(PlayerControl player, GameModifier modifier, uint modifierId)
{
return (player.Data.Role is not ICustomRole role || role.IsModifierApplicable(modifier)) &&
modifier.IsModifierValidOn(player.Data.Role) && !player.HasModifier(modifierId) &&
!player.HasModifier(modifierId) && modifier.IsModifierValidOn(player.Data.Role) &&
modifier.CanSpawnOnCurrentMode();
}
private static bool IsGameModifierPostCheck(PlayerControl player, GameModifier modifier, uint modifierId)
{
return (player.Data.Role is not ICustomRole role || role.IsModifierApplicable(modifier)) &&
!player.HasModifier(modifierId) && modifier.IsModifierValidOnPostCheck(player.Data.Role);
}
}
+7
View File
@@ -33,6 +33,13 @@ public abstract class GameModifier : BaseModifier
/// <returns><see langword="true"/> if the modifier is valid on the role, otherwise <see langword="false"/>.</returns>
public virtual bool IsModifierValidOn(RoleBehaviour role) => true;
/// <summary>
/// Determines whether the modifier is valid on a role, which runs after players are determined but before the modifiers are given.
/// </summary>
/// <param name="role">The role to be checked.</param>
/// <returns><see langword="true"/> if the modifier is valid on the role, otherwise <see langword="false"/>.</returns>
public virtual bool IsModifierValidOnPostCheck(RoleBehaviour role) => IsModifierValidOn(role);
/// <summary>
/// Determines whether the player won the game with this modifier. The modifier with the highest priority will override other modifiers.
/// </summary>
-1
View File
@@ -1,5 +1,4 @@
using System;
using Reactor.Utilities;
using UnityEngine;
namespace MiraAPI.Modifiers.Types;
-1
View File
@@ -4,7 +4,6 @@ using InnerNet;
using MiraAPI.GameEnd;
using Reactor.Networking.Attributes;
using Reactor.Networking.Rpc;
using Reactor.Utilities;
namespace MiraAPI.Networking;
-3
View File
@@ -10,9 +10,6 @@ using MiraAPI.Events.Vanilla.Gameplay;
using MiraAPI.Utilities;
using Reactor.Networking.Attributes;
using Reactor.Networking.Rpc;
using Reactor.Utilities;
using Reactor.Utilities.Extensions;
using Rewired;
using UnityEngine;
using Object = UnityEngine.Object;
@@ -4,7 +4,6 @@ using InnerNet;
using MiraAPI.Events;
using MiraAPI.Events.Vanilla.Meeting;
using MiraAPI.Utilities;
using Reactor.Utilities;
namespace MiraAPI.Patches.Events;
@@ -1,9 +1,7 @@
using System.Linq;
using AmongUs.GameOptions;
using AmongUs.GameOptions;
using HarmonyLib;
using MiraAPI.Events;
using MiraAPI.Events.Vanilla.Gameplay;
using MiraAPI.Events.Vanilla.Usables;
namespace MiraAPI.Patches.Events;
+6 -1
View File
@@ -254,6 +254,12 @@ public static class TaskAdderPatches
.ToArray()
.Any(x => x.FolderName == child.FolderName);
[HarmonyPostfix]
[HarmonyPatch(nameof(TaskAdderGame.OnDisable))]
public static void ClosePatch()
{
Utilities.Extensions.ClearGarbageCollector();
}
// yes it might be crazy patching the entire method, but i tried so many other methods and only this works :cry:
// true -chip
[HarmonyPrefix]
@@ -278,7 +284,6 @@ public static class TaskAdderPatches
__instance.ActiveItems.ToArray().Do(x => x.gameObject.DeepDestroy(false));
__instance.ActiveItems.Clear();
Utilities.Extensions.ClearGarbageCollector();
float num = 0f;
float num2 = 0f;
@@ -1,6 +1,5 @@
using HarmonyLib;
using MiraAPI.Hud;
using Reactor.Utilities;
namespace MiraAPI.Patches.Hud;
+1 -1
View File
@@ -148,7 +148,7 @@ public static class HudManagerPatches
foreach (var t in BottomLeft.GetComponentsInChildren<ActionButton>(true))
{
t.gameObject.DeepDestroy(false);
t.gameObject.Destroy();
}
Utilities.Extensions.ClearGarbageCollector();
+1 -3
View File
@@ -1,12 +1,10 @@
using System.Linq;
using System.Reflection;
using System.Reflection;
using HarmonyLib;
using Il2CppInterop.Runtime.InteropTypes;
using MiraAPI.Events;
using MiraAPI.Events.Vanilla.Gameplay;
using MiraAPI.Roles;
using MiraAPI.Utilities;
using Reactor.Utilities;
namespace MiraAPI.Patches;
@@ -1,13 +1,8 @@
using System.Linq;
using HarmonyLib;
using MiraAPI.Keybinds;
using MiraAPI.LocalSettings;
using Reactor.Utilities;
using Reactor.Utilities.Extensions;
using Rewired.UI.ControlMapper;
using TMPro;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.UI;
namespace MiraAPI.Patches.Keybinds;
@@ -1,6 +1,5 @@
using HarmonyLib;
using MiraAPI.Keybinds;
using MonoMod.Utils;
using Rewired;
namespace MiraAPI.Patches.Keybinds;
@@ -3,7 +3,6 @@ using System.Linq;
using HarmonyLib;
using MiraAPI.LocalSettings;
using MiraAPI.Utilities.Assets;
using Reactor.Utilities;
using Reactor.Utilities.Extensions;
using UnityEngine;
using UnityEngine.Events;
@@ -70,7 +69,7 @@ public static class OptionsMenuPatches
int i = 0;
int tabIdx = 0;
int page = 1;
foreach (var settings in LocalSettingsManager.Tabs)
foreach (var settings in LocalSettingsManager.AvailableTabs)
{
var tab = settings.CreateTab(__instance);
if (settings.ShouldCreateButton)
@@ -165,12 +164,12 @@ public static class OptionsMenuPatches
public static bool OpenTabGroupPrefix(OptionsMenuBehaviour __instance, ref int index)
{
__instance.Tabs.ToList().ForEach(x => x.Close()); // Close all vanilla tabs
LocalSettingsManager.Tabs.ForEach(CustomClose); // Close all mod tabs
LocalSettingsManager.AvailableTabs.ForEach(CustomClose); // Close all mod tabs
// Tabs with index 10 and above are the mod settings tabs
if (index >= 10)
{
CustomOpen(LocalSettingsManager.Tabs[index - 10]);
CustomOpen(LocalSettingsManager.AvailableTabs[index - 10]);
return false;
}
@@ -184,7 +183,7 @@ public static class OptionsMenuPatches
[HarmonyPatch(nameof(OptionsMenuBehaviour.Open))]
public static void OpenPostfix(OptionsMenuBehaviour __instance)
{
LocalSettingsManager.Tabs.ForEach(CustomClose);
LocalSettingsManager.AvailableTabs.ForEach(CustomClose);
currentPage = 1;
UpdatePages();
}
+1 -2
View File
@@ -100,10 +100,9 @@ public static class HatsTabPatches
if (loadRoutine != null) Coroutines.Stop(loadRoutine);
hatIndex = 0;
foreach (var instanceColorChip in __instance.ColorChips) instanceColorChip.gameObject.DeepDestroy(false);
foreach (var instanceColorChip in __instance.ColorChips) instanceColorChip.gameObject.Destroy();
__instance.ColorChips.Clear();
__instance.scroller.Inner.GetComponentsInChildren<TextMeshPro>().Do(x => x.gameObject.DeepDestroy(false));
Utilities.Extensions.ClearGarbageCollector();
var groupNameText = __instance.GetComponentInChildren<TextMeshPro>(false);
var group = sortedHats.Where(x => x.Key == storeNames[page]);
+1 -2
View File
@@ -81,10 +81,9 @@ public static class NameplatesTabPatches
private static void GenerateHats(NameplatesTab __instance, int page)
{
foreach (var instanceColorChip in __instance.ColorChips) instanceColorChip.gameObject.DeepDestroy(false);
foreach (var instanceColorChip in __instance.ColorChips) instanceColorChip.gameObject.Destroy();
__instance.ColorChips.Clear();
__instance.scroller.Inner.GetComponentsInChildren<TextMeshPro>().Do(x => x.gameObject.DeepDestroy(false));
Utilities.Extensions.ClearGarbageCollector();
var groupNameText = __instance.GetComponentInChildren<TextMeshPro>(false);
+1 -2
View File
@@ -83,10 +83,9 @@ public static class SkinsTabPatches
private static void GenerateHats(SkinsTab __instance, int page)
{
foreach (var instanceColorChip in __instance.ColorChips) instanceColorChip.gameObject.DeepDestroy(false);
foreach (var instanceColorChip in __instance.ColorChips) instanceColorChip.gameObject.Destroy();
__instance.ColorChips.Clear();
__instance.scroller.Inner.GetComponentsInChildren<TextMeshPro>().Do(x => x.gameObject.DeepDestroy(false));
Utilities.Extensions.ClearGarbageCollector();
var groupNameText = __instance.GetComponentInChildren<TextMeshPro>(false);
+1 -2
View File
@@ -80,10 +80,9 @@ public static class VisorsTabPatches
private static void GenerateHats(VisorsTab __instance, int page)
{
foreach (var instanceColorChip in __instance.ColorChips) instanceColorChip.gameObject.DeepDestroy(false);
foreach (var instanceColorChip in __instance.ColorChips) instanceColorChip.gameObject.Destroy();
__instance.ColorChips.Clear();
__instance.scroller.Inner.GetComponentsInChildren<TextMeshPro>().Do(x => x.gameObject.DeepDestroy(false));
Utilities.Extensions.ClearGarbageCollector();
var groupNameText = __instance.GetComponentInChildren<TextMeshPro>(false);
+44 -25
View File
@@ -1,8 +1,8 @@
using System;
using System.Collections;
using System.Linq;
using AmongUs.GameOptions;
using BepInEx.Unity.IL2CPP.Utils.Collections;
using HarmonyLib;
using Il2CppInterop.Runtime.Attributes;
using MiraAPI.GameOptions;
using MiraAPI.Modifiers;
using MiraAPI.Presets;
@@ -35,6 +35,13 @@ internal static class GameOptionsMenuPatch
HudManager.Instance.PlayerCam.OverrideScreenShakeEnabled = true;
}
[HarmonyPostfix]
[HarmonyPatch(nameof(GameOptionsMenu.CloseMenu))]
public static void FullMenuClosePatch(GameOptionsMenu __instance)
{
Utilities.Extensions.ClearGarbageCollector();
}
[HarmonyPostfix]
[HarmonyPatch(nameof(GameOptionsMenu.Update))]
// ReSharper disable once InconsistentNaming
@@ -63,7 +70,7 @@ internal static class GameOptionsMenuPatch
var filteredGroups =
GameSettingMenuPatches.SelectedMod?.InternalOptionGroups
.Where(x => x.OptionableType == null &&
x.ParentMenu == MenuCategory.Roles) ?? [];
x.ParentMenu == MenuCategory.Game) ?? [];
foreach (var group in filteredGroups)
{
@@ -74,9 +81,9 @@ internal static class GameOptionsMenuPatch
__instance.scrollBar.SetYBoundsMax(-num - 1.65f);
}
private static void UpdateGroup(AbstractOptionGroup group, ref float num)
private static void UpdateGroup(AbstractOptionGroup? group, ref float num)
{
if (group.Options.Count == 0 || group.Header is null)
if (group is null || group.Options.Count == 0 || group.Header is null || group.CreationCoroutine is not null)
{
return;
}
@@ -102,7 +109,7 @@ internal static class GameOptionsMenuPatch
{
var newOpt = opt.OptionBehaviour;
if (newOpt is null)
if (!newOpt || newOpt == null)
{
continue;
}
@@ -171,7 +178,8 @@ internal static class GameOptionsMenuPatch
private static void ModifiersUpdate(ref float num)
{
var groups = GameSettingMenuPatches.SelectedMod?.InternalOptionGroups
.Where(x => x.ParentMenu is MenuCategory.Modifiers || x.OptionableType?.IsAssignableTo(typeof(BaseModifier)) == true) ?? [];
.Where(x => x.ParentMenu is MenuCategory.Modifiers ||
x.OptionableType?.IsAssignableTo(typeof(BaseModifier)) == true) ?? [];
foreach (var modGroup in groups)
{
@@ -182,7 +190,8 @@ internal static class GameOptionsMenuPatch
private static void ModifiersCreate(GameOptionsMenu menu)
{
var groups = GameSettingMenuPatches.SelectedMod?.InternalOptionGroups
.Where(x => x.ParentMenu is MenuCategory.Modifiers || x.OptionableType?.IsAssignableTo(typeof(BaseModifier)) == true) ?? [];
.Where(x => x.ParentMenu is MenuCategory.Modifiers ||
x.OptionableType?.IsAssignableTo(typeof(BaseModifier)) == true) ?? [];
foreach (var group in groups)
{
CreateGroup(menu, group);
@@ -201,24 +210,21 @@ internal static class GameOptionsMenuPatch
__instance.MapPicker.gameObject.SetActive(false);
if (__instance.name == "MODIFIERS TAB")
switch (__instance.name)
{
ModifiersCreate(__instance);
return false;
}
else if (__instance.name == "CUSTOM TAB 1")
{
CustomMenuOneCreate(__instance);
return false;
}
else if (__instance.name == "CUSTOM TAB 2")
{
CustomMenuTwoCreate(__instance);
return false;
case "MODIFIERS TAB":
ModifiersCreate(__instance);
return false;
case "CUSTOM TAB 1":
CustomMenuOneCreate(__instance);
return false;
case "CUSTOM TAB 2":
CustomMenuTwoCreate(__instance);
return false;
}
var filteredGroups = GameSettingMenuPatches.SelectedMod?.InternalOptionGroups
.Where(x => x.OptionableType == null && x.ParentMenu == MenuCategory.Roles) ?? [];
.Where(x => x.OptionableType == null && x.ParentMenu == MenuCategory.Game) ?? [];
foreach (var group in filteredGroups)
{
@@ -264,7 +270,7 @@ internal static class GameOptionsMenuPatch
return false;
}
private static void CreateGroup(GameOptionsMenu menu, AbstractOptionGroup group)
private static IEnumerator CoCreateGroup(GameOptionsMenu menu, AbstractOptionGroup group)
{
var categoryHeaderMasked = Object.Instantiate(
menu.categoryHeaderOrigin,
@@ -311,7 +317,7 @@ internal static class GameOptionsMenuPatch
defaultPreset = preset;
}
foreach (var newOpt in options)
yield return options.CoLoopWithBudget(newOpt =>
{
newOpt.SetClickMask(menu.ButtonClickMask);
@@ -414,6 +420,7 @@ internal static class GameOptionsMenuPatch
defaultPreset!.ResetOption(strOpt);
}));
}
if (!defaultPreset!.IsOptionInPreset(newOpt))
{
resetBtn.Destroy();
@@ -421,7 +428,7 @@ internal static class GameOptionsMenuPatch
newOpt.Initialize();
newOpt.gameObject.SetActive(false);
}
}).WrapToIl2Cpp();
var boxCol = categoryHeaderMasked.gameObject.AddComponent<BoxCollider2D>();
boxCol.size = new Vector2(7, 0.7f);
@@ -440,5 +447,17 @@ internal static class GameOptionsMenuPatch
: "<size=70%>(Click to close)</size>";
}));
headerBtn.SetButtonEnableState(true);
group.CreationCoroutine = null;
}
private static void CreateGroup(GameOptionsMenu menu, AbstractOptionGroup group)
{
if (group.CreationCoroutine != null)
{
GameSettingMenu.Instance.StopCoroutine(group.CreationCoroutine);
}
group.CreationCoroutine = GameSettingMenu.Instance.StartCoroutine(CoCreateGroup(menu, group).WrapToIl2Cpp());
}
}
@@ -8,7 +8,6 @@ using MiraAPI.Presets;
using MiraAPI.Roles;
using MiraAPI.Utilities;
using MiraAPI.Utilities.Assets;
using Reactor.Utilities;
using Reactor.Utilities.Extensions;
using TMPro;
using UnityEngine;
@@ -262,7 +261,7 @@ internal static class GamePresetsTabPatches
iconSpriteRend.sprite = MiraAssets.RefreshIcon.LoadAsset();
Helpers.DivideSize(refreshButton.gameObject, 2f);
refreshButton.buttonText.gameObject.DeepDestroy();
refreshButton.buttonText.gameObject.Destroy();
refreshButton.OnClick = new Button.ButtonClickedEvent();
refreshButton.OnClick.AddListener((UnityAction)Refresh);
@@ -199,7 +199,7 @@ internal static class GameSettingMenuPatches
{
SaveScrollPositions(__instance);
SelectedModIdx += 1;
if (SelectedModIdx > MiraPluginManager.Instance.RegisteredPlugins.Length)
if (SelectedModIdx > MiraPluginManager.Instance.RegisteredOptionablePlugins.Length)
{
SelectedModIdx = 0;
}
@@ -220,7 +220,7 @@ internal static class GameSettingMenuPatches
SelectedModIdx -= 1;
if (SelectedModIdx < 0)
{
SelectedModIdx = MiraPluginManager.Instance.RegisteredPlugins.Length;
SelectedModIdx = MiraPluginManager.Instance.RegisteredOptionablePlugins.Length;
}
UpdateText(__instance, __instance.GameSettingsTab, __instance.RoleSettingsTab);
@@ -399,17 +399,17 @@ internal static class GameSettingMenuPatches
{
if (_text is not null && SelectedModIdx == 0)
{
_text.text = $"<size=40%>(Page 0/{MiraPluginManager.Instance.RegisteredPlugins.Length})</size>\nDefault";
_text.text = $"<size=40%>(Page 0/{MiraPluginManager.Instance.RegisteredOptionablePlugins.Length})</size>\nMain";
_text.fontSizeMax = 3.2f;
SelectedMod = null;
}
else if (_text is not null)
{
_text.fontSizeMax = 2.3f;
SelectedMod = MiraPluginManager.Instance.RegisteredPlugins[SelectedModIdx - 1];
SelectedMod = MiraPluginManager.Instance.RegisteredOptionablePlugins[SelectedModIdx - 1];
var name = SelectedMod.MiraPlugin.OptionsTitleText;
_text.text = $"<size=50%>(Page {SelectedModIdx}/{MiraPluginManager.Instance.RegisteredPlugins.Length})</size>\n" + name[..Math.Min(name.Length, 25)];
_text.text = $"<size=50%>(Page {SelectedModIdx}/{MiraPluginManager.Instance.RegisteredOptionablePlugins.Length})</size>\n" + name[..Math.Min(name.Length, 25)];
}
bool replaceWithModifiers = true;
@@ -419,6 +419,8 @@ internal static class GameSettingMenuPatches
_customTwoButton!.transform.localPosition = _customTwoBtnOgPos;
menu.RoleSettingsButton.transform.localPosition = _roleBtnOgPos;
CleanupTab(settings, roles);
if (SelectedModIdx != 0)
{
_customOneButton.buttonText.text = SelectedMod!.MiraPlugin.CustomOptionMenuNameOne;
@@ -432,7 +434,7 @@ internal static class GameSettingMenuPatches
x => x.ParentMenu == MenuCategory.Modifiers || x.OptionableType?.IsAssignableTo(typeof(BaseModifier)) == true);
var modHasOptions =
SelectedMod.InternalOptionGroups.Exists(x => x.OptionableType == null &&
x.ParentMenu != MenuCategory.Modifiers && x.ParentMenu != MenuCategory.Roles);
x.ParentMenu == MenuCategory.Game);
_modifiersButton.gameObject.SetActive(true);
_smallRolesButton.gameObject.SetActive(true);
@@ -560,8 +562,6 @@ internal static class GameSettingMenuPatches
{
menu.ChangeTab(0, false);
}
CleanupTab(settings, roles);
}
private static void ClearOptions(Il2CppSystem.Collections.Generic.List<OptionBehaviour> options)
@@ -606,6 +606,8 @@ internal static class GameSettingMenuPatches
CleanupSettings(_customTwoTab, MenuCategory.CustomTwo);
}
Utilities.Extensions.ClearGarbageCollector();
void CleanupRoleSettings(RolesSettingsMenu rolesMenu)
{
if (rolesMenu.advancedSettingChildren != null)
@@ -25,7 +25,7 @@ public static class LobbyViewPanePatches
private static MiraPluginInfo? SelectedMod => SelectedModIdx == 0
? null
: MiraPluginManager.Instance.RegisteredPlugins[SelectedModIdx - 1];
: MiraPluginManager.Instance.RegisteredOptionablePlugins[SelectedModIdx - 1];
private static PassiveButton? ModifiersTabButton { get; set; }
@@ -75,7 +75,7 @@ public static class LobbyViewPanePatches
(UnityAction)(() =>
{
SelectedModIdx += 1;
if (SelectedModIdx > MiraPluginManager.Instance.RegisteredPlugins.Length)
if (SelectedModIdx > MiraPluginManager.Instance.RegisteredOptionablePlugins.Length)
{
SelectedModIdx = 0;
}
@@ -99,7 +99,7 @@ public static class LobbyViewPanePatches
SelectedModIdx -= 1;
if (SelectedModIdx < 0)
{
SelectedModIdx = MiraPluginManager.Instance.RegisteredPlugins.Length;
SelectedModIdx = MiraPluginManager.Instance.RegisteredOptionablePlugins.Length;
}
Refresh(__instance);
@@ -109,7 +109,7 @@ public static class LobbyViewPanePatches
private static void Refresh(LobbyViewSettingsPane menu)
{
ModifiersTabButton?.gameObject.SetActive(SelectedModIdx != 0);
menu.gameModeText.text = SelectedMod?.PluginInfo.Metadata.Name ?? "Default";
menu.gameModeText.text = SelectedMod?.PluginInfo.Metadata.Name ?? "Main";
menu.RefreshTab();
menu.scrollBar.ScrollToTop();
}
@@ -1,8 +1,6 @@
using System.Linq;
using HarmonyLib;
using Il2CppSystem;
using MiraAPI.Roles;
using Object = Il2CppSystem.Object;
namespace MiraAPI.Patches.Options;
@@ -26,12 +24,14 @@ public static class NotificationPopperPatch
var textColor = customRole.OptionsMenuColor.ToTextColor();
var icon = customRole.Configuration.IconTmp ? $"<sprite name=\"{customRole.Configuration.IconTmp.name}\">" : string.Empty;
var item = TranslationController.Instance.GetString(
StringNames.LobbyChangeSettingNotificationRole,
string.Concat(
icon,
"<font=\"Barlow-Black SDF\" material=\"Barlow-Black Outline\">",
textColor,
TranslationController.Instance.GetString(key, Array.Empty<Object>()),
TranslationController.Instance.GetString(key),
"</color></font>"
),
"<font=\"Barlow-Black SDF\" material=\"Barlow-Black Outline\">" + roleCount + "</font>",
+1 -4
View File
@@ -1,9 +1,6 @@
using System.Collections.Generic;
using System.Linq;
using HarmonyLib;
using HarmonyLib;
using Il2CppSystem;
using MiraAPI.GameOptions;
using MiraAPI.GameOptions.OptionTypes;
using MiraAPI.Roles;
using MiraAPI.Utilities;
using UnityEngine;
@@ -1,12 +1,8 @@
using System;
using System.Linq;
using System.Linq;
using HarmonyLib;
using MiraAPI.GameOptions;
using MiraAPI.GameOptions.OptionTypes;
using MiraAPI.Utilities;
using Reactor.Utilities;
using UnityEngine;
using Object = Il2CppSystem.Object;
namespace MiraAPI.Patches.Options;
+104 -76
View File
@@ -1,9 +1,10 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using AmongUs.GameOptions;
using BepInEx.Unity.IL2CPP.Utils.Collections;
using HarmonyLib;
using Il2CppInterop.Runtime.InteropTypes.Arrays;
using MiraAPI.GameOptions;
using MiraAPI.Networking;
using MiraAPI.Roles;
@@ -11,7 +12,6 @@ using MiraAPI.Utilities;
using MiraAPI.Utilities.Assets;
using Reactor.Localization.Utilities;
using Reactor.Networking.Rpc;
using Reactor.Utilities;
using Reactor.Utilities.Extensions;
using TMPro;
using UnityEngine;
@@ -49,9 +49,7 @@ public static class RoleSettingMenuPatches
__instance.scrollBar.SetScrollBounds(__instance);
}
[HarmonyPrefix]
[HarmonyPatch(nameof(RolesSettingsMenu.SetQuotaTab))]
public static bool SetQuotaTabPatch(RolesSettingsMenu __instance)
private static IEnumerator CoQuotaTabPatch(RolesSettingsMenu roleMenu)
{
foreach (var obj in Headers)
{
@@ -59,8 +57,10 @@ public static class RoleSettingMenuPatches
{
continue;
}
obj.DeepDestroy(false);
obj.Destroy();
}
Headers.Clear();
foreach (var obj in RoleOptionSettings)
{
@@ -68,25 +68,26 @@ public static class RoleSettingMenuPatches
{
continue;
}
obj.gameObject.DeepDestroy(false);
obj.gameObject.Destroy();
}
RoleOptionSettings.Clear();
CurrentRole = null;
CurrentRoleOptions = null;
__instance.roleChances = new Il2CppSystem.Collections.Generic.List<RoleOptionSetting>();
__instance.advancedSettingChildren = new Il2CppSystem.Collections.Generic.List<OptionBehaviour>();
Utilities.Extensions.ClearGarbageCollector();
roleMenu.roleChances = new Il2CppSystem.Collections.Generic.List<RoleOptionSetting>();
roleMenu.advancedSettingChildren = new Il2CppSystem.Collections.Generic.List<OptionBehaviour>();
var maskBg = __instance.scrollBar.transform.FindChild("MaskBg");
var hitbox = __instance.scrollBar.transform.FindChild("Hitbox");
var dividerImage = __instance.transform.FindChild("HeaderButtons/DividerImage");
var maskBg = roleMenu.scrollBar.transform.FindChild("MaskBg");
var hitbox = roleMenu.scrollBar.transform.FindChild("Hitbox");
var dividerImage = roleMenu.transform.FindChild("HeaderButtons/DividerImage");
if (GameSettingMenuPatches.SelectedModIdx == 0)
{
__instance.AllButton.transform.parent.gameObject.SetActive(true);
__instance.AllButton.gameObject.SetActive(true);
__instance.scrollBar.transform.localPosition = new Vector3(-1.4957f, 0.657f, -4);
roleMenu.AllButton.transform.parent.gameObject.SetActive(true);
roleMenu.AllButton.gameObject.SetActive(true);
roleMenu.scrollBar.transform.localPosition = new Vector3(-1.4957f, 0.657f, -4);
maskBg.localPosition = new Vector3(1.5353f, -.5734f, -.1f);
maskBg.localScale = new Vector3(6.6811f, 3.3563f, 0.5598f);
hitbox.localPosition = new Vector3(0.3297f, -.2333f, 4f);
@@ -95,67 +96,70 @@ public static class RoleSettingMenuPatches
var num = 0.662f;
var list = CustomRoleManager.AllRoles.Where(
r => !r.IsCustomRole() && !r.IsRoleBlacklisted() && r.TeamType == RoleTeamTypes.Crewmate && r.Role != RoleTypes.Crewmate &&
r.Role != RoleTypes.CrewmateGhost).ToList();
var list2 = CustomRoleManager.AllRoles.Where(
r => !r.IsCustomRole() && !r.IsRoleBlacklisted() && r.TeamType == RoleTeamTypes.Impostor && r.Role != RoleTypes.Impostor &&
r.Role != RoleTypes.ImpostorGhost).ToList();
var list = CustomRoleManager.AllRoles.Where(r =>
!r.IsCustomRole() && !r.IsRoleBlacklisted() && r.TeamType == RoleTeamTypes.Crewmate &&
r.Role != RoleTypes.Crewmate &&
r.Role != RoleTypes.CrewmateGhost).ToList();
var list2 = CustomRoleManager.AllRoles.Where(r =>
!r.IsCustomRole() && !r.IsRoleBlacklisted() && r.TeamType == RoleTeamTypes.Impostor &&
r.Role != RoleTypes.Impostor &&
r.Role != RoleTypes.ImpostorGhost).ToList();
if (__instance.roleTabs == null || __instance.roleTabs.Count == 0)
if (roleMenu.roleTabs == null || roleMenu.roleTabs.Count == 0)
{
var num2 = -1.928f;
__instance.roleTabs = new();
__instance.roleTabs.Add(__instance.AllButton);
roleMenu.roleTabs = new();
roleMenu.roleTabs.Add(roleMenu.AllButton);
foreach (var t in list)
{
__instance.AddRoleTab(t, ref num2);
roleMenu.AddRoleTab(t, ref num2);
}
foreach (var t in list2)
{
__instance.AddRoleTab(t, ref num2);
roleMenu.AddRoleTab(t, ref num2);
}
}
var categoryHeaderEditRole = Object.Instantiate(
__instance.categoryHeaderEditRoleOrigin,
roleMenu.categoryHeaderEditRoleOrigin,
Vector3.zero,
Quaternion.identity,
__instance.RoleChancesSettings.transform);
roleMenu.RoleChancesSettings.transform);
categoryHeaderEditRole.SetHeader(StringNames.CrewmateRolesHeader, 20);
categoryHeaderEditRole.transform.localPosition = new Vector3(4.986f, num, -2f);
num -= 0.522f;
var num3 = 0;
foreach (var t in list)
{
__instance.CreateQuotaOption(t, ref num, num3);
roleMenu.CreateQuotaOption(t, ref num, num3);
num3++;
}
num -= 0.22f;
var categoryHeaderEditRole2 = Object.Instantiate(
__instance.categoryHeaderEditRoleOrigin,
roleMenu.categoryHeaderEditRoleOrigin,
Vector3.zero,
Quaternion.identity,
__instance.RoleChancesSettings.transform);
roleMenu.RoleChancesSettings.transform);
categoryHeaderEditRole2.SetHeader(StringNames.ImpostorRolesHeader, 20);
categoryHeaderEditRole2.transform.localPosition = new Vector3(4.986f, num, -2f);
num -= 0.522f;
foreach (var t in list2)
{
__instance.CreateQuotaOption(t, ref num, num3);
roleMenu.CreateQuotaOption(t, ref num, num3);
num3++;
}
return false;
Info($"Created {num3} role options for the default game.");
yield break;
}
ScrollerNum = 0.522f;
__instance.AllButton.transform.parent.gameObject.SetActive(false);
__instance.AllButton.gameObject.SetActive(false);
__instance.scrollBar.transform.localPosition = new Vector3(-1.4957f, 1.5261f, -4);
roleMenu.AllButton.transform.parent.gameObject.SetActive(false);
roleMenu.AllButton.gameObject.SetActive(false);
roleMenu.scrollBar.transform.localPosition = new Vector3(-1.4957f, 1.5261f, -4);
maskBg.localPosition = new Vector3(1.5353f, -1.0607f, -.1f);
maskBg.localScale = new Vector3(6.6811f, 4.1563f, 0.5598f);
hitbox.localPosition = new Vector3(0.3297f, -.6333f, 4f);
@@ -169,7 +173,8 @@ public static class RoleSettingMenuPatches
if (roleGroups is null)
{
return false;
Error("No role groups found for the selected mod.");
yield break;
}
// sort the groups by priority
@@ -177,13 +182,14 @@ public static class RoleSettingMenuPatches
.OrderBy(x => x.Key.Priority)
.ThenBy(x => x.Key.Name);
var quotaThing = __instance.categoryHeaderEditRoleOrigin.transform.FindChild("QuotaHeader");
var quotaThing = roleMenu.categoryHeaderEditRoleOrigin.transform.FindChild("QuotaHeader");
var usingNewQuota = false;
var template = __instance.transform.parent.parent.GetComponent<GameSettingMenu>().GameSettingsTab.categoryHeaderOrigin;
var template = roleMenu.transform.parent.parent.GetComponent<GameSettingMenu>().GameSettingsTab
.categoryHeaderOrigin;
foreach (var grouping in sortedRoleGroups)
{
if (!grouping.Any() || grouping.All(x=> x.Configuration.HideSettings || !x.VisibleInSettings()))
if (!grouping.Any() || grouping.All(x => x.Configuration.HideSettings || !x.VisibleInSettings()))
{
continue;
}
@@ -203,7 +209,7 @@ public static class RoleSettingMenuPatches
template,
Vector3.zero,
Quaternion.identity,
__instance.RoleChancesSettings.transform);
roleMenu.RoleChancesSettings.transform);
categoryHeaderMasked.SetHeader(name, 20);
@@ -222,9 +228,9 @@ public static class RoleSettingMenuPatches
var blankLabel = quotaInst.transform.FindChild("BlankLabel").gameObject;
var chanceLabel = quotaInst.transform.FindChild("Chance Label").gameObject;
var countLabel = quotaInst.transform.FindChild("# Label").gameObject;
blankLabel.DeepDestroy(false);
chanceLabel.DeepDestroy(false);
countLabel.DeepDestroy(false);
blankLabel.Destroy();
chanceLabel.Destroy();
countLabel.Destroy();
usingNewQuota = true;
quotaThing = quotaInst;
}
@@ -246,19 +252,23 @@ public static class RoleSettingMenuPatches
categoryHeaderMasked.Background.color = Palette.ImpostorRoleHeaderRed;
break;
default:
categoryHeaderMasked.Title.color = group.Color.Equals(MiraApiPlugin.DefaultHeaderColor) ? Color.white : group.Color.FindAlternateColor();
categoryHeaderMasked.Title.color = group.Color.Equals(MiraApiPlugin.DefaultHeaderColor)
? Color.white
: group.Color.FindAlternateColor();
categoryHeaderMasked.Divider.color = group.Color;
categoryHeaderMasked.Background.color = group.Color;
break;
}
categoryHeaderMasked.Title.fontStyle = __instance.categoryHeaderEditRoleOrigin.Title.fontStyle;
categoryHeaderMasked.Title.font = __instance.categoryHeaderEditRoleOrigin.Title.font;
categoryHeaderMasked.Title.fontMaterial = __instance.categoryHeaderEditRoleOrigin.Title.fontMaterial;
categoryHeaderMasked.Title.fontStyle = roleMenu.categoryHeaderEditRoleOrigin.Title.fontStyle;
categoryHeaderMasked.Title.font = roleMenu.categoryHeaderEditRoleOrigin.Title.font;
categoryHeaderMasked.Title.fontMaterial = roleMenu.categoryHeaderEditRoleOrigin.Title.fontMaterial;
categoryHeaderMasked.Divider.color = categoryHeaderMasked.Background.color;
categoryHeaderMasked.Background.transform.localPosition = new Vector3(0.55f, -0.1833f, 0);
categoryHeaderMasked.Background.size = new Vector2(categoryHeaderMasked.Background.size.x + 1.5f, categoryHeaderMasked.Background.size.y);
categoryHeaderMasked.Background.size = new Vector2(
categoryHeaderMasked.Background.size.x + 1.5f,
categoryHeaderMasked.Background.size.y);
categoryHeaderMasked.transform.localScale = Vector3.one * 0.63f;
categoryHeaderMasked.transform.localPosition = new Vector3(-0.44f, ScrollerNum, -2f);
@@ -278,20 +288,21 @@ public static class RoleSettingMenuPatches
if (!RoleGroupHidden[group])
{
foreach (var role in grouping)
{
if (role is not RoleBehaviour roleBehaviour)
yield return
grouping.CoLoopWithBudget(role =>
{
continue;
}
if (role is not RoleBehaviour roleBehaviour)
{
return;
}
var option = CreateQuotaOption(__instance, roleBehaviour, num4);
if (option is not null)
{
RoleOptionSettings.Add(option);
num4++;
}
}
var option = CreateQuotaOption(roleMenu, roleBehaviour, num4);
if (option is not null)
{
RoleOptionSettings.Add(option);
num4++;
}
});
}
var boxCol = categoryHeaderMasked.gameObject.AddComponent<BoxCollider2D>();
@@ -299,25 +310,28 @@ public static class RoleSettingMenuPatches
boxCol.offset = new Vector2(1.5f, -0.3f);
var headerBtn = categoryHeaderMasked.gameObject.AddComponent<PassiveButton>();
headerBtn.ClickSound = __instance.BackButton.GetComponent<PassiveButton>().ClickSound;
headerBtn.ClickSound = roleMenu.BackButton.GetComponent<PassiveButton>().ClickSound;
headerBtn.OnMouseOver = new UnityEvent();
headerBtn.OnMouseOut = new UnityEvent();
headerBtn.OnClick.AddListener(
(UnityAction)(() =>
{
RolePositions[GameSettingMenuPatches.SelectedModIdx] = __instance.scrollBar.Inner.localPosition;
RolePositions[GameSettingMenuPatches.SelectedModIdx] = roleMenu.scrollBar.Inner.localPosition;
if (RoleGroupHidden.TryGetValue(group, out var groupHidden))
{
RoleGroupHidden[group] = !groupHidden;
}
foreach (var obj in Headers)
{
if (!obj)
{
continue;
}
obj.DeepDestroy(false);
obj.Destroy();
}
Headers.Clear();
foreach (var obj in RoleOptionSettings)
{
@@ -325,11 +339,12 @@ public static class RoleSettingMenuPatches
{
continue;
}
obj.gameObject.DeepDestroy(false);
obj.gameObject.Destroy();
}
RoleOptionSettings.Clear();
Utilities.Extensions.ClearGarbageCollector();
__instance.SetQuotaTab();
roleMenu.SetQuotaTab();
}));
headerBtn.SetButtonEnableState(true);
@@ -339,7 +354,22 @@ public static class RoleSettingMenuPatches
}
}
__instance.scrollBar.SetScrollBounds(__instance);
roleMenu.scrollBar.SetScrollBounds(roleMenu);
_quotaTabCoroutine = null;
}
private static Coroutine? _quotaTabCoroutine;
[HarmonyPrefix]
[HarmonyPatch(nameof(RolesSettingsMenu.SetQuotaTab))]
public static bool SetQuotaTabPatch(RolesSettingsMenu __instance)
{
if (_quotaTabCoroutine != null)
{
GameSettingMenu.Instance.StopCoroutine(_quotaTabCoroutine);
}
_quotaTabCoroutine = GameSettingMenu.Instance.StartCoroutine(CoQuotaTabPatch(__instance).WrapToIl2Cpp());
return false;
}
@@ -364,6 +394,7 @@ public static class RoleSettingMenuPatches
}
[HarmonyPrefix]
// TODO: turn this into a fixed update
[HarmonyPatch(nameof(RolesSettingsMenu.Update))]
public static bool UpdatePatch(RolesSettingsMenu __instance)
{
@@ -437,8 +468,7 @@ public static class RoleSettingMenuPatches
roleSetting.Role.StringName,
roleSetting.RoleMaxCount,
roleSetting.RoleChance,
roleSetting.Role.TeamType,
false);
roleSetting.Role.TeamType);
if (AmongUsClient.Instance.AmHost)
{
@@ -452,12 +482,11 @@ public static class RoleSettingMenuPatches
{
foreach (var optBehaviour in __instance.AdvancedRolesSettings.GetComponentsInChildren<OptionBehaviour>())
{
optBehaviour.gameObject.DeepDestroy(false);
optBehaviour.gameObject.Destroy();
}
CurrentRole = role;
__instance.advancedSettingChildren.Clear();
Utilities.Extensions.ClearGarbageCollector();
// TODO: create sub groups under the role settings.
var filteredOptions = GameSettingMenuPatches.SelectedMod?.InternalOptionGroups
@@ -465,8 +494,6 @@ public static class RoleSettingMenuPatches
.SelectMany(x => x.Options)
.ToList() ?? [];
CurrentRoleOptions = filteredOptions;
foreach (var option in filteredOptions)
{
var newOpt = option.CreateOption(
@@ -497,6 +524,7 @@ public static class RoleSettingMenuPatches
newOpt.Initialize();
}
CurrentRoleOptions = filteredOptions;
__instance.scrollBar.ScrollToTop();
}
@@ -649,7 +677,7 @@ public static class RoleSettingMenuPatches
var newButton = Object.Instantiate(roleOptionSetting.buttons[0], roleOptionSetting.transform);
newButton.name = "ConfigButton";
newButton.transform.localPosition = new Vector3(0.4473f, -0.3f, -2f);
newButton.transform.FindChild("Text_TMP").gameObject.DeepDestroy();
newButton.transform.FindChild("Text_TMP").gameObject.Destroy();
newButton.activeSprites.Destroy();
var btnRend = newButton.transform.FindChild("ButtonSprite").GetComponent<SpriteRenderer>();
-1
View File
@@ -8,7 +8,6 @@ using MiraAPI.Hud;
using MiraAPI.Modifiers;
using MiraAPI.Utilities;
using MiraAPI.Voting;
using Reactor.Utilities;
using Reactor.Utilities.Extensions;
namespace MiraAPI.Patches;
+1 -2
View File
@@ -1,5 +1,4 @@
using System.Collections.Generic;
using System.Linq;
using System.Linq;
using AmongUs.GameOptions;
using HarmonyLib;
using MiraAPI.Roles;
+1 -3
View File
@@ -1,9 +1,7 @@
using HarmonyLib;
using InnerNet;
using MiraAPI.Roles;
using MiraAPI.Utilities;
using Reactor.Utilities.Extensions;
using UnityEngine;
namespace MiraAPI.Patches.Roles;
@@ -73,7 +71,7 @@ public static class HudManagerPatches
}
else if (RoleTab != null)
{
RoleTab.gameObject.DeepDestroy();
RoleTab.gameObject.Destroy();
RoleTab = null;
}
}
@@ -1,7 +1,6 @@
using System.Linq;
using AmongUs.GameOptions;
using HarmonyLib;
using InnerNet;
using MiraAPI.Events;
using MiraAPI.Events.Vanilla.Gameplay;
using MiraAPI.Modifiers;
@@ -2,7 +2,6 @@
using HarmonyLib;
using Il2CppSystem.Collections.Generic;
using MiraAPI.Roles;
using Reactor.Utilities;
namespace MiraAPI.Patches.Roles;
-1
View File
@@ -1,6 +1,5 @@
using System.Linq;
using HarmonyLib;
using Reactor.Utilities;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.SceneManagement;
+27
View File
@@ -0,0 +1,27 @@
using HarmonyLib;
using MiraAPI.Utilities.Assets;
using TMPro;
namespace MiraAPI.Patches;
[HarmonyPatch]
public static class TmpAwakePatch
{
[HarmonyPatch(typeof(TextMeshPro), nameof(TextMeshPro.Awake))]
[HarmonyPostfix]
public static void TmpAwakePostfix(TextMeshPro __instance)
{
if (!TmpSpriteUtils.AssetHolder || __instance.m_spriteAsset == TmpSpriteUtils.AssetHolder)
{
return;
}
if (!__instance.m_spriteAsset)
{
__instance.m_spriteAsset = TmpSpriteUtils.AssetHolder;
__instance.UpdateMeshPadding();
return;
}
__instance.m_spriteAsset.fallbackSpriteAssets.Add(TmpSpriteUtils.AssetHolder);
__instance.UpdateMeshPadding();
}
}
@@ -7,7 +7,6 @@ using MiraAPI.Events;
using MiraAPI.Events.Vanilla.Meeting.Voting;
using MiraAPI.Utilities;
using MiraAPI.Voting;
using Reactor.Utilities;
using Reactor.Utilities.Extensions;
using UnityEngine;
@@ -208,13 +208,6 @@ internal static class MeetingHudPatches
public static bool PopulateResultsPatch(MeetingHud __instance, ref Il2CppStructArray<MeetingHud.VoterState> states)
{
var votes = states.Select(x=> new CustomVote(x.VoterId, x.VotedForId)).ToList();
var @event = new PopulateResultsEvent(votes);
MiraEventManager.InvokeEvent(@event);
if (@event.IsCancelled)
{
return false;
}
VotingUtils.HandlePopulateResults(votes);
return false;
+16 -1
View File
@@ -1,4 +1,5 @@
using BepInEx.Configuration;
using System.Linq;
using BepInEx.Configuration;
namespace MiraAPI.PluginLoading;
@@ -7,11 +8,25 @@ namespace MiraAPI.PluginLoading;
/// </summary>
public interface IMiraPlugin
{
/// <summary>
/// Gets or sets a value indicating whether to display the plugin in the options menu.
/// </summary>
public virtual bool DisplayOnOptionsMenu => true;
/// <summary>
/// Gets the name to display on the options menu.
/// </summary>
string OptionsTitleText { get; }
/// <summary>
/// Gets the abbreviated name to display for other mods to pick up.
/// </summary>
/// <returns>The <see cref="string"/> text for the plugin.</returns>
public virtual string GetAbbreviatedModName()
{
return new(OptionsTitleText.Where(c => !char.IsLower(c) && !char.IsWhiteSpace(c)).ToArray());
}
/// <summary>
/// Gets the name for the first custom category in the game options menu, if any.
/// </summary>
-1
View File
@@ -5,7 +5,6 @@ using BepInEx.Configuration;
using MiraAPI.GameModes;
using MiraAPI.GameOptions;
using MiraAPI.Hud;
using MiraAPI.LocalSettings;
using MiraAPI.Modifiers;
using MiraAPI.Presets;
@@ -34,6 +34,10 @@ public sealed class MiraPluginManager
internal MiraPluginInfo[] RegisteredPlugins { get; private set; } = null!;
private readonly Dictionary<Assembly, MiraPluginInfo> _registeredOptionablePlugins = [];
internal MiraPluginInfo[] RegisteredOptionablePlugins { get; private set; } = null!;
internal Dictionary<MiraPluginInfo, List<Type>> QueuedRoleRegistrations { get; } = [];
internal static MiraPluginManager Instance { get; private set; } = new();
@@ -127,6 +131,10 @@ public sealed class MiraPluginManager
QueuedRoleRegistrations.Add(info, roles);
_registeredPlugins.Add(assembly, info);
if (miraPlugin.DisplayOnOptionsMenu)
{
_registeredOptionablePlugins.Add(assembly, info);
}
info.SavePublicCollections();
PresetManager.CreateDefaultPreset(info);
@@ -141,6 +149,7 @@ public sealed class MiraPluginManager
// Cache all the registered plugins into an array for easy access
RegisteredPlugins = [.. _registeredPlugins.Values];
RegisteredOptionablePlugins = [.. _registeredOptionablePlugins.Values];
ModifierManager.Modifiers = new ReadOnlyCollection<BaseModifier>(ModifierManager.InternalModifiers);
};
+2 -3
View File
@@ -4,8 +4,7 @@ using System.Linq;
using BepInEx.Configuration;
using MiraAPI.PluginLoading;
using MiraAPI.Roles;
using MiraAPI.Utilities;
using Reactor.Utilities;
using Reactor.Utilities.Extensions;
using UnityEngine;
namespace MiraAPI.Presets;
@@ -62,7 +61,7 @@ public static class PresetManager
{
if (btn != null)
{
btn.DeepDestroy();
btn.Destroy();
}
}
+1 -1
View File
@@ -26,7 +26,7 @@ public class SavePresetPopup(nint cppPtr) : Minigame(cppPtr)
// Cleanup holder object
public void OnDestroy()
{
transform.parent.gameObject.DeepDestroy();
transform.parent.gameObject.Destroy();
}
public override void Close()
Binary file not shown.

After

Width:  |  Height:  |  Size: 96 B

+7
View File
@@ -3,6 +3,7 @@ using System;
using Il2CppInterop.Runtime.Attributes;
using MiraAPI.Patches.Freeplay;
using MiraAPI.Utilities.Assets;
using TMPro;
using UnityEngine;
namespace MiraAPI.Roles;
@@ -87,6 +88,12 @@ public record struct CustomRoleConfiguration
[HideFromIl2Cpp]
public LoadableAsset<Sprite>? Icon { get; set; } = null;
/// <summary>
/// Gets or sets the <see cref="TMP_SpriteAsset"/> for the Role Icon.
/// </summary>
[HideFromIl2Cpp]
public TMP_SpriteAsset IconTmp { get; set; }
/// <summary>
/// Gets or sets the Intro sound for the Role.
/// </summary>
-1
View File
@@ -11,7 +11,6 @@ using MiraAPI.Utilities;
using MiraAPI.Utilities.Assets;
using Reactor.Localization.Utilities;
using Reactor.Networking.Rpc;
using Reactor.Utilities;
using Reactor.Utilities.Extensions;
using TMPro;
using UnityEngine;
-1
View File
@@ -4,7 +4,6 @@ using BepInEx.Configuration;
using MiraAPI.GameOptions;
using MiraAPI.Modifiers;
using MiraAPI.PluginLoading;
using Reactor.Utilities;
using UnityEngine;
namespace MiraAPI.Roles;
@@ -1,5 +1,4 @@
using System;
using Reactor.Utilities;
using UnityEngine.AddressableAssets;
namespace MiraAPI.Utilities.Assets;
@@ -2,7 +2,6 @@
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using Reactor.Utilities;
using UnityEngine.AddressableAssets;
namespace MiraAPI.Utilities.Assets;
+2
View File
@@ -134,4 +134,6 @@ public static class MiraAssets
/// Gets the sprite used for timed modifier file in TaskAdderGame.
/// </summary>
public static LoadableResourceAsset TimedModifierFile { get; } = new("MiraAPI.Resources.TimedModifierFile.png");
internal static LoadableResourceAsset BlankSprite { get; } = new("MiraAPI.Resources.BlankSprite.png");
}
@@ -0,0 +1,83 @@
using System.Collections.Generic;
using Reactor.Utilities.Extensions;
using TMPro;
using UnityEngine;
namespace MiraAPI.Utilities.Assets;
public static class TmpSpriteUtils
{
private static Shader _spriteShader;
private static Dictionary<string, TMP_SpriteAsset> LoadedSprites = [];
public static TMP_SpriteAsset AssetHolder;
public static TMP_SpriteAsset CreateSpriteAsset(Sprite sprite, string assetName, float scale = 1)
{
return CreateSpriteAsset(sprite.texture, sprite.rect, assetName, scale);
}
public static TMP_SpriteAsset CreateSpriteAsset(Texture2D sourceTexture, Rect rect, string assetName, float scale = 1)
{
if (LoadedSprites.TryGetValue(assetName, out var existingAsset))
{
return existingAsset;
}
if (!AssetHolder)
{
AssetHolder = ScriptableObject.CreateInstance<TMP_SpriteAsset>();
AssetHolder.DontUnload().DontDestroy();
AssetHolder.fallbackSpriteAssets = new();
}
TMP_SpriteAsset spriteAsset = ScriptableObject.CreateInstance<TMP_SpriteAsset>();
spriteAsset.name = assetName;
spriteAsset.spriteSheet = sourceTexture;
if (!_spriteShader)
{
_spriteShader = Shader.Find("TextMeshPro/Sprite");
}
var material = new Material(_spriteShader)
{
name = assetName + " Material",
};
material.SetTexture(ShaderUtilities.ID_MainTex, sourceTexture);
material.SetFloat(ShaderUtilities.ID_StencilComp, 0);
material.SetFloat(ShaderUtilities.ID_StencilID, 0);
material.SetFloat(ShaderUtilities.ID_StencilOp, 0);
material.SetFloat(ShaderUtilities.ID_StencilWriteMask, 255);
material.SetFloat(ShaderUtilities.ID_StencilReadMask, 255);
material.SetFloat(ShaderUtilities.ShaderTag_CullMode, 0);
spriteAsset.material = material;
spriteAsset.spriteInfoList = new Il2CppSystem.Collections.Generic.List<TMP_Sprite>();
AddSpriteToAsset(spriteAsset, rect, assetName, scale);
spriteAsset.DontUnload().DontDestroy();
spriteAsset.UpdateLookupTables();
spriteAsset.fallbackSpriteAssets = new();
AssetHolder.fallbackSpriteAssets.Add(spriteAsset);
AssetHolder.UpdateLookupTables();
LoadedSprites.Add(assetName, spriteAsset);
return spriteAsset;
}
private static void AddSpriteToAsset(TMP_SpriteAsset spriteAsset, Rect rect, string spriteName, float scale)
{
TMP_Sprite newSprite = new TMP_Sprite
{
name = spriteName,
hashCode = TMP_TextUtilities.GetSimpleHashCode(spriteName),
x = 0,
y = 0,
width = rect.width,
height = rect.height,
xOffset = -(rect.width / 3) + (scale - 1) * (rect.width / 2),
yOffset = rect.height / 1.25f,
xAdvance = rect.width,
scale = scale,
};
spriteAsset.spriteInfoList.Add(newSprite);
}
}
+43 -20
View File
@@ -1,6 +1,7 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.Linq;
using System.Reflection;
@@ -8,10 +9,8 @@ using System.Text.RegularExpressions;
using HarmonyLib;
using MiraAPI.GameOptions;
using MiraAPI.Networking;
using MiraAPI.Patches.Menu;
using MiraAPI.Roles;
using MiraAPI.Voting;
using Reactor.Utilities;
using Reactor.Utilities.Extensions;
using Rewired;
using Rewired.Data;
@@ -56,7 +55,7 @@ public static class Extensions
bool isComplete;
if (self.amClosing == Minigame.CloseState.Closing)
{
self.gameObject.DeepDestroy();
self.gameObject.Destroy();
return;
}
if (self.CloseSound && Constants.ShouldPlaySfx())
@@ -229,13 +228,44 @@ public static class Extensions
/// <param name="clearGc">Whether to run the garbage collector immediately.</param>
public static void DeepDestroy(this GameObject obj, bool clearGc = true)
{
if (MainMenuManagerPatches.NeedsDeepDestroy)
obj.Destroy();
}
/// <summary>
/// Runs a given action in a loop with a frame budget based on the current target frame rate. Once the budget is hit, the loop continues on the next frame.
/// </summary>
/// <param name="collection">The collection to iterate over.</param>
/// <param name="action">The action to perform on each item.</param>
/// <typeparam name="T">The type of the collection.</typeparam>
/// <returns>Coroutine.</returns>
public static IEnumerator CoLoopWithBudget<T>(this IEnumerable<T> collection, Action<T> action)
{
var fps = Application.targetFrameRate > 0 ? Application.targetFrameRate : 60;
long budget = 1 / (fps * 2); // default is half of current frame time.
yield return collection.CoLoopWithBudget(budget, action);
}
/// <summary>
/// Runs a given action in a loop with a given frame budget. Once the budget is hit, the loop continues on the next frame.
/// </summary>
/// <param name="collection">The collection to iterate over.</param>
/// <param name="frameBudget">The # of milliseconds to spend in the loop.</param>
/// <param name="action">The action to perform on each item.</param>
/// <typeparam name="T">The type of the collection.</typeparam>
/// <returns>Coroutine.</returns>
public static IEnumerator CoLoopWithBudget<T>(this IEnumerable<T> collection, long frameBudget, Action<T> action)
{
var timer = new Stopwatch();
timer.Start();
foreach (var item in collection)
{
Coroutines.Start(Nuke(obj, clearGc));
}
else
{
obj?.Destroy();
action(item);
if (timer.ElapsedMilliseconds > frameBudget)
{
timer.Restart();
yield return null;
}
}
}
@@ -326,7 +356,7 @@ public static class Extensions
yield return null;
if (clearGc)
{
yield return CoFreeResources();
ClearGarbageCollector();
}
}
@@ -335,16 +365,9 @@ public static class Extensions
/// </summary>
public static void ClearGarbageCollector()
{
Coroutines.Start(CoFreeResources());
}
private static IEnumerator CoFreeResources()
{
yield return Resources.UnloadUnusedAssets();
GC.Collect(0, GCCollectionMode.Forced, blocking: true);
GC.WaitForPendingFinalizers();
GC.Collect(0, GCCollectionMode.Forced, blocking: true);
Resources.UnloadUnusedAssets();
Il2CppSystem.GC.Collect(0, Il2CppSystem.GCCollectionMode.Forced);
GC.Collect(0, GCCollectionMode.Forced);
}
/// <summary>
-2
View File
@@ -2,12 +2,10 @@
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using AmongUs.GameOptions;
using HarmonyLib;
using Il2CppInterop.Runtime.InteropTypes.Arrays;
using MiraAPI.Roles;
using MiraAPI.Utilities.Assets;
using Reactor.Utilities;
using Rewired;
using TMPro;
using UnityEngine;
+3 -1
View File
@@ -5,7 +5,6 @@ using MiraAPI.Events.Vanilla.Meeting.Voting;
using MiraAPI.Networking;
using MiraAPI.Utilities;
using Reactor.Networking.Attributes;
using Reactor.Utilities;
namespace MiraAPI.Voting;
@@ -207,6 +206,9 @@ public static class VotingUtils
return;
}
// If modified, these will visually change.
votes = @event.Votes;
MeetingHud.Instance.TitleText.text =
TranslationController.Instance.GetString(
StringNames.MeetingVotingResults,