diff --git a/MiraAPI.Example/ExamplePlugin.cs b/MiraAPI.Example/ExamplePlugin.cs index 007f0c4..cc1e769 100644 --- a/MiraAPI.Example/ExamplePlugin.cs +++ b/MiraAPI.Example/ExamplePlugin.cs @@ -15,8 +15,8 @@ namespace MiraAPI.Example; public partial class ExamplePlugin : BasePlugin, IMiraConfig { public Harmony Harmony { get; } = new(Id); - public static ExamplePlugin Instance { get; private set; } - public ModdedOptionTabSettings TabSettings => new ModdedOptionTabSettings() + + public ModdedOptionTabSettings TabSettings => new() { Title = "MiraAPI Example Mod", TabIcon = MiraAssets.Empty @@ -24,7 +24,6 @@ public partial class ExamplePlugin : BasePlugin, IMiraConfig public override void Load() { - Instance = this; Harmony.PatchAll(); } } \ No newline at end of file diff --git a/MiraAPI/GameModes/ActiveMode.cs b/MiraAPI/GameModes/ActiveMode.cs new file mode 100644 index 0000000..d687695 --- /dev/null +++ b/MiraAPI/GameModes/ActiveMode.cs @@ -0,0 +1,7 @@ +namespace MiraAPI.GameModes; + +public struct ActiveMode +{ + public string PluginId { get; set; } + public int ModeId { get; set; } +} \ No newline at end of file diff --git a/MiraAPI/GameModes/DefaultMode.cs b/MiraAPI/GameModes/DefaultMode.cs index 2e7fcb0..0993fb6 100644 --- a/MiraAPI/GameModes/DefaultMode.cs +++ b/MiraAPI/GameModes/DefaultMode.cs @@ -4,6 +4,6 @@ public class DefaultMode : CustomGameMode { public override string Name => "Default"; - public override string Description => "Default Among Us GameMode"; + public override string Description => "Default Among Us Game Mode"; public override int Id => 0; } \ No newline at end of file diff --git a/MiraAPI/GameOptions/Attributes/ModdedOptionAttribute.cs b/MiraAPI/GameOptions/Attributes/ModdedOptionAttribute.cs index e2379b5..151ec90 100644 --- a/MiraAPI/GameOptions/Attributes/ModdedOptionAttribute.cs +++ b/MiraAPI/GameOptions/Attributes/ModdedOptionAttribute.cs @@ -19,7 +19,7 @@ namespace MiraAPI.GameOptions.Attributes { foreach (var type in assembly.GetTypes()) { - foreach (PropertyInfo property in type.GetProperties()) + foreach (var property in type.GetProperties()) { foreach (var attribute in property.GetCustomAttributes()) { diff --git a/MiraAPI/GameOptions/ModdedOptionsManager.cs b/MiraAPI/GameOptions/ModdedOptionsManager.cs index d8d5dcf..2f6ef31 100644 --- a/MiraAPI/GameOptions/ModdedOptionsManager.cs +++ b/MiraAPI/GameOptions/ModdedOptionsManager.cs @@ -18,21 +18,6 @@ namespace MiraAPI.GameOptions private static Dictionary OriginalTypes = new(); public static Dictionary RegisteredMods = new(); - public static void Initialize() - { - IL2CPPChainloader.Instance.PluginLoad += (_, assembly, plugin) => - { - if (plugin.GetType().GetInterfaces().Contains(typeof(IMiraConfig))) - { - IMiraConfig config = (IMiraConfig)Activator.CreateInstance(plugin.GetType()); - RegisteredMods.Add(assembly, config); - } - - RegisterOptionGroups(assembly); - - ModdedOptionAttribute.Register(assembly); - }; - } private static void RegisterOptionGroups(Assembly assembly) { diff --git a/MiraAPI/IMiraConfig.cs b/MiraAPI/IMiraConfig.cs index 3cde9a5..5c12a44 100644 --- a/MiraAPI/IMiraConfig.cs +++ b/MiraAPI/IMiraConfig.cs @@ -1,5 +1,4 @@ -using MiraAPI.Utilities; -using MiraAPI.Utilities.Assets; +using MiraAPI.Utilities.Assets; using UnityEngine; namespace MiraAPI diff --git a/MiraAPI/MiraPluginInfo.cs b/MiraAPI/MiraPluginInfo.cs new file mode 100644 index 0000000..bb739be --- /dev/null +++ b/MiraAPI/MiraPluginInfo.cs @@ -0,0 +1,25 @@ +using System.Collections.Generic; +using MiraAPI.GameModes; +using MiraAPI.GameOptions; +using MiraAPI.Roles; + +namespace MiraAPI; + +public class MiraPluginInfo +{ + public string PluginId { get; set; } + public IMiraConfig Config { get; set; } + + public readonly List OptionGroups = []; + public readonly List Options = []; + + public readonly Dictionary CustomRoles = []; + public readonly Dictionary GameModes = []; + + public MiraPluginInfo(string id, IMiraConfig config) + { + PluginId = id; + Config = config; + } + +} \ No newline at end of file diff --git a/MiraAPI/MiraPluginManager.cs b/MiraAPI/MiraPluginManager.cs new file mode 100644 index 0000000..ba52a7f --- /dev/null +++ b/MiraAPI/MiraPluginManager.cs @@ -0,0 +1,50 @@ +using System.Collections.Generic; +using System.Linq; +using System.Reflection; +using BepInEx; +using BepInEx.Unity.IL2CPP; +using MiraAPI.GameOptions.Attributes; +using MiraAPI.Roles; +using MiraAPI.Utilities; + +namespace MiraAPI; + +public class MiraPluginManager +{ + public Dictionary RegisteredPlugins = []; + + public void Initialize() + { + IL2CPPChainloader.Instance.PluginLoad += (_, assembly, plugin) => + { + if (!plugin.GetType().GetInterfaces().Contains(typeof(IMiraConfig))) return; + + var id = MetadataHelper.GetMetadata(plugin.GetType()).GUID; + var info = new MiraPluginInfo(id, plugin as IMiraConfig); + + RegisterRoleAttribute(assembly, info); + + ModdedOptionAttribute.Register(assembly); + + RegisteredPlugins.Add(assembly, info); + + }; + } + + private static void RegisterRoleAttribute(Assembly assembly, MiraPluginInfo pluginInfo) + { + foreach (var type in assembly.GetTypes()) + { + var attribute = type.GetCustomAttribute(); + if (attribute == null) continue; + + Helpers.RegisterIl2CppType(type); + var role = CustomRoleManager.RegisterRole(type, attribute.RoleId); + + pluginInfo.CustomRoles.Add((ushort)role.Role, role as ICustomRole); + } + } + + + +} \ No newline at end of file diff --git a/MiraAPI/Patches/HudManagerPatches.cs b/MiraAPI/Patches/HudManagerPatches.cs index 8fcf456..c0f92e9 100644 --- a/MiraAPI/Patches/HudManagerPatches.cs +++ b/MiraAPI/Patches/HudManagerPatches.cs @@ -6,6 +6,7 @@ using MiraAPI.Patches.Options; using MiraAPI.Roles; using Reactor.Utilities.Extensions; using UnityEngine; +using UnityEngine.Events; namespace MiraAPI.Patches { diff --git a/MiraAPI/Resources/Menu_Button.png b/MiraAPI/Resources/Menu_Button.png index f8d1566..8fa22c7 100644 Binary files a/MiraAPI/Resources/Menu_Button.png and b/MiraAPI/Resources/Menu_Button.png differ diff --git a/MiraAPI/Roles/CustomRoleManager.cs b/MiraAPI/Roles/CustomRoleManager.cs index 962c551..b5b66bd 100644 --- a/MiraAPI/Roles/CustomRoleManager.cs +++ b/MiraAPI/Roles/CustomRoleManager.cs @@ -8,7 +8,6 @@ using Reactor.Utilities; using Reactor.Utilities.Extensions; using System; using System.Collections.Generic; -using System.Linq; using MiraAPI.Networking; using TMPro; using UnityEngine; @@ -18,46 +17,35 @@ namespace MiraAPI.Roles; public static class CustomRoleManager { - public static readonly Dictionary CustomRoles = []; - public static readonly Dictionary> ModRoles = []; - - public static void RegisterInRoleManager() + public static Dictionary CustomRoles = new(); + + public static int GetNextRoleId(ushort requestedId) { - RoleManager.Instance.AllRoles = RoleManager.Instance.AllRoles.Concat(CustomRoles.Values).ToArray(); + while (CustomRoles.ContainsKey(requestedId)) + { + requestedId++; + } + + return requestedId; } - internal static void RegisterRole(Type roleType, ushort roleId, string modId) + internal static RoleBehaviour RegisterRole(Type roleType, ushort roleId) { - if (!IL2CPPChainloader.Instance.Plugins.TryGetValue(modId, out PluginInfo info)) - { - Debug.LogError($"{modId} is not a valid mod!"); - return; - } - if (!(typeof(RoleBehaviour).IsAssignableFrom(roleType) && typeof(ICustomRole).IsAssignableFrom(roleType))) { - return; - } - - if (CustomRoles.Any(behaviour => behaviour.GetType() == roleType)) - { - return; + Debug.LogError($"{roleType?.Name} does not inherit from RoleBehaviour or ICustomRole."); + return null; } var roleBehaviour = (RoleBehaviour)new GameObject(roleType.Name).DontDestroy().AddComponent(Il2CppType.From(roleType)); if (roleBehaviour is not ICustomRole customRole) { - return; + roleBehaviour.gameObject.Destroy(); + return null; } - if (CustomRoles.ContainsKey(roleId)) - { - Debug.LogError($"Role ID conflict for {customRole.RoleName}. Use a different ID."); - return; - } - - roleBehaviour.Role = (RoleTypes)roleId; + roleBehaviour.Role = (RoleTypes)GetNextRoleId(roleId); roleBehaviour.TeamType = customRole.Team == ModdedRoleTeams.Neutral ? RoleTeamTypes.Crewmate : (RoleTeamTypes)customRole.Team; roleBehaviour.NameColor = customRole.RoleColor; roleBehaviour.StringName = CustomStringName.CreateAndRegister(customRole.RoleName); @@ -75,48 +63,27 @@ public static class CustomRoleManager { RoleManager.GhostRoles.Add(roleBehaviour.Role); } - - if (ModRoles.TryGetValue(info, out List roles)) - { - roles.Add(roleBehaviour); - } - else - { - ModRoles.TryAdd(info, [roleBehaviour]); - } - - CustomRoles.Add(roleId, roleBehaviour); + + CustomRoles.Add(roleId, customRole); if (customRole.HideSettings) { - return; + return roleBehaviour; } var config = PluginSingleton.Instance.Config; config.Bind(customRole.NumConfigDefinition, 1); config.Bind(customRole.ChanceConfigDefinition, 100); + return roleBehaviour; } - public static List GetRolesRegistered(string modId) - { - PluginInfo info = ModRoles.Keys.First(key => key.Metadata.GUID == modId); - if (ModRoles.TryGetValue(info, out List roles)) - { - return roles; - } - else - { - Debug.LogError($"{modId} has no roles registered."); - return null; - } - } public static bool GetCustomRoleBehaviour(RoleTypes roleType, out ICustomRole result) { CustomRoles.TryGetValue((ushort)roleType, out var temp); - if (temp is ICustomRole role) + if (temp != null) { - result = role; + result = temp; return true; } diff --git a/MiraAPI/Roles/RegisterCustomRoleAttribute.cs b/MiraAPI/Roles/RegisterCustomRoleAttribute.cs index 0c49aeb..87fdc39 100644 --- a/MiraAPI/Roles/RegisterCustomRoleAttribute.cs +++ b/MiraAPI/Roles/RegisterCustomRoleAttribute.cs @@ -7,40 +7,11 @@ using System.Reflection; namespace MiraAPI.Roles; [AttributeUsage(AttributeTargets.Class)] -public class RegisterCustomRoleAttribute : Attribute -{ - private static readonly HashSet RegisteredAssemblies = []; - public ushort RoleId { get; } - public string ModId { get; } +public class RegisterCustomRoleAttribute(ushort roleId) : Attribute +{ + public ushort RoleId { get; } = roleId; - public RegisterCustomRoleAttribute(string modId) + public RegisterCustomRoleAttribute() : this((ushort)(20 + CustomRoleManager.CustomRoles.Count)) { - ModId = modId; - RoleId = (ushort)(20 + CustomRoleManager.CustomRoles.Count); - } - public RegisterCustomRoleAttribute(string modId, ushort roleId) - { - ModId = modId; - RoleId = roleId; - } - - public static void Initialize() - { - IL2CPPChainloader.Instance.PluginLoad += (_, assembly, plugin) => Register(assembly); - } - - public static void Register(Assembly assembly) - { - if (!RegisteredAssemblies.Add(assembly)) return; - - foreach (var type in assembly.GetTypes()) - { - var attribute = type.GetCustomAttribute(); - if (attribute != null) - { - Helpers.RegisterType(type); - CustomRoleManager.RegisterRole(type, attribute.RoleId, attribute.ModId); - } - } } } \ No newline at end of file diff --git a/MiraAPI/Utilities/Helpers.cs b/MiraAPI/Utilities/Helpers.cs index 5cef351..ceee3b1 100644 --- a/MiraAPI/Utilities/Helpers.cs +++ b/MiraAPI/Utilities/Helpers.cs @@ -17,7 +17,7 @@ namespace MiraAPI.Utilities return ShipStatus.Instance.AllRooms.ToList().Find(room => room.roomArea.OverlapPoint(pos)); } - public static void RegisterType(Type type) + public static void RegisterIl2CppType(Type type) { if (ClassInjector.IsTypeRegisteredInIl2Cpp(type)) {