Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

optimize plugin loading (and other optimizations if I find them) #18

Merged
merged 3 commits into from
Feb 10, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion MiraAPI.Example/Buttons/Freezer/FreezeButton.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@

namespace MiraAPI.Example.Buttons.Freezer;

[RegisterButton]
public class FreezeButton : CustomActionButton<PlayerControl>
{
public override string Name => "Freeze";
Expand Down
1 change: 0 additions & 1 deletion MiraAPI.Example/Buttons/MeetingButton.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@

namespace MiraAPI.Example.Buttons;

[RegisterButton]
public class MeetingButton : CustomActionButton
{
public override string Name => "Call Meeting";
Expand Down
1 change: 0 additions & 1 deletion MiraAPI.Example/Buttons/Teleporter/TeleportButton.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@

namespace MiraAPI.Example.Buttons.Teleporter;

[RegisterButton]
public class TeleportButton : CustomActionButton
{
public override string Name => "Teleport";
Expand Down
1 change: 0 additions & 1 deletion MiraAPI.Example/Modifiers/CaptainModifier.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@

namespace MiraAPI.Example.Modifiers;

[RegisterModifier]
public class CaptainModifier : GameModifier
{
public override string ModifierName => "Captain";
Expand Down
1 change: 0 additions & 1 deletion MiraAPI.Example/Modifiers/Freezer/FreezeModifier.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@

namespace MiraAPI.Example.Modifiers.Freezer;

[RegisterModifier]
public class FreezeModifier : TimedModifier
{
public override string ModifierName => "Freezed";
Expand Down
1 change: 0 additions & 1 deletion MiraAPI.Example/Modifiers/HighPriorityModifier.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@

namespace MiraAPI.Example.Modifiers;

[RegisterModifier]
public class HighPriorityModifier : GameModifier
{
public override string ModifierName => "High Priority";
Expand Down
1 change: 0 additions & 1 deletion MiraAPI.Example/Roles/ChameleonRole.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@

namespace MiraAPI.Example.Roles;

[RegisterCustomRole]
public class ChameloenRole : CrewmateRole, ICustomRole
{
public string RoleName => "Chamelon";
Expand Down
1 change: 0 additions & 1 deletion MiraAPI.Example/Roles/FreezerRole.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@

namespace MiraAPI.Example.Roles;

[RegisterCustomRole]
public class FreezerRole : ImpostorRole, ICustomRole
{
public string RoleName => "Freezer";
Expand Down
1 change: 0 additions & 1 deletion MiraAPI.Example/Roles/NeutralKillerRole.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@

namespace MiraAPI.Example.Roles;

[RegisterCustomRole]
public class NeutralKillerRole : ImpostorRole, ICustomRole
{
public string RoleName => "Neutral Killer";
Expand Down
1 change: 0 additions & 1 deletion MiraAPI.Example/Roles/TeleporterRole.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@

namespace MiraAPI.Example.Roles;

[RegisterCustomRole]
public class TeleporterRole : CrewmateRole, ICustomRole
{
public string RoleName => "Teleporter";
Expand Down
1 change: 0 additions & 1 deletion MiraAPI/GameModes/DefaultMode.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
namespace MiraAPI.GameModes;

[RegisterGameMode]
public class DefaultMode : CustomGameMode
{
public override string Name => "Default";
Expand Down
28 changes: 0 additions & 28 deletions MiraAPI/GameModes/RegisterGameModeAttribute.cs

This file was deleted.

9 changes: 0 additions & 9 deletions MiraAPI/Hud/RegisterButtonAttribute.cs

This file was deleted.

9 changes: 0 additions & 9 deletions MiraAPI/Modifiers/RegisterModifierAttribute.cs

This file was deleted.

9 changes: 9 additions & 0 deletions MiraAPI/PluginLoading/MiraDisableAttribute.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
using System;

namespace MiraAPI.PluginLoading;

/// <summary>
/// Skip an element during plugin loading.
/// </summary>
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property)]
public class MiraDisableAttribute : Attribute;
156 changes: 74 additions & 82 deletions MiraAPI/PluginLoading/MiraPluginManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -38,17 +38,31 @@ internal void Initialize()
}

var info = new MiraPluginInfo(miraPlugin, pluginInfo);
var roles = new List<Type>();

RegisterModifierAttribute(assembly);
RegisterAllOptions(assembly, info);
foreach (var type in assembly.GetTypes())
{
if (type.GetCustomAttribute<MiraDisableAttribute>() != null)
{
continue;
}

RegisterRoleAttribute(assembly, info);
RegisterButtonAttribute(assembly, info);
RegisterModifier(type);
RegisterOptions(type, info);

RegisterColorClasses(assembly);
if (RegisterRoleAttribute(type, info, out var role))
{
roles.Add(role!);
}

_registeredPlugins.Add(assembly, info);
RegisterButtonAttribute(type, info);
RegisterColorClasses(type);
}

info.OptionGroups.Sort((x, y) => x.GroupPriority.CompareTo(y.GroupPriority));
CustomRoleManager.RegisterRoleTypes(roles, info);

_registeredPlugins.Add(assembly, info);
Logger<MiraApiPlugin>.Info($"Registering mod {pluginInfo.Metadata.GUID} with Mira API.");
};
IL2CPPChainloader.Instance.Finished += PaletteManager.RegisterAllColors;
Expand All @@ -65,121 +79,99 @@ public static MiraPluginInfo GetPluginByGuid(string guid)
return Instance._registeredPlugins.Values.First(plugin => plugin.PluginId == guid);
}

private static void RegisterAllOptions(Assembly assembly, MiraPluginInfo pluginInfo)
private static void RegisterOptions(Type type, MiraPluginInfo pluginInfo)
{
var filteredTypes = assembly.GetTypes().Where(type => type.IsAssignableTo(typeof(AbstractOptionGroup)));

foreach (var type in filteredTypes)
if (!type.IsAssignableTo(typeof(AbstractOptionGroup)))
{
if (!ModdedOptionsManager.RegisterGroup(type, pluginInfo))
{
continue;
}

foreach (var property in type.GetProperties())
{
if (property.PropertyType.IsAssignableTo(typeof(IModdedOption)))
{
ModdedOptionsManager.RegisterPropertyOption(type, property, pluginInfo);
continue;
}

var attribute = property.GetCustomAttribute<ModdedOptionAttribute>();
if (attribute == null)
{
continue;
}

ModdedOptionsManager.RegisterAttributeOption(type, attribute, property, pluginInfo);
}
return;
}

pluginInfo.OptionGroups.Sort((x, y) => x.GroupPriority.CompareTo(y.GroupPriority));
}
if (!ModdedOptionsManager.RegisterGroup(type, pluginInfo))
{
return;
}

private static void RegisterRoleAttribute(Assembly assembly, MiraPluginInfo pluginInfo)
{
List<Type> roles = [];
foreach (var type in assembly.GetTypes())
foreach (var property in type.GetProperties())
{
var attribute = type.GetCustomAttribute<RegisterCustomRoleAttribute>();
if (attribute == null)
if (property.PropertyType.IsAssignableTo(typeof(IModdedOption)))
{
ModdedOptionsManager.RegisterPropertyOption(type, property, pluginInfo);
continue;
}

if (!(typeof(RoleBehaviour).IsAssignableFrom(type) && typeof(ICustomRole).IsAssignableFrom(type)))
var attribute = property.GetCustomAttribute<ModdedOptionAttribute>();
if (attribute == null)
{
Logger<MiraApiPlugin>.Error($"{type.Name} does not inherit from RoleBehaviour or ICustomRole.");
continue;
}

if (!ModList.GetById(pluginInfo.PluginId).IsRequiredOnAllClients)
{
Logger<MiraApiPlugin>.Error("Custom roles are only supported on all clients.");
return;
}
ModdedOptionsManager.RegisterAttributeOption(type, attribute, property, pluginInfo);
}
}

private static bool RegisterRoleAttribute(Type type, MiraPluginInfo pluginInfo, out Type? role)
{
role = null;

if (!(typeof(RoleBehaviour).IsAssignableFrom(type) && typeof(ICustomRole).IsAssignableFrom(type)))
{
Logger<MiraApiPlugin>.Error($"{type.Name} does not inherit from RoleBehaviour or ICustomRole.");
return false;
}

roles.Add(type);
if (!ModList.GetById(pluginInfo.PluginId).IsRequiredOnAllClients)
{
Logger<MiraApiPlugin>.Error("Custom roles are only supported on all clients.");
return false;
}

CustomRoleManager.RegisterRoleTypes(roles, pluginInfo);
role = type;
return true;
}

private static void RegisterColorClasses(Assembly assembly)
private static void RegisterColorClasses(Type type)
{
foreach (var type in assembly.GetTypes())
if (type.GetCustomAttribute<RegisterCustomColorsAttribute>() == null)
{
return;
}

if (!type.IsStatic())
{
if (type.GetCustomAttribute<RegisterCustomColorsAttribute>() == null)
Logger<MiraApiPlugin>.Error($"Color class {type.Name} must be static.");
return;
}

foreach (var property in type.GetProperties())
{
if (property.PropertyType != typeof(CustomColor))
{
continue;
}

if (!type.IsStatic())
if (property.GetValue(null) is not CustomColor color)
{
Logger<MiraApiPlugin>.Error($"Color class {type.Name} must be static.");
Logger<MiraApiPlugin>.Error($"Color property {property.Name} in {type.Name} is not a CustomColor.");
continue;
}

foreach (var property in type.GetProperties())
{
if (property.PropertyType != typeof(CustomColor))
{
continue;
}

if (property.GetValue(null) is not CustomColor color)
{
Logger<MiraApiPlugin>.Error($"Color property {property.Name} in {type.Name} is not a CustomColor.");
continue;
}

PaletteManager.CustomColors.Add(color);
}
PaletteManager.CustomColors.Add(color);
}
}

private static void RegisterModifierAttribute(Assembly assembly)
private static void RegisterModifier(Type type)
{
foreach (var type in assembly.GetTypes())
if (type.IsAssignableTo(typeof(BaseModifier)))
{
var attribute = type.GetCustomAttribute<RegisterModifierAttribute>();
if (attribute != null)
{
ModifierManager.RegisterModifier(type);
}
ModifierManager.RegisterModifier(type);
}
}

private static void RegisterButtonAttribute(Assembly assembly, MiraPluginInfo pluginInfo)
private static void RegisterButtonAttribute(Type type, MiraPluginInfo pluginInfo)
{
foreach (var type in assembly.GetTypes())
if (type.IsAssignableTo(typeof(CustomActionButton)) || type.IsAssignableTo(typeof(CustomActionButton<>)))
{
var attribute = type.GetCustomAttribute<RegisterButtonAttribute>();
if (attribute != null)
{
CustomButtonManager.RegisterButton(type, pluginInfo);
}
CustomButtonManager.RegisterButton(type, pluginInfo);
}
}
}
6 changes: 0 additions & 6 deletions MiraAPI/Roles/RegisterCustomRoleAttribute.cs

This file was deleted.

17 changes: 0 additions & 17 deletions MiraAPI/Utilities/Extensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using UnityEngine;

namespace MiraAPI.Utilities;
Expand All @@ -18,22 +17,6 @@ namespace MiraAPI.Utilities;
/// </summary>
public static class Extensions
{
public static IEnumerable<Type> GetTypesSafe(this Assembly assembly)
{
try
{
return assembly.GetTypes();
}
catch (ReflectionTypeLoadException ex)
{
return ex.Types.Where(t => t != null);
}
catch
{
return Enumerable.Empty<Type>();
}
}

internal static NetData GetNetData(this ICustomRole role)
{
var count = role.GetCount();
Expand Down
Loading