From c1cd4a7d67dbf3fe06cf7b22c1feffd5a26964c8 Mon Sep 17 00:00:00 2001
From: Az <56699741+AlchlcDvl@users.noreply.github.com>
Date: Sun, 27 Sep 2026 23:24:57 -0400
Subject: [PATCH 01/10] fix small overlooked behaviours
- fixes issue #45 where the player leave event was in a postfix, when the player character was already destroyed
- fixes #46 where modded role options did not have the same change zero behaviour as vanilla ones
---
MiraAPI/Patches/AmongUsClientSyncPatch.cs | 2 +-
MiraAPI/Patches/Options/OptionsPatches.cs | 20 ++++++++++++++++++++
2 files changed, 21 insertions(+), 1 deletion(-)
diff --git a/MiraAPI/Patches/AmongUsClientSyncPatch.cs b/MiraAPI/Patches/AmongUsClientSyncPatch.cs
index a8a3dfe..926004d 100644
--- a/MiraAPI/Patches/AmongUsClientSyncPatch.cs
+++ b/MiraAPI/Patches/AmongUsClientSyncPatch.cs
@@ -36,7 +36,7 @@ internal static class AmongUsClientSyncPatch
GameModeOption.RpcSyncGamemode(PlayerControl.LocalPlayer, GameModeOption.Value);
}
- [HarmonyPostfix]
+ [HarmonyPrefix]
[HarmonyPatch(typeof(AmongUsClient), nameof(AmongUsClient.OnPlayerLeft))]
public static void PlayerLeftPatch(ClientData data, DisconnectReasons reason)
{
diff --git a/MiraAPI/Patches/Options/OptionsPatches.cs b/MiraAPI/Patches/Options/OptionsPatches.cs
index 64d9119..e99a893 100644
--- a/MiraAPI/Patches/Options/OptionsPatches.cs
+++ b/MiraAPI/Patches/Options/OptionsPatches.cs
@@ -34,6 +34,11 @@ public static class OptionsPatches
__instance.roleChance = 0;
}
+ if (__instance.roleChance == 0)
+ {
+ __instance.roleMaxCount = 0;
+ }
+
__instance.OnValueChanged.Invoke(__instance);
return false;
}
@@ -60,6 +65,11 @@ public static class OptionsPatches
__instance.roleChance = 100;
}
+ if (__instance.roleChance == 0)
+ {
+ __instance.roleMaxCount = 0;
+ }
+
__instance.OnValueChanged.Invoke(__instance);
return false;
}
@@ -84,6 +94,11 @@ public static class OptionsPatches
__instance.roleMaxCount = 0;
}
+ if (__instance.roleMaxCount == 0)
+ {
+ __instance.roleChance = 0;
+ }
+
__instance.OnValueChanged.Invoke(__instance);
return false;
}
@@ -108,6 +123,11 @@ public static class OptionsPatches
__instance.roleMaxCount = __instance.role.MaxCount;
}
+ if (__instance.roleMaxCount == 0)
+ {
+ __instance.roleChance = 0;
+ }
+
__instance.OnValueChanged.Invoke(__instance);
return false;
}
From f5a994abc3c8bb34666dbdca2e3c8ab0caf05208 Mon Sep 17 00:00:00 2001
From: Az <56699741+AlchlcDvl@users.noreply.github.com>
Date: Thu, 8 Oct 2026 00:30:57 -0400
Subject: [PATCH 02/10] avoid over-allocating objects
when reading sprite sheets
---
.../Assets/LoadableBundleSubAssetHolder.cs | 40 ++++++++-----------
1 file changed, 17 insertions(+), 23 deletions(-)
diff --git a/MiraAPI/Utilities/Assets/LoadableBundleSubAssetHolder.cs b/MiraAPI/Utilities/Assets/LoadableBundleSubAssetHolder.cs
index bc2e5c4..85c76ac 100644
--- a/MiraAPI/Utilities/Assets/LoadableBundleSubAssetHolder.cs
+++ b/MiraAPI/Utilities/Assets/LoadableBundleSubAssetHolder.cs
@@ -1,7 +1,5 @@
using System;
-using System.Diagnostics.CodeAnalysis;
-using System.Linq;
-using HarmonyLib;
+using System.Collections.Generic;
using Il2CppInterop.Runtime;
using Reactor.Utilities.Extensions;
using UnityEngine;
@@ -47,35 +45,31 @@ public class LoadableBundleSubAssetHolder
/// Attempts to load all of the sprite assets within the sprite sheet.
///
/// Thrown if the asset is not actually a sprite sheet.
- [SuppressMessage("Style", "IDE0270:Use coalesce expression", Justification = "Null coalescing bypasses Unity lifetime checks.")]
public void TryInit()
{
- if (SubSprites.Length == 0)
+ if (SubSprites.Length != 0)
+ return;
+
+ var newSprites = new List();
+
+ foreach (var name in spriteNames)
{
- var newSprites = Array.Empty();
+ var loadedAssets = bundle.LoadAssetWithSubAssets(name, Il2CppType.From(typeof(Sprite)))
+ ?? throw new InvalidOperationException($"INVALID ASSETS: {name}");
- foreach (var name in spriteNames)
+ foreach (var obj in loadedAssets)
{
- var loadedAssets = bundle.LoadAssetWithSubAssets(name, Il2CppType.From(typeof(Sprite))).ToArray();
+ var img = obj.TryCast();
- if (loadedAssets == null)
- {
- throw new InvalidOperationException($"INVALID ASSETS: {name}");
- }
+ if (img == null)
+ continue;
- foreach (var obj in loadedAssets)
- {
- var img = obj.TryCast();
- if (img != null)
- {
- img.DontDestroy().DontUnload();
- newSprites = newSprites.AddToArray(img);
- }
- }
+ img.DontDestroy().DontUnload();
+ newSprites.Add(img);
}
-
- SubSprites = newSprites;
}
+
+ SubSprites = [.. newSprites];
}
///
From 6410a0dd426f2df72511f159cbbb1515e042cc18 Mon Sep 17 00:00:00 2001
From: Az <56699741+AlchlcDvl@users.noreply.github.com>
Date: Thu, 8 Oct 2026 01:02:09 -0400
Subject: [PATCH 03/10] consolidate copy pasted addressables code
---
.../Utilities/Assets/AddressablesLoader.cs | 66 ++++++++-----------
1 file changed, 28 insertions(+), 38 deletions(-)
diff --git a/MiraAPI/Utilities/Assets/AddressablesLoader.cs b/MiraAPI/Utilities/Assets/AddressablesLoader.cs
index 39626e9..ec02972 100644
--- a/MiraAPI/Utilities/Assets/AddressablesLoader.cs
+++ b/MiraAPI/Utilities/Assets/AddressablesLoader.cs
@@ -1,6 +1,7 @@
using System.Collections;
using System.Collections.Generic;
using System.Linq;
+using System.Runtime.CompilerServices;
using Il2CppInterop.Runtime.Attributes;
using MiraAPI.Patches.Menu;
using Reactor.Utilities;
@@ -23,26 +24,36 @@ public static class AddressablesLoader
private static readonly List RegisteredSkinKeys = [];
private static bool _isInitialized;
+ private static bool _addressableHatsExist;
+ private static bool _addressableVisorsExist;
+ private static bool _addressableNameplatesExist;
+ private static bool _addressableSkinsExist;
+ private static bool _catalogsExist;
///
/// Gets a value indicating whether hats have been loaded by the addressables system.
///
- public static bool AddressableHatsExist { get; private set; }
+ public static bool AddressableHatsExist => _addressableHatsExist;
///
/// Gets a value indicating whether visors have been loaded by the addressables system.
///
- public static bool AddressableVisorsExist { get; private set; }
+ public static bool AddressableVisorsExist => _addressableVisorsExist;
///
/// Gets a value indicating whether nameplates have been loaded by the addressables system.
///
- public static bool AddressableNameplatesExist { get; private set; }
+ public static bool AddressableNameplatesExist => _addressableNameplatesExist;
///
/// Gets a value indicating whether skins have been loaded by the addressables system.
///
- public static bool AddressableSkinsExist { get; private set; }
+ public static bool AddressableSkinsExist => _addressableSkinsExist;
+
+ ///
+ /// Gets a value indicating whether catalogs have been loaded by the addressables system.
+ ///
+ public static bool CatalogsExist => _catalogsExist;
///
/// Registers a specific addressables package to load asynchronously at the start of the game, when possible.
@@ -51,13 +62,7 @@ public static class AddressablesLoader
/// The suffix of the provider for an addressables package.
public static void RegisterCatalog(string location, string providerSuffix = "")
{
- if (_isInitialized)
- {
- Error("AddressablesLoader has already been initialized, cannot register more catalogs.");
- return;
- }
-
- CatalogLocations.Add((location, providerSuffix));
+ RegisterCosmetic((location, providerSuffix), CatalogLocations, "catalog", ref _catalogsExist);
}
///
@@ -66,14 +71,7 @@ public static class AddressablesLoader
/// The key/label/group for a List .
public static void RegisterHats(string addressablesKey)
{
- if (_isInitialized)
- {
- Error("AddressablesLoader has already been initialized, cannot register more keys for hats.");
- return;
- }
-
- AddressableHatsExist = true;
- RegisteredHatKeys.Add(addressablesKey);
+ RegisterCosmetic(addressablesKey, RegisteredHatKeys, "hat", ref _addressableHatsExist);
}
///
@@ -82,14 +80,7 @@ public static class AddressablesLoader
/// The key/label/group for a List .
public static void RegisterSkins(string addressablesKey)
{
- if (_isInitialized)
- {
- Error("AddressablesLoader has already been initialized, cannot register more keys for skins.");
- return;
- }
-
- AddressableSkinsExist = true;
- RegisteredSkinKeys.Add(addressablesKey);
+ RegisterCosmetic(addressablesKey, RegisteredSkinKeys, "skin", ref _addressableSkinsExist);
}
///
@@ -99,14 +90,7 @@ public static class AddressablesLoader
/// /// The title of the group for visors.
public static void RegisterNameplates(string addressablesKey, string groupTitle)
{
- if (_isInitialized)
- {
- Error("AddressablesLoader has already been initialized, cannot register more keys for nameplates.");
- return;
- }
-
- AddressableNameplatesExist = true;
- RegisteredNameplateKeys.Add((addressablesKey, groupTitle));
+ RegisterCosmetic((addressablesKey, groupTitle), RegisteredNameplateKeys, "nameplate", ref _addressableNameplatesExist);
}
///
@@ -115,15 +99,21 @@ public static class AddressablesLoader
/// The key/label/group for a List .
/// The title of the group for visors.
public static void RegisterVisors(string addressablesKey, string groupTitle)
+ {
+ RegisterCosmetic((addressablesKey, groupTitle), RegisteredVisorKeys, "visor", ref _addressableVisorsExist);
+ }
+
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ private static void RegisterCosmetic(T value, List values, string type, ref bool flag)
{
if (_isInitialized)
{
- Error("AddressablesLoader has already been initialized, cannot register more keys for visors.");
+ Error($"AddressablesLoader has already been initialized, cannot register more keys for {type}s.");
return;
}
- AddressableVisorsExist = true;
- RegisteredVisorKeys.Add((addressablesKey, groupTitle));
+ flag = true;
+ values.Add(value);
}
internal static void LoadAll()
From a90a0c4905a5f2251450728f6ec62d2d43902d08 Mon Sep 17 00:00:00 2001
From: Az <56699741+AlchlcDvl@users.noreply.github.com>
Date: Thu, 8 Oct 2026 01:20:05 -0400
Subject: [PATCH 04/10] cache audio clips
---
MiraAPI/Utilities/Assets/AudioTools.cs | 131 ++++++++++++++++++
.../Assets/LoadableAudioResourceAsset.cs | 112 +--------------
.../Assets/LoadableBundleSubAssetHolder.cs | 22 +--
3 files changed, 141 insertions(+), 124 deletions(-)
create mode 100644 MiraAPI/Utilities/Assets/AudioTools.cs
diff --git a/MiraAPI/Utilities/Assets/AudioTools.cs b/MiraAPI/Utilities/Assets/AudioTools.cs
new file mode 100644
index 0000000..abb6bc1
--- /dev/null
+++ b/MiraAPI/Utilities/Assets/AudioTools.cs
@@ -0,0 +1,131 @@
+using System;
+using System.IO;
+using System.Reflection;
+using System.Resources;
+using System.Text;
+using UnityEngine;
+
+namespace MiraAPI.Utilities.Assets;
+
+///
+/// A utility class for various audio-related operations.
+///
+public static class AudioTools
+{
+ ///
+ /// Loads and returns an audio clip from a resource path using the specified .
+ ///
+ /// The path to the resource within the .
+ /// The from which to load the resource.
+ /// A object loaded from the specified resource path.
+ /// Attempted to load an Audio file in non WAV format.
+ /// Stream failed to load. Check if the name of your asset was correct.
+ public static AudioClip LoadAudioFromResources(string resourcePath, Assembly assembly)
+ {
+ using var assetStream = assembly.GetManifestResourceStream(resourcePath)
+ ?? throw new MissingManifestResourceException($"Stream failed to load. Check if the asset name is correct: {resourcePath}");
+
+ using var reader = new BinaryReader(assetStream);
+
+ // Read RIFF header
+ if (Encoding.ASCII.GetString(reader.ReadBytes(4)) != "RIFF")
+ {
+ throw new NotSupportedException("Invalid WAV file (missing RIFF header).");
+ }
+
+ reader.ReadInt32(); // File size (ignore)
+
+ if (Encoding.ASCII.GetString(reader.ReadBytes(4)) != "WAVE")
+ {
+ throw new NotSupportedException("Invalid WAV file (missing WAVE header).");
+ }
+
+ // Read chunks
+ int channels = 0, sampleRate = 0, bitsPerSample = 0;
+ byte[]? audioData = null;
+
+ while (reader.BaseStream.Position < reader.BaseStream.Length)
+ {
+ var chunkId = Encoding.ASCII.GetString(reader.ReadBytes(4));
+ var chunkSize = reader.ReadInt32();
+
+ // Format chunk
+ if (chunkId == "fmt ")
+ {
+ int audioFormat = reader.ReadInt16();
+ channels = reader.ReadInt16();
+ sampleRate = reader.ReadInt32();
+ reader.ReadInt32(); // Byte rate (ignore)
+ reader.ReadInt16(); // Block align (ignore)
+ bitsPerSample = reader.ReadInt16();
+
+ if (audioFormat != 1) // Only PCM supported
+ throw new NotSupportedException("Only PCM WAV files are supported.");
+ }
+
+ // Data chunk
+ else if (chunkId == "data")
+ {
+ audioData = reader.ReadBytes(chunkSize);
+ break; // No need to read further
+ }
+ else
+ {
+ reader.BaseStream.Seek(chunkSize, SeekOrigin.Current); // Skip unknown chunks
+ }
+ }
+
+ if (audioData == null)
+ {
+ throw new InvalidOperationException("WAV file does not contain audio data.");
+ }
+
+ if (channels == 0 || sampleRate == 0 || bitsPerSample == 0)
+ {
+ throw new InvalidOperationException("WAV file does not contain valid format information.");
+ }
+
+ // Convert PCM data to float array
+ var samples = ConvertPcmToFloat(audioData, bitsPerSample);
+
+ // Create the AudioClip
+ var audioClip = AudioClip.Create(resourcePath, samples.Length / channels, channels, sampleRate, false);
+ audioClip.SetData(samples, 0);
+
+ return audioClip;
+ }
+
+ // This is somewhat magic to me, I just copied it from elsewhere.
+ private static float[] ConvertPcmToFloat(byte[] pcmData, int bitsPerSample)
+ {
+ var sampleCount = pcmData.Length / (bitsPerSample / 8);
+ var floatData = new float[sampleCount];
+
+ for (var i = 0; i < sampleCount; i++)
+ {
+ var byteIndex = i * (bitsPerSample / 8);
+
+ switch (bitsPerSample)
+ {
+ case 8:
+ floatData[i] = (pcmData[byteIndex] - 128) / 128f; // 8-bit PCM is unsigned
+ break;
+ case 16:
+ floatData[i] = BitConverter.ToInt16(pcmData, byteIndex) / 32768f;
+ break;
+ case 24:
+ var sample24 = pcmData[byteIndex] | (pcmData[byteIndex + 1] << 8) | (pcmData[byteIndex + 2] << 16);
+ if (sample24 > 0x7FFFFF) sample24 -= 0x1000000; // Convert from unsigned to signed
+ floatData[i] = sample24 / 8388608f;
+ break;
+ case 32:
+ floatData[i] = BitConverter.ToInt32(pcmData, byteIndex) / 2147483648f;
+ break;
+ default:
+ throw new NotSupportedException($"Unsupported bit depth: {bitsPerSample}");
+ }
+ }
+
+ return floatData;
+ }
+}
diff --git a/MiraAPI/Utilities/Assets/LoadableAudioResourceAsset.cs b/MiraAPI/Utilities/Assets/LoadableAudioResourceAsset.cs
index 1bb75ae..8dbc521 100644
--- a/MiraAPI/Utilities/Assets/LoadableAudioResourceAsset.cs
+++ b/MiraAPI/Utilities/Assets/LoadableAudioResourceAsset.cs
@@ -1,8 +1,4 @@
-using System;
-using System.IO;
using System.Reflection;
-using System.Resources;
-using System.Text;
using UnityEngine;
namespace MiraAPI.Utilities.Assets;
@@ -19,114 +15,14 @@ public class LoadableAudioResourceAsset(string path) : LoadableAsset
/// Loads the asset from embedded resources.
///
/// The asset to load.
- /// Attempted to load an Audio file in non WAV format.
- /// Stream failed to load. Check if the name of your asset was correct.
+ ///
public override AudioClip LoadAsset()
{
- using var assetStream = _assembly.GetManifestResourceStream(path)
- ?? throw new MissingManifestResourceException($"Stream failed to load. Check if the asset name is correct: {path}");
-
- using var reader = new BinaryReader(assetStream);
-
- // Read RIFF header
- if (Encoding.ASCII.GetString(reader.ReadBytes(4)) != "RIFF")
+ if (!LoadedAsset)
{
- throw new NotSupportedException("Invalid WAV file (missing RIFF header).");
+ LoadedAsset = AudioTools.LoadAudioFromResources(path, _assembly);
}
- reader.ReadInt32(); // File size (ignore)
-
- if (Encoding.ASCII.GetString(reader.ReadBytes(4)) != "WAVE")
- {
- throw new NotSupportedException("Invalid WAV file (missing WAVE header).");
- }
-
- // Read chunks
- int channels = 0, sampleRate = 0, bitsPerSample = 0;
- byte[]? audioData = null;
-
- while (reader.BaseStream.Position < reader.BaseStream.Length)
- {
- var chunkId = Encoding.ASCII.GetString(reader.ReadBytes(4));
- var chunkSize = reader.ReadInt32();
-
- // Format chunk
- if (chunkId == "fmt ")
- {
- int audioFormat = reader.ReadInt16();
- channels = reader.ReadInt16();
- sampleRate = reader.ReadInt32();
- reader.ReadInt32(); // Byte rate (ignore)
- reader.ReadInt16(); // Block align (ignore)
- bitsPerSample = reader.ReadInt16();
-
- if (audioFormat != 1) // Only PCM supported
- throw new NotSupportedException("Only PCM WAV files are supported.");
- }
-
- // Data chunk
- else if (chunkId == "data")
- {
- audioData = reader.ReadBytes(chunkSize);
- break; // No need to read further
- }
- else
- {
- reader.BaseStream.Seek(chunkSize, SeekOrigin.Current); // Skip unknown chunks
- }
- }
-
- if (audioData == null)
- {
- throw new InvalidOperationException("WAV file does not contain audio data.");
- }
-
- if (channels == 0 || sampleRate == 0 || bitsPerSample == 0)
- {
- throw new InvalidOperationException("WAV file does not contain valid format information.");
- }
-
- // Convert PCM data to float array
- var samples = ConvertPcmToFloat(audioData, bitsPerSample);
-
- // Create the AudioClip
- var audioClip = AudioClip.Create(path, samples.Length / channels, channels, sampleRate, false);
- audioClip.SetData(samples, 0);
-
- return audioClip;
- }
-
- // This is somewhat magic to me, I just copied it from elsewhere.
- private static float[] ConvertPcmToFloat(byte[] pcmData, int bitsPerSample)
- {
- var sampleCount = pcmData.Length / (bitsPerSample / 8);
- var floatData = new float[sampleCount];
-
- for (var i = 0; i < sampleCount; i++)
- {
- var byteIndex = i * (bitsPerSample / 8);
-
- switch (bitsPerSample)
- {
- case 8:
- floatData[i] = (pcmData[byteIndex] - 128) / 128f; // 8-bit PCM is unsigned
- break;
- case 16:
- floatData[i] = BitConverter.ToInt16(pcmData, byteIndex) / 32768f;
- break;
- case 24:
- var sample24 = pcmData[byteIndex] | (pcmData[byteIndex + 1] << 8) | (pcmData[byteIndex + 2] << 16);
- if (sample24 > 0x7FFFFF) sample24 -= 0x1000000; // Convert from unsigned to signed
- floatData[i] = sample24 / 8388608f;
- break;
- case 32:
- floatData[i] = BitConverter.ToInt32(pcmData, byteIndex) / 2147483648f;
- break;
- default:
- throw new NotSupportedException($"Unsupported bit depth: {bitsPerSample}");
- }
- }
-
- return floatData;
+ return LoadedAsset!;
}
}
diff --git a/MiraAPI/Utilities/Assets/LoadableBundleSubAssetHolder.cs b/MiraAPI/Utilities/Assets/LoadableBundleSubAssetHolder.cs
index 85c76ac..80de3b4 100644
--- a/MiraAPI/Utilities/Assets/LoadableBundleSubAssetHolder.cs
+++ b/MiraAPI/Utilities/Assets/LoadableBundleSubAssetHolder.cs
@@ -9,36 +9,26 @@ namespace MiraAPI.Utilities.Assets;
///
/// A utility class for loading multiple assets from an .
///
-public class LoadableBundleSubAssetHolder
+/// The name of the assets to pull from.
+/// The that contains the assets.
+public class LoadableBundleSubAssetHolder(string[] names, AssetBundle bundle)
{
- private readonly string[] spriteNames;
- private readonly AssetBundle bundle;
+ private readonly string[] spriteNames = names;
+ private readonly AssetBundle bundle = bundle;
///
/// Gets the sprites contained within the asset.
///
public Sprite[] SubSprites { get; private set; } = [];
- ///
- /// Initializes a new instance of the class.
- ///
- /// The name of the assets to pull from.
- /// The that contains the assets.
- public LoadableBundleSubAssetHolder(string[] names, AssetBundle bundle)
- {
- this.bundle = bundle;
- spriteNames = names;
- }
-
///
/// Initializes a new instance of the class.
///
/// The name of the asset.
/// The that contains the assets.
public LoadableBundleSubAssetHolder(string name, AssetBundle bundle)
+ : this([name], bundle)
{
- this.bundle = bundle;
- spriteNames = [name];
}
///
From 43f1209c1ca8c659ddeadf2021bc69539d40969f Mon Sep 17 00:00:00 2001
From: Az <56699741+AlchlcDvl@users.noreply.github.com>
Date: Thu, 8 Oct 2026 01:27:24 -0400
Subject: [PATCH 05/10] minor code changes
---
MiraAPI/Utilities/Assets/LoadableAudioResourceAsset.cs | 4 ----
MiraAPI/Utilities/Assets/LoadableBundleSubAssetHolder.cs | 5 +----
2 files changed, 1 insertion(+), 8 deletions(-)
diff --git a/MiraAPI/Utilities/Assets/LoadableAudioResourceAsset.cs b/MiraAPI/Utilities/Assets/LoadableAudioResourceAsset.cs
index 8dbc521..49529a5 100644
--- a/MiraAPI/Utilities/Assets/LoadableAudioResourceAsset.cs
+++ b/MiraAPI/Utilities/Assets/LoadableAudioResourceAsset.cs
@@ -11,10 +11,6 @@ public class LoadableAudioResourceAsset(string path) : LoadableAsset
{
private readonly Assembly _assembly = Assembly.GetCallingAssembly();
- ///
- /// Loads the asset from embedded resources.
- ///
- /// The asset to load.
///
public override AudioClip LoadAsset()
{
diff --git a/MiraAPI/Utilities/Assets/LoadableBundleSubAssetHolder.cs b/MiraAPI/Utilities/Assets/LoadableBundleSubAssetHolder.cs
index 80de3b4..7925607 100644
--- a/MiraAPI/Utilities/Assets/LoadableBundleSubAssetHolder.cs
+++ b/MiraAPI/Utilities/Assets/LoadableBundleSubAssetHolder.cs
@@ -13,9 +13,6 @@ namespace MiraAPI.Utilities.Assets;
/// The that contains the assets.
public class LoadableBundleSubAssetHolder(string[] names, AssetBundle bundle)
{
- private readonly string[] spriteNames = names;
- private readonly AssetBundle bundle = bundle;
-
///
/// Gets the sprites contained within the asset.
///
@@ -42,7 +39,7 @@ public class LoadableBundleSubAssetHolder(string[] names, AssetBundle bundle)
var newSprites = new List();
- foreach (var name in spriteNames)
+ foreach (var name in names)
{
var loadedAssets = bundle.LoadAssetWithSubAssets(name, Il2CppType.From(typeof(Sprite)))
?? throw new InvalidOperationException($"INVALID ASSETS: {name}");
From bdf9f4c9e84e6046db2ec7fcefbb43c0e92b0d1d Mon Sep 17 00:00:00 2001
From: Az <56699741+AlchlcDvl@users.noreply.github.com>
Date: Sun, 11 Oct 2026 12:01:26 -0400
Subject: [PATCH 06/10] deprecate addressables loader
- decprecates the addressables loader utility
- increments the required version
---
MiraAPI/Patches/Menu/HatsTabPatches.cs | 193 ------------------
MiraAPI/Patches/Menu/InventoryUtility.cs | 55 -----
.../Patches/Menu/MainMenuManagerPatches.cs | 4 +-
MiraAPI/Patches/Menu/NameplatesTabPatches.cs | 161 ---------------
MiraAPI/Patches/Menu/SkinsTabPatches.cs | 155 --------------
MiraAPI/Patches/Menu/VisorsTabPatches.cs | 154 --------------
.../Utilities/Assets/AddressablesLoader.cs | 4 +-
7 files changed, 4 insertions(+), 722 deletions(-)
delete mode 100644 MiraAPI/Patches/Menu/HatsTabPatches.cs
delete mode 100644 MiraAPI/Patches/Menu/InventoryUtility.cs
delete mode 100644 MiraAPI/Patches/Menu/NameplatesTabPatches.cs
delete mode 100644 MiraAPI/Patches/Menu/SkinsTabPatches.cs
delete mode 100644 MiraAPI/Patches/Menu/VisorsTabPatches.cs
diff --git a/MiraAPI/Patches/Menu/HatsTabPatches.cs b/MiraAPI/Patches/Menu/HatsTabPatches.cs
deleted file mode 100644
index e9cebd8..0000000
--- a/MiraAPI/Patches/Menu/HatsTabPatches.cs
+++ /dev/null
@@ -1,193 +0,0 @@
-using System;
-using System.Collections;
-using System.Collections.Generic;
-using System.Collections.Immutable;
-using System.Diagnostics.CodeAnalysis;
-using System.Linq;
-using AmongUs.Data;
-using HarmonyLib;
-using MiraAPI.Utilities;
-using MiraAPI.Utilities.Assets;
-using Reactor.Utilities;
-using Reactor.Utilities.Extensions;
-using TMPro;
-using UnityEngine;
-using Object = UnityEngine.Object;
-
-namespace MiraAPI.Patches.Menu;
-
-[HarmonyPatch(typeof(HatsTab))]
-public static class HatsTabPatches
-{
- private static readonly Dictionary StoreNames = [];
- private static SortedList> sortedHats = [];
- private static int currentPage;
-
- private static void PreviousPage(HatsTab hatsTab)
- {
- currentPage--;
- currentPage = currentPage < 0 ? sortedHats.Count - 1 : currentPage;
- GenerateHats(hatsTab, currentPage);
- }
-
- private static void NextPage(HatsTab hatsTab)
- {
- currentPage++;
- currentPage = currentPage > sortedHats.Count - 1 ? 0 : currentPage;
- GenerateHats(hatsTab, currentPage);
- }
-
- [HarmonyPatch(nameof(HatsTab.OnEnable))]
- [HarmonyPrefix]
- [SuppressMessage("Style", "IDE0028:Collection initialization can be simplified", Justification = "Preview feature.")]
- public static bool OnEnablePrefix(HatsTab __instance)
- {
- if (!AddressablesLoader.AddressableHatsExist)
- {
- return true;
- }
-
- __instance.currentHat = HatManager.Instance.GetHatById(DataManager.Player.Customization.Hat);
- var allHats = HatManager.Instance.GetUnlockedHats().ToImmutableList();
-
- if (sortedHats.Count == 0)
- {
- var num = 0;
- var comparer = new ControllableComparer(["vanilla"], [], StringComparer.InvariantCulture);
- sortedHats = new SortedList>(comparer);
- foreach (var hat in allHats)
- {
- if (!sortedHats.ContainsKey(hat.StoreName)) sortedHats[hat.StoreName] = [];
- sortedHats[hat.StoreName].Add(hat);
-
- if (!StoreNames.ContainsValue(hat.StoreName))
- {
- StoreNames.Add(num, hat.StoreName);
- num++;
- }
- }
- }
-
- InventoryUtility.CreateNextBackButtons(__instance, PreviousPage, NextPage);
-
- GenerateHats(__instance, currentPage);
-
- return false;
- }
-
- [HarmonyPatch(typeof(HatsTab), nameof(HatsTab.Update))]
- [HarmonyPrefix]
- public static void UpdatePrefix(HatsTab __instance)
- {
- if (!AddressablesLoader.AddressableHatsExist)
- {
- return;
- }
-
- if (sortedHats.Count == 0) return;
-
- if (Input.GetKeyDown(KeyCode.LeftControl) || Input.GetKeyDown(KeyCode.RightControl) || Input.GetKeyDown(KeyCode.LeftArrow))
- {
- PreviousPage(__instance);
- }
- else if (Input.GetKeyDown(KeyCode.Tab) || Input.GetKeyDown(KeyCode.RightArrow))
- {
- NextPage(__instance);
- }
- }
-
- private static IEnumerator? loadRoutine;
- private static int hatIndex;
-
- private static void GenerateHats(HatsTab __instance, int page)
- {
- if (loadRoutine != null) Coroutines.Stop(loadRoutine);
-
- hatIndex = 0;
- foreach (var instanceColorChip in __instance.ColorChips) instanceColorChip.gameObject.Destroy();
- __instance.ColorChips.Clear();
- __instance.scroller.Inner.GetComponentsInChildren().Do(x => x.gameObject.DeepDestroy(false));
-
- var groupNameText = __instance.GetComponentInChildren(false);
- var group = sortedHats.Where(x => x.Key == StoreNames[page]);
-
- foreach (var (groupName, hats) in group)
- {
- var text = Object.Instantiate(groupNameText, __instance.scroller.Inner);
- text.enabled = true;
- text.gameObject.transform.localScale = Vector3.one;
- text.GetComponent().Destroy();
- text.EnableStencilMasking();
- text.text = $"{groupName} ({currentPage + 1}/{sortedHats.Count})";
- text.alignment = TextAlignmentOptions.Center;
- text.fontSize = 5f;
- text.fontSizeMax = 5f;
- text.fontSizeMin = 0f;
- var xLerp = __instance.XRange.Lerp(0.5f);
-
- // ReSharper disable once PossibleLossOfFraction (Justification: Intended.)
- var yLerp = __instance.YStart - hatIndex / __instance.NumPerRow * __instance.YOffset;
- text.transform.localPosition = new Vector3(xLerp, yLerp, -1f);
-
- hatIndex += 5;
- loadRoutine = Coroutines.Start(CoGenerateChips(__instance, hats));
- }
-
- // ReSharper disable once PossibleLossOfFraction (Justification: Intended.)
- __instance.scroller.ContentYBounds.max = -(__instance.YStart - (hatIndex + 1) / __instance.NumPerRow * __instance.YOffset) - 3f;
- __instance.currentHatIsEquipped = true;
- }
-
- private static IEnumerator CoGenerateChips(HatsTab __instance, List hats)
- {
- __instance.scroller.ScrollToTop();
- var batchSize = 5;
- for (var i = 0; i < hats.Count; i += batchSize)
- {
- var batch = hats.Skip(i).Take(batchSize).ToList();
-
- foreach (var hat in batch.OrderBy(HatManager.Instance.allHats.IndexOf))
- {
- var hatXPosition = __instance.XRange.Lerp(hatIndex % __instance.NumPerRow / (__instance.NumPerRow - 1f));
-
- // ReSharper disable once PossibleLossOfFraction (Justification: Intended.)
- var hatYPosition = __instance.YStart - hatIndex / __instance.NumPerRow * __instance.YOffset;
- GenerateColorChip(__instance, new Vector2(hatXPosition, hatYPosition), hat);
- hatIndex += 1;
- yield return null;
- }
-
- __instance.SetScrollerBounds();
- yield return new WaitForSeconds(0.01f);
- }
-
- __instance.currentHatIsEquipped = true;
- loadRoutine = null;
- }
-
- private static void GenerateColorChip(HatsTab __instance, Vector2 position, HatData hat)
- {
- var colorChip = Object.Instantiate(__instance.ColorTabPrefab, __instance.scroller.Inner);
- colorChip.gameObject.name = hat.ProductId;
- if (ActiveInputManager.currentControlType == ActiveInputManager.InputType.Keyboard)
- {
- colorChip.Button.OnClick.AddListener((Action)__instance.ClickEquip);
- colorChip.Button.OnMouseOver.AddListener((Action)(() => __instance.SelectHat(hat)));
- colorChip.Button.OnMouseOut.AddListener((Action)(() => __instance.SelectHat(HatManager.Instance.GetHatById(DataManager.Player.Customization.Hat))));
- }
- else
- {
- colorChip.Button.OnClick.AddListener((Action)(() => __instance.SelectHat(hat)));
- }
-
- colorChip.Inner.SetHat(hat, __instance.HasLocalPlayer() ? PlayerControl.LocalPlayer.Data.DefaultOutfit.ColorId : DataManager.Player.Customization.Color);
- colorChip.Button.ClickMask = __instance.scroller.Hitbox;
- colorChip.SelectionHighlight.gameObject.SetActive(false);
- __instance.UpdateMaterials(colorChip.Inner.FrontLayer, hat);
- colorChip.Inner.SetMaskType(PlayerMaterial.MaskType.SimpleUI);
- colorChip.transform.localPosition = new Vector3(position.x, position.y, -1f);
- colorChip.Inner.transform.localPosition = hat.ChipOffset + new Vector2(0f, -0.3f);
- colorChip.Tag = hat;
- __instance.ColorChips.Add(colorChip);
- }
-}
diff --git a/MiraAPI/Patches/Menu/InventoryUtility.cs b/MiraAPI/Patches/Menu/InventoryUtility.cs
deleted file mode 100644
index 8284005..0000000
--- a/MiraAPI/Patches/Menu/InventoryUtility.cs
+++ /dev/null
@@ -1,55 +0,0 @@
-using System;
-using MiraAPI.Utilities.Assets;
-using TMPro;
-using UnityEngine;
-using UnityEngine.Events;
-using UnityEngine.UI;
-using Object = UnityEngine.Object;
-
-namespace MiraAPI.Patches.Menu;
-
-public static class InventoryUtility
-{
- public static void CreateNextBackButtons(T tab, Action previousPage, Action nextPage)
- where T : InventoryTab
- {
- var title = tab.transform.FindChild("Text");
- title.localPosition = new Vector3(.9123f, -.23f, -55);
- title.GetComponent().alignment = TextAlignmentOptions.Center;
-
- tab.scroller.Hitbox.transform.localScale -= new Vector3(0, 0.1f, 0);
- tab.scroller.Hitbox.transform.localPosition -= new Vector3(0, 0.1f, 0);
-
- var leftButtonElement = Object.Instantiate(PlayerCustomizationMenu.Instance.BackButton.gameObject, tab.transform);
- var leftSpriteRenderer = leftButtonElement.GetComponent();
- var leftButton = leftButtonElement.GetComponent();
-
- leftButtonElement.transform.localPosition = new Vector3(-1.1f, -0.2f, -55);
- leftSpriteRenderer.sprite = MiraAssets.NextButton.LoadAsset();
- leftSpriteRenderer.flipX = true;
-
- leftButton.OnMouseOver = new UnityEvent();
- leftButton.OnMouseOver.AddListener((Action)(() => leftSpriteRenderer.sprite = MiraAssets.NextButtonActive.LoadAsset()));
- leftButton.OnMouseOut = new UnityEvent();
- leftButton.OnMouseOut.AddListener((Action)(() => leftSpriteRenderer.sprite = MiraAssets.NextButton.LoadAsset()));
-
- leftButton.OnClick = new Button.ButtonClickedEvent();
- leftButton.OnClick.AddListener((Action)(() => previousPage(tab)));
-
- var rightButtonElement = Object.Instantiate(leftButtonElement, tab.transform);
- var rightSpriteRenderer = rightButtonElement.GetComponent();
- var rightButton = rightButtonElement.GetComponent();
-
- rightButtonElement.transform.localPosition = new Vector3(2.8f, -0.2f, -55);
- rightSpriteRenderer.sprite = MiraAssets.NextButton.LoadAsset();
- rightSpriteRenderer.flipX = false;
-
- rightButton.OnMouseOver = new UnityEvent();
- rightButton.OnMouseOver.AddListener((Action)(() => rightSpriteRenderer.sprite = MiraAssets.NextButtonActive.LoadAsset()));
- rightButton.OnMouseOut = new UnityEvent();
- rightButton.OnMouseOut.AddListener((Action)(() => rightSpriteRenderer.sprite = MiraAssets.NextButton.LoadAsset()));
-
- rightButton.OnClick = new Button.ButtonClickedEvent();
- rightButton.OnClick.AddListener((Action)(() => nextPage(tab)));
- }
-}
diff --git a/MiraAPI/Patches/Menu/MainMenuManagerPatches.cs b/MiraAPI/Patches/Menu/MainMenuManagerPatches.cs
index 4ac5b37..aff0906 100644
--- a/MiraAPI/Patches/Menu/MainMenuManagerPatches.cs
+++ b/MiraAPI/Patches/Menu/MainMenuManagerPatches.cs
@@ -2,7 +2,6 @@
using System.Collections;
using HarmonyLib;
using MiraAPI.LocalSettings;
-using MiraAPI.Utilities.Assets;
using Reactor.Utilities;
using UnityEngine;
@@ -23,10 +22,9 @@ public static class MainMenuManagerPatches
[HarmonyPostfix]
public static void AwakePostfix()
{
- var requiredVersion = new Version(2026, 6, 5);
+ var requiredVersion = new Version(2026, 9, 29);
var version = Version.Parse(Application.version);
NeedsDeepDestroy = version >= requiredVersion;
- AddressablesLoader.LoadAll();
Coroutines.Start(SetFps());
}
diff --git a/MiraAPI/Patches/Menu/NameplatesTabPatches.cs b/MiraAPI/Patches/Menu/NameplatesTabPatches.cs
deleted file mode 100644
index c105eb1..0000000
--- a/MiraAPI/Patches/Menu/NameplatesTabPatches.cs
+++ /dev/null
@@ -1,161 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Diagnostics.CodeAnalysis;
-using System.Linq;
-using AmongUs.Data;
-using HarmonyLib;
-using Innersloth.Assets;
-using MiraAPI.Utilities;
-using MiraAPI.Utilities.Assets;
-using Reactor.Utilities.Extensions;
-using TMPro;
-using UnityEngine;
-using Object = UnityEngine.Object;
-
-namespace MiraAPI.Patches.Menu;
-
-[HarmonyPatch(typeof(NameplatesTab))]
-public static class NameplatesTabPatches
-{
- [SuppressMessage("Style", "IDE0028:Collection initialization can be simplified", Justification = "Preview feature.")]
- private static readonly SortedList> SortedNameplates = new(new ControllableComparer(["vanilla"], [], StringComparer.InvariantCulture));
- private static int currentPage;
-
- internal static void AddRange(IEnumerable<(string Key, NamePlateData Visor)> data)
- {
- foreach (var (key, visor) in data)
- {
- if (!SortedNameplates.ContainsKey(key)) SortedNameplates.Add(key, []);
- SortedNameplates[key].Add(visor);
- }
- }
-
- private static void PreviousPage(NameplatesTab tab)
- {
- currentPage--;
- currentPage = currentPage < 0 ? SortedNameplates.Count - 1 : currentPage;
- GenerateHats(tab, currentPage);
- }
-
- private static void NextPage(NameplatesTab tab)
- {
- currentPage++;
- currentPage = currentPage > SortedNameplates.Count - 1 ? 0 : currentPage;
- GenerateHats(tab, currentPage);
- }
-
- [HarmonyPatch(nameof(NameplatesTab.OnEnable))]
- [HarmonyPrefix]
- public static bool OnEnablePrefix(NameplatesTab __instance)
- {
- if (!AddressablesLoader.AddressableNameplatesExist)
- {
- return true;
- }
-
- __instance.plateId = HatManager.Instance.GetNamePlateById(DataManager.Player.Customization.namePlate).ProdId;
-
- if (!SortedNameplates.ContainsKey("Vanilla")) AddRange(HatManager.Instance.GetUnlockedNamePlates().Select(x => ("Vanilla", x)));
-
- InventoryUtility.CreateNextBackButtons(__instance, PreviousPage, NextPage);
-
- GenerateHats(__instance, currentPage);
-
- return false;
- }
-
- [HarmonyPatch(typeof(NameplatesTab), nameof(NameplatesTab.Update))]
- [HarmonyPrefix]
-
- public static void UpdatePrefix(NameplatesTab __instance)
- {
- if (!AddressablesLoader.AddressableNameplatesExist)
- {
- return;
- }
-
- if (Input.GetKeyDown(KeyCode.LeftControl) || Input.GetKeyDown(KeyCode.RightControl) || Input.GetKeyDown(KeyCode.LeftArrow))
- {
- PreviousPage(__instance);
- }
- else if (Input.GetKeyDown(KeyCode.Tab) || Input.GetKeyDown(KeyCode.RightArrow))
- {
- NextPage(__instance);
- }
- }
-
- private static void GenerateHats(NameplatesTab __instance, int page)
- {
- foreach (var instanceColorChip in __instance.ColorChips) instanceColorChip.gameObject.Destroy();
- __instance.ColorChips.Clear();
- __instance.scroller.Inner.GetComponentsInChildren().Do(x => x.gameObject.DeepDestroy(false));
-
- var groupNameText = __instance.GetComponentInChildren(false);
-
- var hatIndex = 0;
-
- var (groupName, nameplates) = SortedNameplates.ToArray()[page];
- var text = Object.Instantiate(groupNameText, __instance.scroller.Inner);
- text.enabled = true;
- text.gameObject.transform.localScale = Vector3.one;
- text.GetComponent().Destroy();
- text.EnableStencilMasking();
- text.text = $"{groupName} ({currentPage + 1}/{SortedNameplates.Count})";
- text.alignment = TextAlignmentOptions.Center;
- text.fontSize = 5f;
- text.fontSizeMax = 5f;
- text.fontSizeMin = 0f;
- var xLerp = __instance.XRange.Lerp(0.5f);
- var yLerp = __instance.YStart - __instance.YOffset;
- text.transform.localPosition = new Vector3(xLerp, yLerp, -1f);
-
- hatIndex += 2;
- foreach (var visor in nameplates.OrderBy(HatManager.Instance.allNamePlates.IndexOf))
- {
- var hatXPosition = __instance.XRange.Lerp(hatIndex % __instance.NumPerRow / (__instance.NumPerRow - 1f));
-
- // ReSharper disable once PossibleLossOfFraction (Justification: Intended.)
- var hatYPosition = __instance.YStart - hatIndex / __instance.NumPerRow * __instance.YOffset;
- GenerateColorChip(__instance, new Vector2(hatXPosition, hatYPosition), visor);
- hatIndex += 1;
- }
-
- __instance.SetScrollerBounds();
- __instance.currentNameplateIsEquipped = true;
- }
-
- private static void GenerateColorChip(NameplatesTab __instance, Vector2 position, NamePlateData namePlate)
- {
- var colorChip = Object.Instantiate(__instance.ColorTabPrefab, __instance.scroller.Inner);
- colorChip.gameObject.name = namePlate.ProductId;
-
- if (ActiveInputManager.currentControlType == ActiveInputManager.InputType.Keyboard)
- {
- colorChip.Button.OnClick.AddListener((Action)__instance.ClickEquip);
- colorChip.Button.OnMouseOver.AddListener((Action)(() => __instance.SelectNameplate(namePlate)));
- colorChip.Button.OnMouseOut.AddListener(
- (Action)(() => __instance.SelectNameplate(
- HatManager.Instance.GetNamePlateById(DataManager.Player.Customization.NamePlate))));
- }
- else
- {
- colorChip.Button.OnClick.AddListener((Action)(() => __instance.SelectNameplate(namePlate)));
- }
-
- colorChip.Button.ClickMask = __instance.scroller.Hitbox;
- colorChip.ProductId = namePlate.ProdId;
-
- __instance.StartCoroutine(__instance.CoLoadAssetAsync(namePlate.GetAssetReference(), (Action?)LoadNameplate));
- colorChip.transform.localPosition = new Vector3(position.x, position.y, -1f);
- colorChip.Tag = namePlate;
- __instance.ColorChips.Add(colorChip);
- return;
-
- void LoadNameplate(NamePlateViewData viewData)
- {
- colorChip.transform.GetChild(1).GetComponent().sprite = viewData.Image;
-
- // (colorChip as NameplateChip).image.sprite = viewData?.Image;
- }
- }
-}
diff --git a/MiraAPI/Patches/Menu/SkinsTabPatches.cs b/MiraAPI/Patches/Menu/SkinsTabPatches.cs
deleted file mode 100644
index 08bfe8c..0000000
--- a/MiraAPI/Patches/Menu/SkinsTabPatches.cs
+++ /dev/null
@@ -1,155 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Collections.Immutable;
-using System.Diagnostics.CodeAnalysis;
-using System.Linq;
-using AmongUs.Data;
-using HarmonyLib;
-using MiraAPI.Utilities;
-using MiraAPI.Utilities.Assets;
-using Reactor.Utilities.Extensions;
-using TMPro;
-using UnityEngine;
-using Object = UnityEngine.Object;
-
-namespace MiraAPI.Patches.Menu;
-
-[HarmonyPatch(typeof(SkinsTab))]
-public static class SkinsTabPatches
-{
- private static SortedList> sortedSkins = [];
- private static int currentPage;
-
- private static void PreviousPage(SkinsTab tab)
- {
- currentPage--;
- currentPage = currentPage < 0 ? sortedSkins.Count - 1 : currentPage;
- GenerateHats(tab, currentPage);
- }
-
- private static void NextPage(SkinsTab tab)
- {
- currentPage++;
- currentPage = currentPage > sortedSkins.Count - 1 ? 0 : currentPage;
- GenerateHats(tab, currentPage);
- }
-
- [HarmonyPatch(nameof(SkinsTab.OnEnable))]
- [HarmonyPrefix]
- [SuppressMessage("Style", "IDE0028:Collection initialization can be simplified", Justification = "Preview feature.")]
- public static bool OnEnablePrefix(SkinsTab __instance)
- {
- if (!AddressablesLoader.AddressableSkinsExist)
- {
- return true;
- }
-
- __instance.skinId = HatManager.Instance.GetSkinById(DataManager.Player.Customization.Skin).ProdId;
- var allSkins = HatManager.Instance.GetUnlockedSkins().ToImmutableList();
-
- if (sortedSkins.Count == 0)
- {
- var comparer = new ControllableComparer(["vanilla"], [], StringComparer.InvariantCulture);
- sortedSkins = new SortedList>(comparer);
- foreach (var skin in allSkins)
- {
- if (!sortedSkins.ContainsKey(skin.StoreName)) sortedSkins[skin.StoreName] = [];
- sortedSkins[skin.StoreName].Add(skin);
- }
- }
-
- InventoryUtility.CreateNextBackButtons(__instance, PreviousPage, NextPage);
-
- GenerateHats(__instance, currentPage);
-
- return false;
- }
-
- [HarmonyPatch(typeof(SkinsTab), nameof(SkinsTab.Update))]
- [HarmonyPrefix]
-
- public static void UpdatePrefix(SkinsTab __instance)
- {
- if (!AddressablesLoader.AddressableSkinsExist)
- {
- return;
- }
-
- if (Input.GetKeyDown(KeyCode.LeftControl) || Input.GetKeyDown(KeyCode.RightControl) || Input.GetKeyDown(KeyCode.LeftArrow))
- {
- PreviousPage(__instance);
- }
- else if (Input.GetKeyDown(KeyCode.Tab) || Input.GetKeyDown(KeyCode.RightArrow))
- {
- NextPage(__instance);
- }
- }
-
- private static void GenerateHats(SkinsTab __instance, int page)
- {
- foreach (var instanceColorChip in __instance.ColorChips) instanceColorChip.gameObject.Destroy();
- __instance.ColorChips.Clear();
- __instance.scroller.Inner.GetComponentsInChildren().Do(x => x.gameObject.DeepDestroy(false));
-
- var groupNameText = __instance.GetComponentInChildren(false);
-
- var hatIndex = 0;
-
- var (groupName, skins) = sortedSkins.ToArray()[page];
- var text = Object.Instantiate(groupNameText, __instance.scroller.Inner);
- text.enabled = true;
- text.gameObject.transform.localScale = Vector3.one;
- text.GetComponent().Destroy();
- text.EnableStencilMasking();
- text.text = $"{groupName} ({currentPage + 1}/{sortedSkins.Count})";
- text.alignment = TextAlignmentOptions.Center;
- text.fontSize = 5f;
- text.fontSizeMax = 5f;
- text.fontSizeMin = 0f;
- var xLerp = __instance.XRange.Lerp(0.5f);
- var yLerp = __instance.YStart - __instance.YOffset;
- text.transform.localPosition = new Vector3(xLerp, yLerp, -1f);
-
- hatIndex += 5;
- foreach (var skin in skins.OrderBy(HatManager.Instance.allSkins.IndexOf))
- {
- var hatXPosition = __instance.XRange.Lerp(hatIndex % __instance.NumPerRow / (__instance.NumPerRow - 1f));
-
- // ReSharper disable once PossibleLossOfFraction (Justification: Intended.)
- var hatYPosition = __instance.YStart - hatIndex / __instance.NumPerRow * __instance.YOffset;
- GenerateColorChip(__instance, new Vector2(hatXPosition, hatYPosition), skin);
- hatIndex += 1;
- }
-
- __instance.SetScrollerBounds();
- __instance.currentSkinIsEquipped = true;
- }
-
- private static void GenerateColorChip(SkinsTab __instance, Vector2 position, SkinData skin)
- {
- var colorChip = Object.Instantiate(__instance.ColorTabPrefab, __instance.scroller.Inner);
- colorChip.gameObject.name = skin.ProductId;
- if (ActiveInputManager.currentControlType == ActiveInputManager.InputType.Keyboard)
- {
- colorChip.Button.OnClick.AddListener((Action)__instance.ClickEquip);
- colorChip.Button.OnMouseOver.AddListener((Action)(() => __instance.SelectSkin(skin)));
- colorChip.Button.OnMouseOut.AddListener(
- (Action)(() =>
- __instance.SelectSkin(HatManager.Instance.GetSkinById(DataManager.Player.Customization.Skin))));
- }
- else
- {
- colorChip.Button.OnClick.AddListener((Action)(() => __instance.SelectSkin(skin)));
- }
-
- colorChip.Button.ClickMask = __instance.scroller.Hitbox;
- colorChip.ProductId = skin.ProductId;
- colorChip.SelectionHighlight.gameObject.SetActive(false);
- __instance.UpdateMaterials(colorChip.Inner.FrontLayer, skin);
- skin.SetPreview(colorChip.Inner.FrontLayer, __instance.HasLocalPlayer() ? PlayerControl.LocalPlayer.Data.DefaultOutfit.ColorId : DataManager.Player.Customization.Color);
- colorChip.transform.localPosition = new Vector3(position.x, position.y, -1f);
- colorChip.Inner.transform.localPosition = skin.ChipOffset + new Vector2(0f, -0.3f);
- colorChip.Tag = skin;
- __instance.ColorChips.Add(colorChip);
- }
-}
diff --git a/MiraAPI/Patches/Menu/VisorsTabPatches.cs b/MiraAPI/Patches/Menu/VisorsTabPatches.cs
deleted file mode 100644
index cc37c28..0000000
--- a/MiraAPI/Patches/Menu/VisorsTabPatches.cs
+++ /dev/null
@@ -1,154 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Diagnostics.CodeAnalysis;
-using System.Linq;
-using AmongUs.Data;
-using HarmonyLib;
-using MiraAPI.Utilities;
-using MiraAPI.Utilities.Assets;
-using Reactor.Utilities.Extensions;
-using TMPro;
-using UnityEngine;
-using Object = UnityEngine.Object;
-
-namespace MiraAPI.Patches.Menu;
-
-[HarmonyPatch(typeof(VisorsTab))]
-public static class VisorsTabPatches
-{
- [SuppressMessage("Style", "IDE0028:Collection initialization can be simplified", Justification = "Preview feature.")]
- private static readonly SortedList> SortedVisors = new(new ControllableComparer(["vanilla"], [], StringComparer.InvariantCulture));
- private static int currentPage;
-
- internal static void AddRange(IEnumerable<(string Key, VisorData Visor)> data)
- {
- foreach (var (key, visor) in data)
- {
- if (!SortedVisors.ContainsKey(key)) SortedVisors.Add(key, []);
- SortedVisors[key].Add(visor);
- }
- }
-
- private static void PreviousPage(VisorsTab tab)
- {
- currentPage--;
- currentPage = currentPage < 0 ? SortedVisors.Count - 1 : currentPage;
- GenerateHats(tab, currentPage);
- }
-
- private static void NextPage(VisorsTab tab)
- {
- currentPage++;
- currentPage = currentPage > SortedVisors.Count - 1 ? 0 : currentPage;
- GenerateHats(tab, currentPage);
- }
-
- [HarmonyPatch(nameof(VisorsTab.OnEnable))]
- [HarmonyPrefix]
- public static bool OnEnablePrefix(VisorsTab __instance)
- {
- if (!AddressablesLoader.AddressableVisorsExist)
- {
- return true;
- }
-
- __instance.visorId = HatManager.Instance.GetVisorById(DataManager.Player.Customization.Visor).ProdId;
-
- if (!SortedVisors.ContainsKey("Vanilla")) AddRange(HatManager.Instance.GetUnlockedVisors().Select(x => ("Vanilla", x)));
-
- InventoryUtility.CreateNextBackButtons(__instance, PreviousPage, NextPage);
-
- GenerateHats(__instance, currentPage);
-
- return false;
- }
-
- [HarmonyPatch(typeof(VisorsTab), nameof(VisorsTab.Update))]
- [HarmonyPrefix]
-
- public static void UpdatePrefix(VisorsTab __instance)
- {
- if (!AddressablesLoader.AddressableVisorsExist)
- {
- return;
- }
-
- if (Input.GetKeyDown(KeyCode.LeftControl) || Input.GetKeyDown(KeyCode.RightControl) || Input.GetKeyDown(KeyCode.LeftArrow))
- {
- PreviousPage(__instance);
- }
- else if (Input.GetKeyDown(KeyCode.Tab) || Input.GetKeyDown(KeyCode.RightArrow))
- {
- NextPage(__instance);
- }
- }
-
- private static void GenerateHats(VisorsTab __instance, int page)
- {
- foreach (var instanceColorChip in __instance.ColorChips) instanceColorChip.gameObject.Destroy();
- __instance.ColorChips.Clear();
- __instance.scroller.Inner.GetComponentsInChildren().Do(x => x.gameObject.DeepDestroy(false));
-
- var groupNameText = __instance.GetComponentInChildren(false);
-
- var hatIndex = 0;
-
- var (groupName, visors) = SortedVisors.ToArray()[page];
- var text = Object.Instantiate(groupNameText, __instance.scroller.Inner);
- text.enabled = true;
- text.gameObject.transform.localScale = Vector3.one;
- text.GetComponent().Destroy();
- text.EnableStencilMasking();
- text.text = $"{groupName} ({currentPage + 1}/{SortedVisors.Count})";
- text.alignment = TextAlignmentOptions.Center;
- text.fontSize = 5f;
- text.fontSizeMax = 5f;
- text.fontSizeMin = 0f;
- var xLerp = __instance.XRange.Lerp(0.5f);
- var yLerp = __instance.YStart - __instance.YOffset;
- text.transform.localPosition = new Vector3(xLerp, yLerp, -1f);
-
- hatIndex += 5;
- foreach (var visor in visors.OrderBy(HatManager.Instance.allVisors.IndexOf))
- {
- var hatXPosition = __instance.XRange.Lerp(hatIndex % __instance.NumPerRow / (__instance.NumPerRow - 1f));
-
- // ReSharper disable once PossibleLossOfFraction (Justification: Intended.)
- var hatYPosition = __instance.YStart - hatIndex / __instance.NumPerRow * __instance.YOffset;
- GenerateColorChip(__instance, new Vector2(hatXPosition, hatYPosition), visor);
- hatIndex += 1;
- }
-
- __instance.SetScrollerBounds();
- __instance.currentVisorIsEquipped = true;
- }
-
- private static void GenerateColorChip(VisorsTab __instance, Vector2 position, VisorData visor)
- {
- var colorChip = Object.Instantiate(__instance.ColorTabPrefab, __instance.scroller.Inner);
- colorChip.gameObject.name = visor.ProductId;
-
- if (ActiveInputManager.currentControlType == ActiveInputManager.InputType.Keyboard)
- {
- colorChip.Button.OnClick.AddListener((Action)__instance.ClickEquip);
- colorChip.Button.OnMouseOver.AddListener((Action)(() => __instance.SelectVisor(visor)));
- colorChip.Button.OnMouseOut.AddListener(
- (Action)(() =>
- __instance.SelectVisor(HatManager.Instance.GetVisorById(DataManager.Player.Customization.Visor))));
- }
- else
- {
- colorChip.Button.OnClick.AddListener((Action)(() => __instance.SelectVisor(visor)));
- }
-
- colorChip.Button.ClickMask = __instance.scroller.Hitbox;
- colorChip.ProductId = visor.ProductId;
- colorChip.SelectionHighlight.gameObject.SetActive(false);
- __instance.UpdateMaterials(colorChip.Inner.FrontLayer, visor);
- visor.SetPreview(colorChip.Inner.FrontLayer, __instance.HasLocalPlayer() ? PlayerControl.LocalPlayer.Data.DefaultOutfit.ColorId : DataManager.Player.Customization.Color);
- colorChip.transform.localPosition = new Vector3(position.x, position.y, -1f);
- colorChip.Inner.transform.localPosition = visor.ChipOffset + new Vector2(0f, -0.3f);
- colorChip.Tag = visor;
- __instance.ColorChips.Add(colorChip);
- }
-}
diff --git a/MiraAPI/Utilities/Assets/AddressablesLoader.cs b/MiraAPI/Utilities/Assets/AddressablesLoader.cs
index ec02972..980b6f7 100644
--- a/MiraAPI/Utilities/Assets/AddressablesLoader.cs
+++ b/MiraAPI/Utilities/Assets/AddressablesLoader.cs
@@ -1,4 +1,5 @@
-using System.Collections;
+using System;
+using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.CompilerServices;
@@ -13,6 +14,7 @@ namespace MiraAPI.Utilities.Assets;
///
/// The component for loading Addressables, and cosmetics.
///
+[Obsolete("This system has been deprecated in favour of CorsacCosmetics. This will be removed in a future version.", true)]
public static class AddressablesLoader
{
private static readonly List<(string Location, string ProviderSuffix)> CatalogLocations = [];
From 01b172d73ec9d2a75de455b8b739502493238cdd Mon Sep 17 00:00:00 2001
From: Az <56699741+AlchlcDvl@users.noreply.github.com>
Date: Sun, 11 Oct 2026 12:05:25 -0400
Subject: [PATCH 07/10] remove more code, actually
and also fix build error
---
.../Utilities/Assets/AddressablesLoader.cs | 186 ++----------------
1 file changed, 12 insertions(+), 174 deletions(-)
diff --git a/MiraAPI/Utilities/Assets/AddressablesLoader.cs b/MiraAPI/Utilities/Assets/AddressablesLoader.cs
index 980b6f7..fee0a72 100644
--- a/MiraAPI/Utilities/Assets/AddressablesLoader.cs
+++ b/MiraAPI/Utilities/Assets/AddressablesLoader.cs
@@ -1,13 +1,5 @@
using System;
-using System.Collections;
-using System.Collections.Generic;
-using System.Linq;
-using System.Runtime.CompilerServices;
-using Il2CppInterop.Runtime.Attributes;
-using MiraAPI.Patches.Menu;
-using Reactor.Utilities;
-using UnityEngine.AddressableAssets;
-using UnityEngine.ResourceManagement.AsyncOperations;
+using System.Diagnostics.CodeAnalysis;
namespace MiraAPI.Utilities.Assets;
@@ -15,47 +7,33 @@ namespace MiraAPI.Utilities.Assets;
/// The component for loading Addressables, and cosmetics.
///
[Obsolete("This system has been deprecated in favour of CorsacCosmetics. This will be removed in a future version.", true)]
+[SuppressMessage("Style", "IDE0060:Remove unused parameter", Justification = "Part of obsolete code.")]
public static class AddressablesLoader
{
- private static readonly List<(string Location, string ProviderSuffix)> CatalogLocations = [];
- private static readonly List LoadedLocations = [];
-
- private static readonly List RegisteredHatKeys = [];
- private static readonly List<(string, string)> RegisteredVisorKeys = [];
- private static readonly List<(string, string)> RegisteredNameplateKeys = [];
- private static readonly List RegisteredSkinKeys = [];
-
- private static bool _isInitialized;
- private static bool _addressableHatsExist;
- private static bool _addressableVisorsExist;
- private static bool _addressableNameplatesExist;
- private static bool _addressableSkinsExist;
- private static bool _catalogsExist;
-
///
/// Gets a value indicating whether hats have been loaded by the addressables system.
///
- public static bool AddressableHatsExist => _addressableHatsExist;
+ public static bool AddressableHatsExist => false;
///
/// Gets a value indicating whether visors have been loaded by the addressables system.
///
- public static bool AddressableVisorsExist => _addressableVisorsExist;
+ public static bool AddressableVisorsExist => false;
///
/// Gets a value indicating whether nameplates have been loaded by the addressables system.
///
- public static bool AddressableNameplatesExist => _addressableNameplatesExist;
+ public static bool AddressableNameplatesExist => false;
///
/// Gets a value indicating whether skins have been loaded by the addressables system.
///
- public static bool AddressableSkinsExist => _addressableSkinsExist;
+ public static bool AddressableSkinsExist => false;
///
/// Gets a value indicating whether catalogs have been loaded by the addressables system.
///
- public static bool CatalogsExist => _catalogsExist;
+ public static bool CatalogsExist => false;
///
/// Registers a specific addressables package to load asynchronously at the start of the game, when possible.
@@ -64,7 +42,7 @@ public static class AddressablesLoader
/// The suffix of the provider for an addressables package.
public static void RegisterCatalog(string location, string providerSuffix = "")
{
- RegisterCosmetic((location, providerSuffix), CatalogLocations, "catalog", ref _catalogsExist);
+ Warning("The addressables system has been deprecated. None of the registered assets will be added.");
}
///
@@ -73,7 +51,7 @@ public static class AddressablesLoader
/// The key/label/group for a List .
public static void RegisterHats(string addressablesKey)
{
- RegisterCosmetic(addressablesKey, RegisteredHatKeys, "hat", ref _addressableHatsExist);
+ Warning("The addressables system has been deprecated. None of the registered assets will be added.");
}
///
@@ -82,7 +60,7 @@ public static class AddressablesLoader
/// The key/label/group for a List .
public static void RegisterSkins(string addressablesKey)
{
- RegisterCosmetic(addressablesKey, RegisteredSkinKeys, "skin", ref _addressableSkinsExist);
+ Warning("The addressables system has been deprecated. None of the registered assets will be added.");
}
///
@@ -92,7 +70,7 @@ public static class AddressablesLoader
/// /// The title of the group for visors.
public static void RegisterNameplates(string addressablesKey, string groupTitle)
{
- RegisterCosmetic((addressablesKey, groupTitle), RegisteredNameplateKeys, "nameplate", ref _addressableNameplatesExist);
+ Warning("The addressables system has been deprecated. None of the registered assets will be added.");
}
///
@@ -102,146 +80,6 @@ public static class AddressablesLoader
/// The title of the group for visors.
public static void RegisterVisors(string addressablesKey, string groupTitle)
{
- RegisterCosmetic((addressablesKey, groupTitle), RegisteredVisorKeys, "visor", ref _addressableVisorsExist);
- }
-
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- private static void RegisterCosmetic(T value, List values, string type, ref bool flag)
- {
- if (_isInitialized)
- {
- Error($"AddressablesLoader has already been initialized, cannot register more keys for {type}s.");
- return;
- }
-
- flag = true;
- values.Add(value);
- }
-
- internal static void LoadAll()
- {
- if (_isInitialized)
- {
- Error("AddressablesLoader has already been initialized.");
- return;
- }
-
- _isInitialized = true;
- foreach (var (location, providerSuffix) in CatalogLocations)
- {
- Coroutines.Start(CoLoadAddressables(location, providerSuffix));
- }
-
- Coroutines.Start(LoadCosmetics());
- }
-
- internal static IEnumerator CoLoadAddressables(string location, string suffix = "")
- {
- while (!AmongUsClient.Instance) yield return null;
-
- // Load the local/remote content catalog
- var catalogOperation = Addressables.LoadContentCatalog(location, suffix);
- yield return catalogOperation;
-
- // Check for errors
- if (catalogOperation.Status != AsyncOperationStatus.Succeeded)
- {
- Error($"Failed to load catalog {location}.");
- }
-
- Info($"Loaded addressables {location}.");
- LoadedLocations.Add(location);
- }
-
- [HideFromIl2Cpp]
- internal static IEnumerator LoadCosmetics()
- {
- while (!AmongUsClient.Instance || CatalogLocations.Select(x => x.Location).Any(x => !LoadedLocations.Contains(x))) yield return null;
-
- var hatBehaviours = DiscoverData(RegisteredHatKeys);
- hatBehaviours = [.. hatBehaviours.OrderBy(x => x.StoreName)];
- var skinBehaviours = DiscoverData(RegisteredSkinKeys);
- skinBehaviours = [.. skinBehaviours.OrderBy(x => x.StoreName)];
- var namePlateBehaviours = DiscoverAndReportData(RegisteredNameplateKeys);
- namePlateBehaviours = [.. namePlateBehaviours.OrderBy(x => x.Category)];
- var visorBehaviours = DiscoverAndReportData(RegisteredVisorKeys);
- visorBehaviours = [.. visorBehaviours.OrderBy(x => x.Category)];
-
- var hatData = new List();
- hatData.AddRange(HatManager.Instance.allHats);
- hatData.ForEach(x => x.StoreName = "Vanilla");
- HatManager.Instance.allHats = PrepareArray(hatData, hatBehaviours);
-
- var skinData = new List();
- skinData.AddRange(HatManager.Instance.allSkins);
- skinData.ForEach(x => x.StoreName = "Vanilla");
- HatManager.Instance.allSkins = PrepareArray(skinData, skinBehaviours);
-
- var visorData = new List();
- visorData.AddRange(HatManager.Instance.allVisors);
- VisorsTabPatches.AddRange(visorBehaviours);
- HatManager.Instance.allVisors = PrepareArray(visorData, [.. visorBehaviours.Select(x => x.Data)]);
-
- var namePlateData = new List();
- namePlateData.AddRange(HatManager.Instance.allNamePlates);
- NameplatesTabPatches.AddRange(namePlateBehaviours);
- HatManager.Instance.allNamePlates = PrepareArray(namePlateData, [.. namePlateBehaviours.Select(x => x.Data)]);
- }
-
- private static T[] PrepareArray(List data, List behaviours)
- where T : CosmeticData
- {
- var count = data.Count;
- for (var i = 0; i < behaviours.Count; i++)
- {
- behaviours[i].displayOrder = count + i;
- data.Add(behaviours[i]);
- }
-
- return [.. data];
- }
-
- private static List DiscoverData(List tags)
- {
- var behaviours = new List();
-
- foreach (var tag in tags)
- {
- try
- {
- var allLocations = Addressables.LoadResourceLocationsAsync(tag).WaitForCompletion();
- var assets = Addressables.LoadAssetsAsync(allLocations, null, false).WaitForCompletion();
- var array = new CppCollections.List(assets.Pointer);
- behaviours.AddRange(array.ToArray());
- }
- catch
- {
- Error($"Failed to find tag {tag}");
- }
- }
-
- return behaviours;
- }
-
- private static List<(string Category, T Data)> DiscoverAndReportData(List<(string Tag, string Category)> tags)
- {
- var behaviours = new List<(string, T)>();
-
- foreach (var tag in tags)
- {
- try
- {
- var allLocations = Addressables.LoadResourceLocationsAsync(tag.Tag).WaitForCompletion();
- var assets = Addressables.LoadAssetsAsync(allLocations, null, false).WaitForCompletion();
- var array = new CppCollections.List(assets.Pointer);
- behaviours.AddRange(array.ToArray().Select(x => (tag.Category, x)));
- }
- catch
- {
- Error($"Failed to find tag {tag}");
- }
- }
-
- return behaviours;
+ Warning("The addressables system has been deprecated. None of the registered assets will be added.");
}
}
From d5b08a7145e57e103beea91b89b9da6e6a55c007 Mon Sep 17 00:00:00 2001
From: Az <56699741+AlchlcDvl@users.noreply.github.com>
Date: Sun, 11 Oct 2026 12:25:13 -0400
Subject: [PATCH 08/10] better audio loading
---
MiraAPI/Utilities/Assets/AudioTools.cs | 72 ++++++++++++++++++--------
1 file changed, 50 insertions(+), 22 deletions(-)
diff --git a/MiraAPI/Utilities/Assets/AudioTools.cs b/MiraAPI/Utilities/Assets/AudioTools.cs
index abb6bc1..075b65c 100644
--- a/MiraAPI/Utilities/Assets/AudioTools.cs
+++ b/MiraAPI/Utilities/Assets/AudioTools.cs
@@ -2,6 +2,7 @@ using System;
using System.IO;
using System.Reflection;
using System.Resources;
+using System.Runtime.InteropServices;
using System.Text;
using UnityEngine;
@@ -96,34 +97,61 @@ public static class AudioTools
}
// This is somewhat magic to me, I just copied it from elsewhere.
+ // Could have been written better, so here - Az
private static float[] ConvertPcmToFloat(byte[] pcmData, int bitsPerSample)
{
var sampleCount = pcmData.Length / (bitsPerSample / 8);
var floatData = new float[sampleCount];
- for (var i = 0; i < sampleCount; i++)
- {
- var byteIndex = i * (bitsPerSample / 8);
+ ReadOnlySpan source = pcmData;
+ Span destination = floatData;
- switch (bitsPerSample)
- {
- case 8:
- floatData[i] = (pcmData[byteIndex] - 128) / 128f; // 8-bit PCM is unsigned
- break;
- case 16:
- floatData[i] = BitConverter.ToInt16(pcmData, byteIndex) / 32768f;
- break;
- case 24:
- var sample24 = pcmData[byteIndex] | (pcmData[byteIndex + 1] << 8) | (pcmData[byteIndex + 2] << 16);
- if (sample24 > 0x7FFFFF) sample24 -= 0x1000000; // Convert from unsigned to signed
- floatData[i] = sample24 / 8388608f;
- break;
- case 32:
- floatData[i] = BitConverter.ToInt32(pcmData, byteIndex) / 2147483648f;
- break;
- default:
- throw new NotSupportedException($"Unsupported bit depth: {bitsPerSample}");
- }
+ switch (bitsPerSample)
+ {
+ case 8:
+ for (var i = 0; i < sampleCount; i++)
+ {
+ destination[i] = (source[i] - 128) / 128f; // 8-bit PCM is unsigned
+ }
+
+ break;
+
+ case 16:
+ var shortSource = MemoryMarshal.Cast(source);
+
+ for (var i = 0; i < sampleCount; i++)
+ {
+ destination[i] = shortSource[i] / 32768f;
+ }
+
+ break;
+
+ case 24:
+ for (int i = 0, byteIndex = 0; i < sampleCount; i++, byteIndex += 3)
+ {
+ var sample24 = source[byteIndex] | (source[byteIndex + 1] << 8) | (source[byteIndex + 2] << 16);
+
+ // Convert from unsigned to signed
+ if (sample24 > 0x7FFFFF)
+ sample24 -= 0x1000000;
+
+ destination[i] = sample24 / 8388608f;
+ }
+
+ break;
+
+ case 32:
+ var intSource = MemoryMarshal.Cast(source);
+
+ for (var i = 0; i < sampleCount; i++)
+ {
+ destination[i] = intSource[i] / 2147483648f;
+ }
+
+ break;
+
+ default:
+ throw new NotSupportedException($"Unsupported bit depth: {bitsPerSample}");
}
return floatData;
From 398286794368027d681eb86327a54b8b237b0554 Mon Sep 17 00:00:00 2001
From: Az <56699741+AlchlcDvl@users.noreply.github.com>
Date: Sun, 11 Oct 2026 12:29:32 -0400
Subject: [PATCH 09/10] cache il2cpp type
---
MiraAPI/Utilities/Assets/LoadableBundleSubAssetHolder.cs | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/MiraAPI/Utilities/Assets/LoadableBundleSubAssetHolder.cs b/MiraAPI/Utilities/Assets/LoadableBundleSubAssetHolder.cs
index 7925607..1507c42 100644
--- a/MiraAPI/Utilities/Assets/LoadableBundleSubAssetHolder.cs
+++ b/MiraAPI/Utilities/Assets/LoadableBundleSubAssetHolder.cs
@@ -38,10 +38,11 @@ public class LoadableBundleSubAssetHolder(string[] names, AssetBundle bundle)
return;
var newSprites = new List();
+ var type = Il2CppType.From(typeof(Sprite));
foreach (var name in names)
{
- var loadedAssets = bundle.LoadAssetWithSubAssets(name, Il2CppType.From(typeof(Sprite)))
+ var loadedAssets = bundle.LoadAssetWithSubAssets(name, type)
?? throw new InvalidOperationException($"INVALID ASSETS: {name}");
foreach (var obj in loadedAssets)
From 50312e31c278d069ac87eae514c536dd4e2475bf Mon Sep 17 00:00:00 2001
From: Az <56699741+AlchlcDvl@users.noreply.github.com>
Date: Wed, 14 Oct 2026 00:48:08 -0400
Subject: [PATCH 10/10] resolve and suppress warnings
---
.editorconfig | 12 ++
MiraAPI.Example/.editorconfig | 4 +
MiraAPI.Example/Resources/Locale/en_US.xml | 12 +-
MiraAPI/GameModes/HideAndSeekMode.cs | 2 -
.../OptionTypes/ModdedPlayerOption.cs | 2 +-
MiraAPI/Hud/CustomPaginableMenu.cs | 1 -
MiraAPI/MiraApiPlugin.cs | 8 +-
MiraAPI/Patches/.editorconfig | 4 +-
.../Patches/Options/GameOptionsMenuPatch.cs | 6 +-
MiraAPI/Patches/Options/SettingPatches.cs | 4 +-
MiraAPI/Patches/RoleGuidePatches.cs | 126 +++++++-----------
MiraAPI/Patches/Stubs/RoleBehaviourStubs.cs | 4 +-
MiraAPI/Presets/SavePresetPopup.cs | 1 +
MiraAPI/Roles/ICustomRole.cs | 9 +-
MiraAPI/Translation/MiraLocaleManager.cs | 2 -
MiraAPI/Utilities/ControllableComparer.cs | 2 -
MiraAPI/Utilities/Helpers.cs | 13 +-
17 files changed, 106 insertions(+), 106 deletions(-)
create mode 100644 MiraAPI.Example/.editorconfig
diff --git a/.editorconfig b/.editorconfig
index af9feb4..2f48813 100644
--- a/.editorconfig
+++ b/.editorconfig
@@ -86,3 +86,15 @@ dotnet_diagnostic.SA1133.severity = none
# IDE0001: Simplify Names
dotnet_diagnostic.IDE0001.severity = warning
+
+# IDE0079: Remove unnecessary suppression
+dotnet_diagnostic.IDE0079.severity = none
+
+# S3903: Types should be defined in named namespaces
+dotnet_diagnostic.S3903.severity = none
+
+# IDE0045: Convert to conditional expression
+dotnet_diagnostic.IDE0045.severity = none
+
+# IDE0046: Convert to conditional expression
+dotnet_diagnostic.IDE0046.severity = none
diff --git a/MiraAPI.Example/.editorconfig b/MiraAPI.Example/.editorconfig
new file mode 100644
index 0000000..171e612
--- /dev/null
+++ b/MiraAPI.Example/.editorconfig
@@ -0,0 +1,4 @@
+[*.{cs,vb}]
+
+# SA1602: Enumeration items should be documented.
+dotnet_diagnostic.SA1602.severity = none
diff --git a/MiraAPI.Example/Resources/Locale/en_US.xml b/MiraAPI.Example/Resources/Locale/en_US.xml
index e370dc3..56f74c8 100644
--- a/MiraAPI.Example/Resources/Locale/en_US.xml
+++ b/MiraAPI.Example/Resources/Locale/en_US.xml
@@ -16,11 +16,11 @@
Your votes have double the power.
You get one extra vote in the meeting!
The Mayor is a Crewmate role that gets two votes in the meeting, instead of the singular vote other Crewmates get.
- Chamelon
- Become one with the environment.
- Fade out of everyone's vision by not moving.
- Stay invisible while not moving.
- The Chamelon is a Crewmate role that slowly becomes invisible while standing still.
+ Chameleon
+ Become one with the environment.
+ Fade out of everyone's vision by not moving.
+ Stay invisible while not moving.
+ The Chameleon is a Crewmate role that slowly becomes invisible while standing still.
Outcast Killer
Kill everyone else.
Be the last outcast standing.
@@ -73,7 +73,7 @@ Eliminate every other faction.
Example Bool 2
Slider
Example Number
- Example Multplier
+ Example Multiplier
Example Enum
Example Button
Outcast Killer Wins!
diff --git a/MiraAPI/GameModes/HideAndSeekMode.cs b/MiraAPI/GameModes/HideAndSeekMode.cs
index 316c3cf..ec99ce9 100644
--- a/MiraAPI/GameModes/HideAndSeekMode.cs
+++ b/MiraAPI/GameModes/HideAndSeekMode.cs
@@ -1,7 +1,6 @@
using System;
using System.Collections;
using System.Collections.Generic;
-using System.Diagnostics.CodeAnalysis;
using System.Globalization;
using System.Linq;
using AmongUs.Data;
@@ -462,7 +461,6 @@ public class HideAndSeekMode : AbstractGameMode
}
///
- [SuppressMessage("Style", "IDE0046:Convert to conditional expression", Justification = "Warning cascades into forcing the entire tree to be ternary operators.")]
public override PlayerBodyTypes GetBodyType(PlayerControl player)
{
if (player == null || player.Data == null || player.Data.Role == null)
diff --git a/MiraAPI/GameOptions/OptionTypes/ModdedPlayerOption.cs b/MiraAPI/GameOptions/OptionTypes/ModdedPlayerOption.cs
index 646de56..40cf0f8 100644
--- a/MiraAPI/GameOptions/OptionTypes/ModdedPlayerOption.cs
+++ b/MiraAPI/GameOptions/OptionTypes/ModdedPlayerOption.cs
@@ -43,7 +43,7 @@ public class ModdedPlayerOption : ModdedOption
data.Title = StringName;
data.Type = global::OptionTypes.Player;
- Values = new();
+ Values = [];
AllowNone = allowNone;
Value = DefaultValue;
}
diff --git a/MiraAPI/Hud/CustomPaginableMenu.cs b/MiraAPI/Hud/CustomPaginableMenu.cs
index 27f7819..f24ccee 100644
--- a/MiraAPI/Hud/CustomPaginableMenu.cs
+++ b/MiraAPI/Hud/CustomPaginableMenu.cs
@@ -100,7 +100,6 @@ public abstract class CustomPaginableMenu : CustomPhoneMenu GetFilteredEntries()
{
var query = NormalizeForSearch(searchText);
diff --git a/MiraAPI/MiraApiPlugin.cs b/MiraAPI/MiraApiPlugin.cs
index 4da8968..a07c36d 100644
--- a/MiraAPI/MiraApiPlugin.cs
+++ b/MiraAPI/MiraApiPlugin.cs
@@ -64,11 +64,9 @@ public partial class MiraApiPlugin : BasePlugin, IMiraPlugin
private static MiraPluginManager? PluginManager { get; set; }
internal Harmony Harmony { get; } = new(Id);
- public static ConfigEntry WikiSortingGroup { get; private set; }
-
- public static ConfigEntry WikiSortingMethod { get; private set; }
-
- public static ConfigEntry WikiSortingFilter { get; private set; }
+ internal static ConfigEntry WikiSortingGroup { get; private set; }
+ internal static ConfigEntry WikiSortingMethod { get; private set; }
+ internal static ConfigEntry WikiSortingFilter { get; private set; }
///
public override void Load()
diff --git a/MiraAPI/Patches/.editorconfig b/MiraAPI/Patches/.editorconfig
index 2622fc7..a019ed9 100644
--- a/MiraAPI/Patches/.editorconfig
+++ b/MiraAPI/Patches/.editorconfig
@@ -12,5 +12,5 @@ dotnet_diagnostic.SA1611.severity = none
# SA1615: Element return value should be documented.
dotnet_diagnostic.SA1615.severity = none
-# S125: Sections of code should not be commented out.
-dotnet_diagnostic.S125.severity = none
\ No newline at end of file
+# SA1602: Enumeration items should be documented.
+dotnet_diagnostic.SA1602.severity = none
\ No newline at end of file
diff --git a/MiraAPI/Patches/Options/GameOptionsMenuPatch.cs b/MiraAPI/Patches/Options/GameOptionsMenuPatch.cs
index e65f4c3..7e2b312 100644
--- a/MiraAPI/Patches/Options/GameOptionsMenuPatch.cs
+++ b/MiraAPI/Patches/Options/GameOptionsMenuPatch.cs
@@ -25,9 +25,9 @@ namespace MiraAPI.Patches.Options;
[HarmonyPatch(typeof(GameOptionsMenu))]
internal static class GameOptionsMenuPatch
{
- private static readonly List VanillaHeaders = new();
- private static readonly List VanillaOptions = new();
- private static readonly List MainOptions = new();
+ private static readonly List VanillaHeaders = [];
+ private static readonly List VanillaOptions = [];
+ private static readonly List MainOptions = [];
private static readonly Dictionary> GameModeGroups = [];
private static readonly Dictionary> GameModeOptions = [];
private static readonly Dictionary> GameModeHeaders = [];
diff --git a/MiraAPI/Patches/Options/SettingPatches.cs b/MiraAPI/Patches/Options/SettingPatches.cs
index 8fd6581..59b956c 100644
--- a/MiraAPI/Patches/Options/SettingPatches.cs
+++ b/MiraAPI/Patches/Options/SettingPatches.cs
@@ -1,5 +1,4 @@
-using System.Diagnostics.CodeAnalysis;
-using System.Globalization;
+using System.Globalization;
using System.Linq;
using HarmonyLib;
using MiraAPI.GameOptions;
@@ -24,7 +23,6 @@ public static class SettingPatches
/// to skip original method.
[HarmonyPrefix]
[HarmonyPatch(typeof(FloatGameSetting), nameof(FloatGameSetting.GetValueString))]
- [SuppressMessage("Style", "IDE0045:Convert to conditional expression", Justification = "Warning cascades into forcing the entire tree to be ternary operators.")]
public static bool ValueStringPatch(
FloatGameSetting __instance,
ref string __result,
diff --git a/MiraAPI/Patches/RoleGuidePatches.cs b/MiraAPI/Patches/RoleGuidePatches.cs
index 92080e8..508b3f7 100644
--- a/MiraAPI/Patches/RoleGuidePatches.cs
+++ b/MiraAPI/Patches/RoleGuidePatches.cs
@@ -33,20 +33,13 @@ public static class RoleGuidePatches
private static readonly List RoleEntries = [];
private static readonly List ModifierEntries = [];
- public static GameObject SearchComponentContainer;
- public static PassiveButton SearchIconButton;
+ private static GameObject searchComponentContainer;
private static SpriteRenderer _searchIconIdle;
private static SpriteRenderer _searchIconHover;
- public static TextMeshPro OrderSortingTmp;
- public static PassiveButton SearchSortingOrderButton;
private static SpriteRenderer _searchSortingOrderIdle;
private static SpriteRenderer _searchSortingOrderHover;
- public static TextMeshPro GroupSortingTmp;
- public static PassiveButton SearchSortingGroupButton;
private static SpriteRenderer _searchSortingGroupIdle;
private static SpriteRenderer _searchSortingGroupHover;
- public static TextMeshPro FilterSortingTmp;
- public static PassiveButton SearchSortingFilterButton;
private static SpriteRenderer _searchSortingFilterIdle;
private static SpriteRenderer _searchSortingFilterHover;
private static Scroller _rolesScroller;
@@ -153,10 +146,6 @@ public static class RoleGuidePatches
_advancedInfoTabScroller = null!;
_currentAdvancedTabObject = null!;
_loadingSpinner = null;
- SearchIconButton = null!;
- SearchSortingOrderButton = null!;
- SearchSortingGroupButton = null!;
- SearchSortingFilterButton = null!;
_searchIconIdle = null!;
_searchIconHover = null!;
_searchSortingOrderIdle = null!;
@@ -260,6 +249,7 @@ public static class RoleGuidePatches
_titleText.transform.GetComponent().Destroy();
}
}
+
if (!_titleIcon)
{
var titleIconObj = new GameObject("TitleIcon");
@@ -369,18 +359,18 @@ public static class RoleGuidePatches
_guide = instance;
_loading = false;
- SearchComponentContainer = new GameObject();
- SearchComponentContainer.transform.SetParent(instance.MatchInfoParent.transform);
- SearchComponentContainer.transform.localPosition = Vector3.zero;
- instance.MatchInfoParent.transform.GetChild(1).transform.SetParent(SearchComponentContainer.transform);
+ searchComponentContainer = new GameObject();
+ searchComponentContainer.transform.SetParent(instance.MatchInfoParent.transform);
+ searchComponentContainer.transform.localPosition = Vector3.zero;
+ instance.MatchInfoParent.transform.GetChild(1).transform.SetParent(searchComponentContainer.transform);
var sortingOrderButton = Object.Instantiate(
HudManager.Instance.SettingsButton,
- SearchComponentContainer.transform);
+ searchComponentContainer.transform);
sortingOrderButton.gameObject.SetActive(true);
- SearchSortingOrderButton = sortingOrderButton.GetComponent();
+ var searchSortingOrderButton = sortingOrderButton.GetComponent();
SetupSearchButton(
- SearchSortingOrderButton,
+ searchSortingOrderButton,
"SearchSortingOrderButton",
SwitchMethod,
GetSortMethodSprite(_sortMethod, false),
@@ -391,11 +381,11 @@ public static class RoleGuidePatches
var sortingGroupButton = Object.Instantiate(
sortingOrderButton,
- SearchComponentContainer.transform);
+ searchComponentContainer.transform);
sortingGroupButton.gameObject.SetActive(true);
- SearchSortingGroupButton = sortingGroupButton.GetComponent();
+ var searchSortingGroupButton = sortingGroupButton.GetComponent();
SetupSearchButton(
- SearchSortingGroupButton,
+ searchSortingGroupButton,
"SearchSortingGroupButton",
SwitchGrouping,
GetSortGroupSprite(_sortGrouping, false),
@@ -406,11 +396,11 @@ public static class RoleGuidePatches
var sortingFilterButton = Object.Instantiate(
sortingOrderButton,
- SearchComponentContainer.transform);
+ searchComponentContainer.transform);
sortingFilterButton.gameObject.SetActive(true);
- SearchSortingFilterButton = sortingFilterButton.GetComponent();
+ var searchSortingFilterButton = sortingFilterButton.GetComponent();
SetupSearchButton(
- SearchSortingFilterButton,
+ searchSortingFilterButton,
"SearchSortingFilterButton",
SwitchFilter,
GetSortFilterSprite(_sortFilter, false),
@@ -463,9 +453,8 @@ public static class RoleGuidePatches
sortingOrderButton,
sortingOrderButton.transform.parent);
searchIconButton.gameObject.SetActive(true);
- SearchIconButton = searchIconButton.GetComponent();
SetupSearchButton(
- SearchIconButton,
+ searchIconButton.GetComponent(),
"SearchIconButton",
ClearSearchText,
MiraAssets.SearchIconIdleSprite,
@@ -476,7 +465,7 @@ public static class RoleGuidePatches
var searchBox = Object.Instantiate(
instance.TabButtons[2].gameObject,
- SearchComponentContainer.transform);
+ searchComponentContainer.transform);
var searchButton = searchBox.GetComponent();
var tmpText = searchButton.transform.GetChild(0).GetComponent();
tmpText.GetComponent().Destroy();
@@ -621,26 +610,26 @@ public static class RoleGuidePatches
modifiersButton.OnClick.AddListener((Action)(() => OpenModifiersTab()));
instance.TabButtons.Add(modifiersButton);
- OrderSortingTmp = Object.Instantiate(
+ var orderSortingTmp = Object.Instantiate(
_titleText,
sortingOrderButton.transform);
- OrderSortingTmp.text = MiraLocaleManager.Get("MiraApi.Wiki.OrderLabel");
- OrderSortingTmp.fontSize = OrderSortingTmp.fontSizeMax = 3f;
- OrderSortingTmp.alignment = TextAlignmentOptions.Center;
- OrderSortingTmp.horizontalAlignment = HorizontalAlignmentOptions.Center;
- OrderSortingTmp.transform.localPosition = new Vector3(-0.65f, 0.4f, 0);
+ orderSortingTmp.text = MiraLocaleManager.Get("MiraApi.Wiki.OrderLabel");
+ orderSortingTmp.fontSize = orderSortingTmp.fontSizeMax = 3f;
+ orderSortingTmp.alignment = TextAlignmentOptions.Center;
+ orderSortingTmp.horizontalAlignment = HorizontalAlignmentOptions.Center;
+ orderSortingTmp.transform.localPosition = new Vector3(-0.65f, 0.4f, 0);
- GroupSortingTmp = Object.Instantiate(
- OrderSortingTmp,
+ var groupSortingTmp = Object.Instantiate(
+ orderSortingTmp,
sortingGroupButton.transform);
- OrderSortingTmp.text = MiraLocaleManager.Get("MiraApi.Wiki.GroupingLabel");
- GroupSortingTmp.transform.localPosition = new Vector3(-0.65f, 0.4f, 0);
+ orderSortingTmp.text = MiraLocaleManager.Get("MiraApi.Wiki.GroupingLabel");
+ groupSortingTmp.transform.localPosition = new Vector3(-0.65f, 0.4f, 0);
- FilterSortingTmp = Object.Instantiate(
- OrderSortingTmp,
+ var filterSortingTmp = Object.Instantiate(
+ orderSortingTmp,
sortingFilterButton.transform);
- FilterSortingTmp.text = MiraLocaleManager.Get("MiraApi.Wiki.FilterLabel");
- FilterSortingTmp.transform.localPosition = new Vector3(-0.65f, 0.4f, 0);
+ filterSortingTmp.text = MiraLocaleManager.Get("MiraApi.Wiki.FilterLabel");
+ filterSortingTmp.transform.localPosition = new Vector3(-0.65f, 0.4f, 0);
playerButton.transform.localPosition = new Vector3(-3.6f, 0.656f, -0.2f);
settingButton.transform.localPosition = new Vector3(-3.6f, 0.056f, -0.2f);
@@ -731,11 +720,17 @@ public static class RoleGuidePatches
}
}
- public static void OpenModifiersTab() => OpenTab(ModifiersTabIndex);
+ public static void OpenModifiersTab()
+ {
+ OpenTab(ModifiersTabIndex);
+ }
- public static void OpenRolesTab() => OpenTab(RolesTabIndex);
+ public static void OpenRolesTab()
+ {
+ OpenTab(RolesTabIndex);
+ }
- public sealed class DetailedPanel(string title, string category, string modId, RoleBehaviour? role, GameModifier? modifier)
+ private sealed class DetailedPanel(string title, string category, string modId, RoleBehaviour? role, GameModifier? modifier)
{
public MatchInfoRolePanel? Panel { get; set; }
public string Title { get; } = title;
@@ -803,14 +798,7 @@ public static class RoleGuidePatches
private static IEnumerator CoPopulate(float delay)
{
- if (delay > 0f)
- {
- yield return new WaitForSeconds(delay);
- }
- else
- {
- yield return null;
- }
+ yield return delay > 0f ? new WaitForSeconds(delay) : null;
if (!_guide)
{
@@ -1048,14 +1036,8 @@ public static class RoleGuidePatches
public static void SwitchFilter()
{
var stepUp = (SortingFilter)((int)_sortFilter + 1);
- if (Enum.IsDefined(stepUp))
- {
- _sortFilter = stepUp;
- }
- else
- {
- _sortFilter = SortingFilter.EnabledOnly;
- }
+
+ _sortFilter = Enum.IsDefined(stepUp) ? stepUp : SortingFilter.EnabledOnly;
MiraApiPlugin.WikiSortingFilter.Value = _sortFilter;
@@ -1094,14 +1076,8 @@ public static class RoleGuidePatches
public static void SwitchMethod()
{
var stepUp = (SortingMethod)((int)_sortMethod + 1);
- if (Enum.IsDefined(stepUp))
- {
- _sortMethod = stepUp;
- }
- else
- {
- _sortMethod = SortingMethod.Alphabetical;
- }
+
+ _sortMethod = Enum.IsDefined(stepUp) ? stepUp : SortingMethod.Alphabetical;
MiraApiPlugin.WikiSortingMethod.Value = _sortMethod;
@@ -1288,7 +1264,7 @@ public static class RoleGuidePatches
}
_advancedInfoTabScroller?.gameObject.SetActive(false);
- SearchComponentContainer?.SetActive(true);
+ searchComponentContainer?.SetActive(true);
UpdateSpinner();
}
@@ -1341,9 +1317,9 @@ public static class RoleGuidePatches
_currentAdvancedTabObject.Destroy();
}
- if (SearchComponentContainer)
+ if (searchComponentContainer)
{
- SearchComponentContainer.SetActive(false);
+ searchComponentContainer.SetActive(false);
}
if (_advancedInfoTabScroller == null)
@@ -1543,20 +1519,20 @@ public static class RoleGuidePatches
}
}
-public enum SortingGroups
+internal enum SortingGroups
{
Ungrouped,
Faction,
AmountChance,
}
-public enum SortingMethod
+internal enum SortingMethod
{
Alphabetical,
AlphabeticalDescending,
}
-public enum SortingFilter
+internal enum SortingFilter
{
EnabledOnly,
DisabledOnly,
diff --git a/MiraAPI/Patches/Stubs/RoleBehaviourStubs.cs b/MiraAPI/Patches/Stubs/RoleBehaviourStubs.cs
index f047fd3..b856d22 100644
--- a/MiraAPI/Patches/Stubs/RoleBehaviourStubs.cs
+++ b/MiraAPI/Patches/Stubs/RoleBehaviourStubs.cs
@@ -39,10 +39,10 @@ public static class RoleBehaviourStubs
}
///
- /// Stub method for .
+ /// Stub method for .
///
/// The object.
- /// The to append the task hint to.
+ /// The to append the task hint to.
[HarmonyReversePatch]
[HarmonyPatch(typeof(RoleBehaviour), nameof(RoleBehaviour.AppendTaskHint), typeof(Il2CppSystem.Text.StringBuilder))]
[MethodImpl(MethodImplOptions.NoInlining)]
diff --git a/MiraAPI/Presets/SavePresetPopup.cs b/MiraAPI/Presets/SavePresetPopup.cs
index b9932ff..9405e83 100644
--- a/MiraAPI/Presets/SavePresetPopup.cs
+++ b/MiraAPI/Presets/SavePresetPopup.cs
@@ -16,6 +16,7 @@ namespace MiraAPI.Presets;
[RegisterInIl2Cpp]
[SuppressMessage("Style", "IDE0051:Remove unused private members", Justification = "Unity convention.")]
+[SuppressMessage("Design", "CA1050:Declare types in namespaces", Justification = "Unity script.")]
#pragma warning disable CS1591 // Missing XML comment for publicly visible type or member (Justification: Unity fields; ignore.)
public class SavePresetPopup(nint cppPtr) : Minigame(cppPtr)
{
diff --git a/MiraAPI/Roles/ICustomRole.cs b/MiraAPI/Roles/ICustomRole.cs
index 4d5e247..88b1f85 100644
--- a/MiraAPI/Roles/ICustomRole.cs
+++ b/MiraAPI/Roles/ICustomRole.cs
@@ -345,7 +345,14 @@ public interface ICustomRole : IOptionable
/// Gets the list of abilities or other similar information to display below the text of a role's wiki page.
///
[HideFromIl2Cpp]
- public List WikiAbilities => [];
+ List WikiAbilities => [];
}
+///
+/// A data holder of an ability's wiki entry.
+///
+/// The name of the ability.
+/// The type of the ability.
+/// The description of the ability.
+/// The icon sprite of the ability.
public record struct AdvancedWikiAbilityDescription(string Name, string AbilityType, string Description, LoadableAsset Icon);
diff --git a/MiraAPI/Translation/MiraLocaleManager.cs b/MiraAPI/Translation/MiraLocaleManager.cs
index d26f422..0bce8ca 100644
--- a/MiraAPI/Translation/MiraLocaleManager.cs
+++ b/MiraAPI/Translation/MiraLocaleManager.cs
@@ -1,6 +1,5 @@
using System;
using System.Collections.Generic;
-using System.Diagnostics.CodeAnalysis;
using System.IO;
using System.Linq;
using System.Reflection;
@@ -162,7 +161,6 @@ public static class MiraLocaleManager
/// The string id to find.
/// Fallback string to use if no translation is found.
/// A based on the key provided.
- [SuppressMessage("Style", "IDE0046:Convert to conditional expression", Justification = "Warning cascades into forcing the entire tree to be ternary operators.")]
public static string Get(MiraLanguage language, string key, string fallback = "")
{
if (Locale.TryGetValue(language, out var translations) &&
diff --git a/MiraAPI/Utilities/ControllableComparer.cs b/MiraAPI/Utilities/ControllableComparer.cs
index 49c4b0e..5e7ac70 100644
--- a/MiraAPI/Utilities/ControllableComparer.cs
+++ b/MiraAPI/Utilities/ControllableComparer.cs
@@ -1,6 +1,5 @@
using System;
using System.Collections.Generic;
-using System.Diagnostics.CodeAnalysis;
using System.Linq;
namespace MiraAPI.Utilities;
@@ -9,7 +8,6 @@ internal sealed class ControllableComparer(T[] forcedToBottom, T[] forcedToTo
where T : IComparable
{
///
- [SuppressMessage("Style", "IDE0046:Convert to conditional expression", Justification = "Warning cascades into forcing the entire tree to be ternary operators.")]
public int Compare(T? x, T? y)
{
if ((forcedToBottom.Contains(x) && forcedToBottom.Contains(y)) || (forcedToTop.Contains(x) && forcedToTop.Contains(y)))
diff --git a/MiraAPI/Utilities/Helpers.cs b/MiraAPI/Utilities/Helpers.cs
index 773a4ae..413fb59 100644
--- a/MiraAPI/Utilities/Helpers.cs
+++ b/MiraAPI/Utilities/Helpers.cs
@@ -32,6 +32,11 @@ public static class Helpers
{
private static readonly Regex TrailingZeroRegex = new(@"\.0+(?!\d)", RegexOptions.Compiled, TimeSpan.FromMilliseconds(100));
+ ///
+ /// Gets all of the options stored within the provided type.
+ ///
+ /// The type to get the options of.
+ /// A readonly list of options from the provided type.
public static ReadOnlyCollection? GetModdedOptionsForType(Type classType)
{
var group = ModdedOptionsManager.Groups.FirstOrDefault(x => x.OptionableType == classType);
@@ -39,6 +44,11 @@ public static class Helpers
return group?.Children;
}
+ ///
+ /// Gets the option text of the provided type.
+ ///
+ /// The type to get the text for.
+ /// The options text of the provided type.
public static string GetOptionsText(Type classType)
{
var group = ModdedOptionsManager.Groups.FirstOrDefault(x => x.OptionableType == classType);
@@ -836,7 +846,7 @@ public static class Helpers
obj.transform.SetParent(parent.Inner.transform);
obj.transform.localPosition = new Vector3(0f, 0.5f, 0f);
var scrollHeight = variableTextSizing
- ? (desc.textBounds.size.y - 2.5f) + maxTextSize + 0.475f
+ ? desc.textBounds.size.y - 2.5f + maxTextSize + 0.475f
: desc.textBounds.size.y - 2.5f + Mathf.Ceil(num / 2f) * 1.45f;
parent.SetYBoundsMax(Mathf.Clamp(scrollHeight, 0f, 999f));
return obj;
@@ -857,6 +867,7 @@ public static class Helpers
panel.roleDescription.fontSizeMin = 1.5f;
panel.roleDescription.ForceMeshUpdate();
}
+
panel.roleIcon.sprite = ability.Icon.LoadAsset();
panel.roleIcon.SetSizeLimit(0.13f);