diff --git a/Source/AGS.API/AGS.API.csproj b/Source/AGS.API/AGS.API.csproj
index 8ec659603..9d45426d0 100644
--- a/Source/AGS.API/AGS.API.csproj
+++ b/Source/AGS.API/AGS.API.csproj
@@ -276,6 +276,7 @@
+
diff --git a/Source/AGS.API/Misc/Events/ClaimEventToken.cs b/Source/AGS.API/Misc/Events/ClaimEventToken.cs
new file mode 100644
index 000000000..3cf7f40c7
--- /dev/null
+++ b/Source/AGS.API/Misc/Events/ClaimEventToken.cs
@@ -0,0 +1,16 @@
+namespace AGS.API
+{
+ ///
+ /// This is a token that can be used when you want to claim an event, so that other subscribers which follow you on the subscriber list will not get that event.
+ ///
+ ///
+ public struct ClaimEventToken
+ {
+ ///
+ /// Gets or sets a value indicating whether this is claimed.
+ /// If you claim the event (by setting Claimed = true), this event will not be propogated to the rest of the subscribers.
+ ///
+ /// true if claimed; otherwise, false.
+ public bool Claimed { get; set; }
+ }
+}
diff --git a/Source/AGS.API/Misc/Events/IBlockingEvent.cs b/Source/AGS.API/Misc/Events/IBlockingEvent.cs
index 0504375fb..e130cd349 100644
--- a/Source/AGS.API/Misc/Events/IBlockingEvent.cs
+++ b/Source/AGS.API/Misc/Events/IBlockingEvent.cs
@@ -3,6 +3,52 @@
namespace AGS.API
{
+ ///
+ /// This allows you to subscribe to an event with the option of claiming the event, so that other subscribers in the list will not receive the event.
+ ///
+ ///
+ ///
+ /// myEvent.Subscribe(onEvent1);
+ /// myEvent.Subscribe(onEvent2);
+ ///
+ /// void onEvent1(ref ClaimEventToken token)
+ /// {
+ /// token.Claimed = true; //We claimed the event, "onEvent2" will not get called.
+ /// }
+ ///
+ ///
+ ///
+ public delegate void ClaimableCallback(ref ClaimEventToken token);
+
+ ///
+ /// This allows you to subscribe to an event with the option of claiming the event, so that other subscribers in the list will not receive the event.
+ ///
+ /// For an example- .
+ ///
+ public delegate void ClaimableCallbackWithArgs(TEventArgs args, ref ClaimEventToken token);
+
+ ///
+ /// In a scenario where an event has multiple subscribers, the callback priority affects which subscriber gets the callback first.
+ /// High priority subscribers will receive the event before normal priority (the default) subscribers, and low priority will receive the event last.
+ ///
+ /// Note: For 2 subscribers with the same callback priority, there's no guarantee regarding who gets the event first.
+ ///
+ public enum CallbackPriority : byte
+ {
+ ///
+ /// Low priority- will receive the event last.
+ ///
+ Low,
+ ///
+ /// Normal priority.
+ ///
+ Normal,
+ ///
+ /// High priority- will receive the event first.
+ ///
+ High,
+ }
+
///
/// Represents an event which can be subscribed and invoked synchronously.
/// An event is a notification for something that has happened.
@@ -21,21 +67,43 @@ public interface IBlockingEvent
/// Once subscribed, whenever the event happens this callback will be called.
///
/// Callback.
- void Subscribe(Action callback);
+ /// The callback priority (determines the order in which the subscribers get the events).
+ void Subscribe(Action callback, CallbackPriority priority = CallbackPriority.Normal);
///
/// Unsubscribe the specified callback from the event.
/// This will stops notifications to call this callback.
///
/// Callback.
- void Unsubscribe(Action callback);
+ /// The callback priority (determines the order in which the subscribers get the events).
+ void Unsubscribe(Action callback, CallbackPriority priority = CallbackPriority.Normal);
+
+ ///
+ /// Subscribe the specified callback to the event.
+ /// Once subscribed, whenever the event happens this callback will be called.
+ ///
+ /// In addition, this specific overload allows you to claim the event so that subscribers which follow you on the list will not receive the event.
+ /// For an example- .
+ ///
+ /// Callback.
+ /// The callback priority (determines the order in which the subscribers get the events).
+ void Subscribe(ClaimableCallbackWithArgs callback, CallbackPriority priority = CallbackPriority.Normal);
+
+ ///
+ /// Unsubscribe the specified callback from the event.
+ /// This will stops notifications to call this callback.
+ ///
+ /// Callback.
+ /// The callback priority (determines the order in which the subscribers get the events).
+ void Unsubscribe(ClaimableCallbackWithArgs callback, CallbackPriority priority = CallbackPriority.Normal);
///
/// Asynchronously wait until the event fires and the specific condition applies.
///
/// The task to be awaited.
/// The condition we are waiting to apply before moving on.
- Task WaitUntilAsync(Predicate condition);
+ /// The callback priority (determines the order in which the subscribers get the events).
+ Task WaitUntilAsync(Predicate condition, CallbackPriority priority = CallbackPriority.Normal);
///
/// Invoke the event synchronously (i.e will wait for all subscribers to process the event before moving on).
@@ -62,21 +130,43 @@ public interface IBlockingEvent
/// Once subscribed, whenever the event happens this callback will be called.
///
/// Callback.
- void Subscribe(Action callback);
+ /// The callback priority (determines the order in which the subscribers get the events).
+ void Subscribe(Action callback, CallbackPriority priority = CallbackPriority.Normal);
+
+ ///
+ /// Unsubscribe the specified callback from the event.
+ /// This will stops notifications to call this callback.
+ ///
+ /// Callback.
+ /// The callback priority (determines the order in which the subscribers get the events).
+ void Unsubscribe(Action callback, CallbackPriority priority = CallbackPriority.Normal);
+
+ ///
+ /// Subscribe the specified callback to the event.
+ /// Once subscribed, whenever the event happens this callback will be called.
+ ///
+ /// In addition, this specific overload allows you to claim the event so that subscribers which follow you on the list will not receive the event.
+ /// For an example- .
+ ///
+ /// Callback.
+ /// The callback priority (determines the order in which the subscribers get the events).
+ void Subscribe(ClaimableCallback callback, CallbackPriority priority = CallbackPriority.Normal);
///
/// Unsubscribe the specified callback from the event.
/// This will stops notifications to call this callback.
///
/// Callback.
- void Unsubscribe(Action callback);
+ /// The callback priority (determines the order in which the subscribers get the events).
+ void Unsubscribe(ClaimableCallback callback, CallbackPriority priority = CallbackPriority.Normal);
///
/// Asynchronously wait until the event fires and the specific condition applies.
///
/// The task to be awaited.
/// The condition we are waiting to apply before moving on.
- Task WaitUntilAsync(Func condition);
+ /// The callback priority (determines the order in which the subscribers get the events).
+ Task WaitUntilAsync(Func condition, CallbackPriority priority = CallbackPriority.Normal);
///
/// Invoke the event synchronously (i.e will wait for all subscribers to process the event before moving on).
diff --git a/Source/AGS.API/Misc/Events/IEvent.cs b/Source/AGS.API/Misc/Events/IEvent.cs
index 0d4e0a10b..0855eb6e4 100644
--- a/Source/AGS.API/Misc/Events/IEvent.cs
+++ b/Source/AGS.API/Misc/Events/IEvent.cs
@@ -21,28 +21,32 @@ public interface IEvent
/// Once subscribed, whenever the event happens this callback will be called.
///
/// Callback.
- void Subscribe(Action callback);
+ /// The callback priority (determines the order in which the subscribers get the events).
+ void Subscribe(Action callback, CallbackPriority priority = CallbackPriority.Normal);
///
/// Unsubscribe the specified callback from the event.
/// This will stops notifications to call this callback.
///
/// Callback.
- void Unsubscribe(Action callback);
+ /// The callback priority (determines the order in which the subscribers get the events).
+ void Unsubscribe(Action callback, CallbackPriority priority = CallbackPriority.Normal);
///
/// Subscribe the specified asynchronous callback to the event.
/// Once subscribed, whenever the event happens this callback will be called.
///
/// Callback.
- void SubscribeToAsync(Func callback);
+ /// The callback priority (determines the order in which the subscribers get the events).
+ void SubscribeToAsync(Func callback, CallbackPriority priority = CallbackPriority.Normal);
///
/// Unsubscribe the specified asynchronous callback from the event.
/// This will stops notifications to call this callback.
///
/// Callback.
- void UnsubscribeToAsync(Func callback);
+ /// The callback priority (determines the order in which the subscribers get the events).
+ void UnsubscribeToAsync(Func callback, CallbackPriority priority = CallbackPriority.Normal);
///
/// Subscribe the specified callback to the event.
@@ -50,14 +54,16 @@ public interface IEvent
/// This version of Subscribe ignores incoming arguments from the event (if you need the arguments, use the other overload which gets an action of TEventArgs).
///
/// Callback.
- void Subscribe(Action callback);
+ /// The callback priority (determines the order in which the subscribers get the events).
+ void Subscribe(Action callback, CallbackPriority priority = CallbackPriority.Normal);
///
/// Unsubscribe the specified callback from the event.
/// This will stops notifications to call this callback.
///
/// Callback.
- void Unsubscribe(Action callback);
+ /// The callback priority (determines the order in which the subscribers get the events).
+ void Unsubscribe(Action callback, CallbackPriority priority = CallbackPriority.Normal);
///
/// Subscribe the specified asynchronous callback to the event.
@@ -65,21 +71,24 @@ public interface IEvent
/// This version of Subscribe ignores incoming arguments from the event (if you need the arguments, use the other overload which gets a func of TEventArgs -> Task).
///
/// Callback.
- void SubscribeToAsync(Func callback);
+ /// The callback priority (determines the order in which the subscribers get the events).
+ void SubscribeToAsync(Func callback, CallbackPriority priority = CallbackPriority.Normal);
///
/// Unsubscribe the specified asynchronous callback from the event.
/// This will stops notifications to call this callback.
///
/// Callback.
- void UnsubscribeToAsync(Func callback);
+ /// The callback priority (determines the order in which the subscribers get the events).
+ void UnsubscribeToAsync(Func callback, CallbackPriority priority = CallbackPriority.Normal);
///
/// Asynchronously wait until the event fires and the specific condition applies.
///
/// The task to be awaited.
/// The condition we are waiting to apply before moving on.
- Task WaitUntilAsync(Predicate condition);
+ /// The callback priority (determines the order in which the subscribers get the events).
+ Task WaitUntilAsync(Predicate condition, CallbackPriority priority = CallbackPriority.Normal);
///
/// Invoke the event asynchronously.
@@ -106,35 +115,40 @@ public interface IEvent
/// Once subscribed, whenever the event happens this callback will be called.
///
/// Callback.
- void Subscribe(Action callback);
+ /// The callback priority (determines the order in which the subscribers get the events).
+ void Subscribe(Action callback, CallbackPriority priority = CallbackPriority.Normal);
///
/// Unsubscribe the specified callback from the event.
/// This will stops notifications to call this callback.
///
/// Callback.
- void Unsubscribe(Action callback);
+ /// The callback priority (determines the order in which the subscribers get the events).
+ void Unsubscribe(Action callback, CallbackPriority priority = CallbackPriority.Normal);
///
/// Subscribe the specified asynchronous callback to the event.
/// Once subscribed, whenever the event happens this callback will be called.
///
/// Callback.
- void SubscribeToAsync(Func callback);
+ /// The callback priority (determines the order in which the subscribers get the events).
+ void SubscribeToAsync(Func callback, CallbackPriority priority = CallbackPriority.Normal);
///
/// Unsubscribe the specified asynchronous callback from the event.
/// This will stops notifications to call this callback.
///
/// Callback.
- void UnsubscribeToAsync(Func callback);
+ /// The callback priority (determines the order in which the subscribers get the events).
+ void UnsubscribeToAsync(Func callback, CallbackPriority priority = CallbackPriority.Normal);
///
/// Asynchronously wait until the event fires and the specific condition applies.
///
/// The task to be awaited.
/// The condition we are waiting to apply before moving on.
- Task WaitUntilAsync(Func condition);
+ /// The callback priority (determines the order in which the subscribers get the events).
+ Task WaitUntilAsync(Func condition, CallbackPriority priority = CallbackPriority.Normal);
///
/// Invoke the event asynchronously.
diff --git a/Source/Engine/AGS.Engine/Misc/Events/AGSEvent.cs b/Source/Engine/AGS.Engine/Misc/Events/AGSEvent.cs
index 5d3d02f6a..afe7cf616 100644
--- a/Source/Engine/AGS.Engine/Misc/Events/AGSEvent.cs
+++ b/Source/Engine/AGS.Engine/Misc/Events/AGSEvent.cs
@@ -6,281 +6,52 @@
namespace AGS.Engine
{
- public class AGSEvent : IEvent, IBlockingEvent
- {
- private readonly IConcurrentHashSet _invocationList;
- private const int MAX_SUBSCRIPTIONS = 10000;
- private int _count;
-
- public AGSEvent ()
- {
- _invocationList = new AGSConcurrentHashSet(fireListChangedEvent: false);
- }
-
- #region IEvent implementation
-
- public int SubscribersCount => _count;
-
- public void Subscribe (Action callback)
- {
- _count++;
- if (_count > MAX_SUBSCRIPTIONS)
- {
- Debug.WriteLine("Subscribe Overflow!");
- return;
- }
- _invocationList.Add (new Callback (callback));
- }
-
- public void Subscribe(Action callback)
- {
- _count++;
- if (_count > MAX_SUBSCRIPTIONS)
- {
- Debug.WriteLine("Subscribe Overflow!");
- return;
- }
- _invocationList.Add(new Callback(callback));
- }
-
- public void Unsubscribe (Action callback)
- {
- if (_invocationList.Remove(new Callback (callback)))
- {
- _count--;
- }
- }
-
- public void Unsubscribe(Action callback)
- {
- if (_invocationList.Remove(new Callback(callback)))
- {
- _count--;
- }
- }
-
- public void SubscribeToAsync (Func callback)
- {
- subscribeToAsync(new Callback (callback));
- }
-
- public void UnsubscribeToAsync (Func callback)
- {
- unsubscribeToAsync(new Callback (callback));
- }
-
- public void SubscribeToAsync(Func callback)
- {
- subscribeToAsync(new Callback(callback));
- }
-
- public void UnsubscribeToAsync(Func callback)
- {
- unsubscribeToAsync(new Callback(callback));
- }
-
- public async Task WaitUntilAsync(Predicate condition)
- {
- TaskCompletionSource