@@ -31,8 +31,20 @@ namespace Exiled.Events.Features
3131 /// </summary>
3232 public class Event : IExiledEvent
3333 {
34+ private record Registration ( CustomEventHandler handler , int priority ) ;
35+
36+ private record AsyncRegistration ( CustomAsyncEventHandler handler , int priority ) ;
37+
3438 private static readonly List < Event > EventsValue = new ( ) ;
3539
40+ private static readonly IComparer < Registration > RegisterComparable = Comparer < Registration > . Create ( ( x , y ) => y . priority - x . priority ) ;
41+
42+ private static readonly IComparer < AsyncRegistration > AsyncRegisterComparable = Comparer < AsyncRegistration > . Create ( ( x , y ) => y . priority - x . priority ) ;
43+
44+ private readonly List < Registration > innerEvent = new ( ) ;
45+
46+ private readonly List < AsyncRegistration > innerAsyncEvent = new ( ) ;
47+
3648 private bool patched ;
3749
3850 /// <summary>
@@ -43,10 +55,6 @@ public Event()
4355 EventsValue . Add ( this ) ;
4456 }
4557
46- private event CustomEventHandler InnerEvent ;
47-
48- private event CustomAsyncEventHandler InnerAsyncEvent ;
49-
5058 /// <summary>
5159 /// Gets a <see cref="IReadOnlyList{T}"/> of <see cref="Event{T}"/> which contains all the <see cref="Event{T}"/> instances.
5260 /// </summary>
@@ -105,6 +113,14 @@ public Event()
105113 /// </summary>
106114 /// <param name="handler">The handler to add.</param>
107115 public void Subscribe ( CustomEventHandler handler )
116+ => Subscribe ( handler , 0 ) ;
117+
118+ /// <summary>
119+ /// Subscribes a target <see cref="CustomEventHandler"/> to the inner event if the conditional is true.
120+ /// </summary>
121+ /// <param name="handler">The handler to add.</param>
122+ /// <param name="priority">The highest priority is the first called, the lowest the last.</param>
123+ public void Subscribe ( CustomEventHandler handler , int priority )
108124 {
109125 Log . Assert ( Events . Instance is not null , $ "{ nameof ( Events . Instance ) } is null, please ensure you have exiled_events enabled!") ;
110126
@@ -114,14 +130,36 @@ public void Subscribe(CustomEventHandler handler)
114130 patched = true ;
115131 }
116132
117- InnerEvent += handler ;
133+ if ( handler == null )
134+ return ;
135+
136+ Registration registration = new Registration ( handler , priority ) ;
137+ int index = innerEvent . BinarySearch ( registration , RegisterComparable ) ;
138+ if ( index < 0 )
139+ {
140+ innerEvent . Insert ( ~ index , registration ) ;
141+ }
142+ else
143+ {
144+ while ( index < innerEvent . Count && innerEvent [ index ] . priority == priority )
145+ index ++ ;
146+ innerEvent . Insert ( index , registration ) ;
147+ }
118148 }
119149
120150 /// <summary>
121151 /// Subscribes a target <see cref="CustomAsyncEventHandler"/> to the inner event if the conditional is true.
122152 /// </summary>
123153 /// <param name="handler">The handler to add.</param>
124154 public void Subscribe ( CustomAsyncEventHandler handler )
155+ => Subscribe ( handler , 0 ) ;
156+
157+ /// <summary>
158+ /// Subscribes a target <see cref="CustomAsyncEventHandler"/> to the inner event if the conditional is true.
159+ /// </summary>
160+ /// <param name="handler">The handler to add.</param>
161+ /// <param name="priority">The highest priority is the first called, the lowest the last.</param>
162+ public void Subscribe ( CustomAsyncEventHandler handler , int priority )
125163 {
126164 Log . Assert ( Events . Instance is not null , $ "{ nameof ( Events . Instance ) } is null, please ensure you have exiled_events enabled!") ;
127165
@@ -131,7 +169,21 @@ public void Subscribe(CustomAsyncEventHandler handler)
131169 patched = true ;
132170 }
133171
134- InnerAsyncEvent += handler ;
172+ if ( handler == null )
173+ return ;
174+
175+ AsyncRegistration registration = new AsyncRegistration ( handler , 0 ) ;
176+ int index = innerAsyncEvent . BinarySearch ( registration , AsyncRegisterComparable ) ;
177+ if ( index < 0 )
178+ {
179+ innerAsyncEvent . Insert ( ~ index , registration ) ;
180+ }
181+ else
182+ {
183+ while ( index < innerAsyncEvent . Count && innerAsyncEvent [ index ] . priority == priority )
184+ index ++ ;
185+ innerAsyncEvent . Insert ( index , registration ) ;
186+ }
135187 }
136188
137189 /// <summary>
@@ -140,7 +192,9 @@ public void Subscribe(CustomAsyncEventHandler handler)
140192 /// <param name="handler">The handler to add.</param>
141193 public void Unsubscribe ( CustomEventHandler handler )
142194 {
143- InnerEvent -= handler ;
195+ int index = innerEvent . FindIndex ( p => p . handler == handler ) ;
196+ if ( index != - 1 )
197+ innerEvent . RemoveAt ( index ) ;
144198 }
145199
146200 /// <summary>
@@ -149,52 +203,88 @@ public void Unsubscribe(CustomEventHandler handler)
149203 /// <param name="handler">The handler to add.</param>
150204 public void Unsubscribe ( CustomAsyncEventHandler handler )
151205 {
152- InnerAsyncEvent -= handler ;
206+ int index = innerAsyncEvent . FindIndex ( p => p . handler == handler ) ;
207+ if ( index != - 1 )
208+ innerAsyncEvent . RemoveAt ( index ) ;
153209 }
154210
155211 /// <summary>
156212 /// Executes all <see cref="CustomEventHandler"/> listeners safely.
157213 /// </summary>
158214 public void InvokeSafely ( )
159215 {
160- InvokeNormal ( ) ;
161- InvokeAsync ( ) ;
216+ BlendedInvoke ( ) ;
162217 }
163218
164219 /// <inheritdoc cref="InvokeSafely"/>
165- internal void InvokeNormal ( )
220+ internal void BlendedInvoke ( )
166221 {
167- if ( InnerEvent is null )
168- return ;
222+ Registration [ ] innerEvent = this . innerEvent . ToArray ( ) ;
223+ AsyncRegistration [ ] innerAsyncEvent = this . innerAsyncEvent . ToArray ( ) ;
224+ int count = innerEvent . Length + innerAsyncEvent . Length ;
225+ int eventIndex = 0 , asyncEventIndex = 0 ;
169226
170- foreach ( CustomEventHandler handler in InnerEvent . GetInvocationList ( ) . Cast < CustomEventHandler > ( ) )
227+ for ( int i = 0 ; i < count ; i ++ )
228+ {
229+ if ( eventIndex < innerEvent . Length && ( asyncEventIndex >= innerAsyncEvent . Length || innerEvent [ eventIndex ] . priority >= innerAsyncEvent [ asyncEventIndex ] . priority ) )
230+ {
231+ try
232+ {
233+ innerEvent [ eventIndex ] . handler ( ) ;
234+ }
235+ catch ( Exception ex )
236+ {
237+ Log . Error ( $ "Method \" { innerEvent [ eventIndex ] . handler . Method . Name } \" of the class \" { innerEvent [ eventIndex ] . handler . Method . ReflectedType . FullName } \" caused an exception when handling the event \" { GetType ( ) . FullName } \" \n { ex } ") ;
238+ }
239+
240+ eventIndex ++ ;
241+ }
242+ else
243+ {
244+ try
245+ {
246+ Timing . RunCoroutine ( innerAsyncEvent [ asyncEventIndex ] . handler ( ) ) ;
247+ }
248+ catch ( Exception ex )
249+ {
250+ Log . Error ( $ "Method \" { innerAsyncEvent [ asyncEventIndex ] . handler . Method . Name } \" of the class \" { innerAsyncEvent [ asyncEventIndex ] . handler . Method . ReflectedType . FullName } \" caused an exception when handling the event \" { GetType ( ) . FullName } \" \n { ex } ") ;
251+ }
252+
253+ asyncEventIndex ++ ;
254+ }
255+ }
256+ }
257+
258+ /// <inheritdoc cref="InvokeSafely"/>
259+ internal void InvokeNormal ( )
260+ {
261+ Registration [ ] innerEvent = this . innerEvent . ToArray ( ) ;
262+ foreach ( Registration registration in innerEvent )
171263 {
172264 try
173265 {
174- handler ( ) ;
266+ registration . handler ( ) ;
175267 }
176268 catch ( Exception ex )
177269 {
178- Log . Error ( $ "Method \" { handler . Method . Name } \" of the class \" { handler . Method . ReflectedType . FullName } \" caused an exception when handling the event \" { GetType ( ) . FullName } \" \n { ex } ") ;
270+ Log . Error ( $ "Method \" { registration . handler . Method . Name } \" of the class \" { registration . handler . Method . ReflectedType . FullName } \" caused an exception when handling the event \" { GetType ( ) . FullName } \" \n { ex } ") ;
179271 }
180272 }
181273 }
182274
183275 /// <inheritdoc cref="InvokeSafely"/>
184276 internal void InvokeAsync ( )
185277 {
186- if ( InnerAsyncEvent is null )
187- return ;
188-
189- foreach ( CustomAsyncEventHandler handler in InnerAsyncEvent . GetInvocationList ( ) . Cast < CustomAsyncEventHandler > ( ) )
278+ AsyncRegistration [ ] innerAsyncEvent = this . innerAsyncEvent . ToArray ( ) ;
279+ foreach ( AsyncRegistration registration in innerAsyncEvent )
190280 {
191281 try
192282 {
193- Timing . RunCoroutine ( handler ( ) ) ;
283+ Timing . RunCoroutine ( registration . handler ( ) ) ;
194284 }
195285 catch ( Exception ex )
196286 {
197- Log . Error ( $ "Method \" { handler . Method . Name } \" of the class \" { handler . Method . ReflectedType . FullName } \" caused an exception when handling the event \" { GetType ( ) . FullName } \" \n { ex } ") ;
287+ Log . Error ( $ "Method \" { registration . handler . Method . Name } \" of the class \" { registration . handler . Method . ReflectedType . FullName } \" caused an exception when handling the event \" { GetType ( ) . FullName } \" \n { ex } ") ;
198288 }
199289 }
200290 }
0 commit comments