diff --git a/Obsidian/Events/MinecraftEvent.cs b/Obsidian/Events/MinecraftEvent.cs index 2a8860878..05bcea273 100644 --- a/Obsidian/Events/MinecraftEvent.cs +++ b/Obsidian/Events/MinecraftEvent.cs @@ -1,7 +1,6 @@ using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Internal; using Microsoft.Extensions.Logging; -using Obsidian.API.Events; using Obsidian.Plugins; using System.Diagnostics; @@ -14,7 +13,7 @@ internal readonly struct MinecraftEvent public Type? ModuleType { get; init; } - public required PluginContainer PluginContainer { get; init; } + public required PluginContainer? PluginContainer { get; init; } public required Priority Priority { get; init; } @@ -25,14 +24,15 @@ internal readonly struct MinecraftEvent public Delegate? MethodDelegate { get; init; } //TODO PARAM INJECTION - public async ValueTask Execute(params object[]? methodParams) + public async ValueTask Execute(IServiceProvider serviceProvider, params object[]? methodParams) { if (this.MethodExecutor != null) { - var module = this.ModuleFactory!.Invoke(this.PluginContainer.ServiceScope.ServiceProvider, null)//Will inject services through constructor + var module = this.ModuleFactory!.Invoke(this.PluginContainer?.ServiceScope.ServiceProvider + ?? serviceProvider, null)//Will inject services through constructor ?? throw new InvalidOperationException("Failed to initialize module from factory."); - this.PluginContainer.InjectServices(this.Logger, module); //inject through attribute + this.PluginContainer?.InjectServices(this.Logger, module); //inject through attribute if (this.MethodExecutor.MethodReturnType == typeof(ValueTask)) { diff --git a/Obsidian/Services/EventDispatcher.cs b/Obsidian/Services/EventDispatcher.cs index 1b351b893..86cc41897 100644 --- a/Obsidian/Services/EventDispatcher.cs +++ b/Obsidian/Services/EventDispatcher.cs @@ -21,14 +21,14 @@ public sealed class EventDispatcher : IDisposable private static readonly Type minecraftEventHandlerType = typeof(MinecraftEventHandler); private readonly ILogger logger; - + private readonly IServiceProvider serviceProvider; private readonly FrozenDictionary> registeredEvents; private readonly FrozenDictionary eventNames; - public EventDispatcher(ILogger logger) + public EventDispatcher(ILogger logger, IServiceProvider serviceProvider) { this.logger = logger; - + this.serviceProvider = serviceProvider; var events = baseMinecraftEventArgsType.Assembly.GetTypes() .Where(x => x.IsSubclassOf(baseMinecraftEventArgsType) && !x.IsAbstract) .ToList(); @@ -39,16 +39,17 @@ public EventDispatcher(ILogger logger) foreach (var eventType in events) { var @eventArgs = (BaseMinecraftEventArgs)RuntimeHelpers.GetUninitializedObject(eventType); + var name = eventType.Name.TrimEventArgs(); - dict.Add(@eventArgs.Name, []); - names.Add(eventType, @eventArgs.Name); + dict.Add(name, []); + names.Add(eventType, name); } this.registeredEvents = dict.ToFrozenDictionary(); this.eventNames = names.ToFrozenDictionary(); } - public void RegisterEvents(PluginContainer pluginContainer) where TEventModule : MinecraftEventHandler + public void RegisterEvents(PluginContainer? pluginContainer) where TEventModule : MinecraftEventHandler { var eventModule = typeof(TEventModule); var eventModuleTypeInfo = eventModule.GetTypeInfo(); @@ -95,7 +96,7 @@ public void RegisterEvent(PluginContainer pluginContainer, ValueTask }); } - public void RegisterEvent(PluginContainer pluginContainer, Delegate handler, Priority priority = Priority.Low) + public void RegisterEvent(PluginContainer? pluginContainer, Delegate handler, Priority priority = Priority.Low) { var eventType = handler.Method.GetParameters().FirstOrDefault()?.ParameterType ?? throw new InvalidOperationException("Missing parameter for event."); @@ -115,6 +116,8 @@ public void RegisterEvent(PluginContainer pluginContainer, Delegate handler, Pri public void RegisterEvents(PluginContainer pluginContainer) { + ArgumentNullException.ThrowIfNull(pluginContainer); + var modules = pluginContainer.PluginAssembly.GetTypes().Where(x => x.IsAssignableFrom(minecraftEventHandlerType)); foreach (var eventModule in modules) @@ -150,6 +153,7 @@ public void RegisterEvents(PluginContainer pluginContainer) public async ValueTask ExecuteEventAsync(TEventArgs eventArgs) where TEventArgs : BaseMinecraftEventArgs { var eventType = eventArgs.GetType(); + using var serviceScope = this.serviceProvider.CreateScope(); if (!this.registeredEvents.TryGetValue(eventArgs.Name, out var events)) return EventResult.Completed; @@ -162,7 +166,7 @@ public async ValueTask ExecuteEventAsync(TEventArgs eve { try { - await @event.Execute(new[] { eventArgs }); + await @event.Execute(serviceScope.ServiceProvider, new[] { eventArgs }); if (eventArgs is ICancellable cancellable && cancellable.IsCancelled) eventResult = EventResult.Cancelled; diff --git a/Obsidian/Utilities/Extensions.cs b/Obsidian/Utilities/Extensions.cs index 4e7baaa59..e7186a09c 100644 --- a/Obsidian/Utilities/Extensions.cs +++ b/Obsidian/Utilities/Extensions.cs @@ -60,6 +60,11 @@ public static partial class Extensions public static IEnumerable WithInjectAttribute(this Type type) => type.GetProperties().Where(x => x.GetCustomAttribute() != null && !x.PropertyType.IsAssignableTo(pluginBaseType)); + private const string EventArgs = "EventArgs"; + + public static string TrimEventArgs(this string value) => + value.Replace(EventArgs, string.Empty); + public static void WritePacketId(this IPacket packet, MinecraftStream stream) { stream.Lock.Wait();