diff --git a/Exiled.Events/Features/Event.cs b/Exiled.Events/Features/Event.cs
index 141def259f..c27c657030 100644
--- a/Exiled.Events/Features/Event.cs
+++ b/Exiled.Events/Features/Event.cs
@@ -13,12 +13,19 @@ namespace Exiled.Events.Features
using Exiled.API.Features;
using Exiled.Events.EventArgs.Interfaces;
+ using MEC;
///
/// The custom delegate, with empty parameters.
///
public delegate void CustomEventHandler();
+ ///
+ /// THe custom delegate, with empty parameters. Holds async events with .
+ ///
+ /// of .
+ public delegate IEnumerator CustomAsyncEventHandler();
+
///
/// An implementation of that encapsulates a no-argument event.
///
@@ -38,6 +45,8 @@ public Event()
private event CustomEventHandler InnerEvent;
+ private event CustomAsyncEventHandler InnerAsyncEvent;
+
///
/// Gets a of which contains all the instances.
///
@@ -55,6 +64,18 @@ public Event()
return @event;
}
+ ///
+ /// Subscribes a to the inner event, and checks patches if dynamic patching is enabled.
+ ///
+ /// The to subscribe the to.
+ /// The to subscribe to the .
+ /// The with the handler added to it.
+ public static Event operator +(Event @event, CustomAsyncEventHandler asyncEventHandler)
+ {
+ @event.Subscribe(asyncEventHandler);
+ return @event;
+ }
+
///
/// Unsubscribes a target from the inner event, and checks if unpatching is possible, if dynamic patching is enabled.
///
@@ -67,6 +88,18 @@ public Event()
return @event;
}
+ ///
+ /// Unsubscribes a target from the inner event, and checks if unpatching is possible, if dynamic patching is enabled.
+ ///
+ /// The the will be unsubscribed from.
+ /// The that will be unsubscribed from the .
+ /// The with the handler unsubscribed from it.
+ public static Event operator -(Event @event, CustomAsyncEventHandler asyncEventHandler)
+ {
+ @event.Unsubscribe(asyncEventHandler);
+ return @event;
+ }
+
///
/// Subscribes a target to the inner event if the conditional is true.
///
@@ -84,6 +117,23 @@ public void Subscribe(CustomEventHandler handler)
InnerEvent += handler;
}
+ ///
+ /// Subscribes a target to the inner event if the conditional is true.
+ ///
+ /// The handler to add.
+ public void Subscribe(CustomAsyncEventHandler handler)
+ {
+ Log.Assert(Events.Instance is not null, $"{nameof(Events.Instance)} is null, please ensure you have exiled_events enabled!");
+
+ if (Events.Instance.Config.UseDynamicPatching && !patched)
+ {
+ Events.Instance.Patcher.Patch(this);
+ patched = true;
+ }
+
+ InnerAsyncEvent += handler;
+ }
+
///
/// Unsubscribes a target from the inner event if the conditional is true.
///
@@ -93,10 +143,26 @@ public void Unsubscribe(CustomEventHandler handler)
InnerEvent -= handler;
}
+ ///
+ /// Unsubscribes a target from the inner event if the conditional is true.
+ ///
+ /// The handler to add.
+ public void Unsubscribe(CustomAsyncEventHandler handler)
+ {
+ InnerAsyncEvent -= handler;
+ }
+
///
/// Executes all listeners safely.
///
public void InvokeSafely()
+ {
+ InvokeNormal();
+ InvokeAsync();
+ }
+
+ ///
+ internal void InvokeNormal()
{
if (InnerEvent is null)
return;
@@ -113,5 +179,24 @@ public void InvokeSafely()
}
}
}
+
+ ///
+ internal void InvokeAsync()
+ {
+ if (InnerAsyncEvent is null)
+ return;
+
+ foreach (CustomAsyncEventHandler handler in InnerAsyncEvent.GetInvocationList().Cast())
+ {
+ try
+ {
+ Timing.RunCoroutine(handler());
+ }
+ catch (Exception ex)
+ {
+ Log.Error($"Method \"{handler.Method.Name}\" of the class \"{handler.Method.ReflectedType.FullName}\" caused an exception when handling the event \"{GetType().FullName}\"\n{ex}");
+ }
+ }
+ }
}
}
diff --git a/Exiled.Events/Features/Event{T}.cs b/Exiled.Events/Features/Event{T}.cs
index f8ea5f51fd..8cbd180544 100644
--- a/Exiled.Events/Features/Event{T}.cs
+++ b/Exiled.Events/Features/Event{T}.cs
@@ -13,6 +13,7 @@ namespace Exiled.Events.Features
using Exiled.API.Features;
using Exiled.Events.EventArgs.Interfaces;
+ using MEC;
///
/// The custom delegate.
@@ -21,6 +22,14 @@ namespace Exiled.Events.Features
/// The instance.
public delegate void CustomEventHandler(TEventArgs ev);
+ ///
+ /// The custom delegate.
+ ///
+ /// The type.
+ /// The instance.
+ /// of .
+ public delegate IEnumerator CustomAsyncEventHandler(TEventArgs ev);
+
///
/// An implementation of the interface that encapsulates an event with arguments.
///
@@ -41,6 +50,8 @@ public Event()
private event CustomEventHandler InnerEvent;
+ private event CustomAsyncEventHandler InnerAsyncEvent;
+
///
/// Gets a of which contains all the instances.
///
@@ -58,6 +69,18 @@ public Event()
return @event;
}
+ ///
+ /// Subscribes a to the inner event, and checks patches if dynamic patching is enabled.
+ ///
+ /// The to subscribe the to.
+ /// The to subscribe to the .
+ /// The with the handler added to it.
+ public static Event operator +(Event @event, CustomAsyncEventHandler asyncEventHandler)
+ {
+ @event.Subscribe(asyncEventHandler);
+ return @event;
+ }
+
///
/// Unsubscribes a target from the inner event and checks if unpatching is possible, if dynamic patching is enabled.
///
@@ -70,6 +93,18 @@ public Event()
return @event;
}
+ ///
+ /// Unsubscribes a target from the inner event, and checks if unpatching is possible, if dynamic patching is enabled.
+ ///
+ /// The the will be unsubscribed from.
+ /// The that will be unsubscribed from the .
+ /// The with the handler unsubscribed from it.
+ public static Event operator -(Event @event, CustomAsyncEventHandler asyncEventHandler)
+ {
+ @event.Unsubscribe(asyncEventHandler);
+ return @event;
+ }
+
///
/// Subscribes a target to the inner event if the conditional is true.
///
@@ -87,6 +122,23 @@ public void Subscribe(CustomEventHandler handler)
InnerEvent += handler;
}
+ ///
+ /// Subscribes a target to the inner event if the conditional is true.
+ ///
+ /// The handler to add.
+ public void Subscribe(CustomAsyncEventHandler handler)
+ {
+ Log.Assert(Events.Instance is not null, $"{nameof(Events.Instance)} is null, please ensure you have exiled_events enabled!");
+
+ if (Events.Instance.Config.UseDynamicPatching && !patched)
+ {
+ Events.Instance.Patcher.Patch(this);
+ patched = true;
+ }
+
+ InnerAsyncEvent += handler;
+ }
+
///
/// Unsubscribes a target from the inner event if the conditional is true.
///
@@ -96,12 +148,28 @@ public void Unsubscribe(CustomEventHandler handler)
InnerEvent -= handler;
}
+ ///
+ /// Unsubscribes a target from the inner event if the conditional is true.
+ ///
+ /// The handler to add.
+ public void Unsubscribe(CustomAsyncEventHandler handler)
+ {
+ InnerAsyncEvent -= handler;
+ }
+
///
/// Executes all listeners safely.
///
/// The event argument.
/// Event or its arg is .
public void InvokeSafely(T arg)
+ {
+ InvokeNormal(arg);
+ InvokeAsync(arg);
+ }
+
+ ///
+ internal void InvokeNormal(T arg)
{
if (InnerEvent is null)
return;
@@ -118,5 +186,24 @@ public void InvokeSafely(T arg)
}
}
}
+
+ ///
+ internal void InvokeAsync(T arg)
+ {
+ if (InnerAsyncEvent is null)
+ return;
+
+ foreach (CustomAsyncEventHandler handler in InnerAsyncEvent.GetInvocationList().Cast>())
+ {
+ try
+ {
+ Timing.RunCoroutine(handler(arg));
+ }
+ catch (Exception ex)
+ {
+ Log.Error($"Method \"{handler.Method.Name}\" of the class \"{handler.Method.ReflectedType.FullName}\" caused an exception when handling the event \"{GetType().FullName}\"\n{ex}");
+ }
+ }
+ }
}
}