com.wallstop-studios.dxmessaging 2.0.0-rc07 → 2.0.0-rc09

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1333,45 +1333,42 @@
1333
1333
 
1334
1334
  private Dictionary<
1335
1335
  InstanceId,
1336
- SortedDictionary<int, Dictionary<Action<T>, int>>
1336
+ Dictionary<int, Dictionary<Action<T>, int>>
1337
1337
  > _targetedHandlers;
1338
- private SortedDictionary<int, Dictionary<Action<T>, int>> _untargetedHandlers;
1338
+ private Dictionary<int, Dictionary<Action<T>, int>> _untargetedHandlers;
1339
1339
  private Dictionary<
1340
1340
  InstanceId,
1341
- SortedDictionary<int, Dictionary<Action<T>, int>>
1341
+ Dictionary<int, Dictionary<Action<T>, int>>
1342
1342
  > _broadcastHandlers;
1343
1343
  private Dictionary<
1344
1344
  InstanceId,
1345
- SortedDictionary<int, Dictionary<Action<T>, int>>
1345
+ Dictionary<int, Dictionary<Action<T>, int>>
1346
1346
  > _targetedPostProcessingHandlers;
1347
- private SortedDictionary<
1348
- int,
1349
- Dictionary<Action<T>, int>
1350
- > _untargetedPostProcessingHandlers;
1347
+ private Dictionary<int, Dictionary<Action<T>, int>> _untargetedPostProcessingHandlers;
1351
1348
  private Dictionary<
1352
1349
  InstanceId,
1353
- SortedDictionary<int, Dictionary<Action<T>, int>>
1350
+ Dictionary<int, Dictionary<Action<T>, int>>
1354
1351
  > _broadcastPostProcessingHandlers;
1355
1352
  private Dictionary<
1356
1353
  InstanceId,
1357
- SortedDictionary<int, Dictionary<FastHandler<T>, int>>
1354
+ Dictionary<int, Dictionary<FastHandler<T>, int>>
1358
1355
  > _targetedFastHandlers;
1359
- private SortedDictionary<int, Dictionary<FastHandler<T>, int>> _untargetedFastHandlers;
1356
+ private Dictionary<int, Dictionary<FastHandler<T>, int>> _untargetedFastHandlers;
1360
1357
  private Dictionary<
1361
1358
  InstanceId,
1362
- SortedDictionary<int, Dictionary<FastHandler<T>, int>>
1359
+ Dictionary<int, Dictionary<FastHandler<T>, int>>
1363
1360
  > _broadcastFastHandlers;
1364
1361
  private Dictionary<
1365
1362
  InstanceId,
1366
- SortedDictionary<int, Dictionary<FastHandler<T>, int>>
1363
+ Dictionary<int, Dictionary<FastHandler<T>, int>>
1367
1364
  > _targetedPostProcessingFastHandlers;
1368
- private SortedDictionary<
1365
+ private Dictionary<
1369
1366
  int,
1370
1367
  Dictionary<FastHandler<T>, int>
1371
1368
  > _untargetedPostProcessingFastHandlers;
1372
1369
  private Dictionary<
1373
1370
  InstanceId,
1374
- SortedDictionary<int, Dictionary<FastHandler<T>, int>>
1371
+ Dictionary<int, Dictionary<FastHandler<T>, int>>
1375
1372
  > _broadcastPostProcessingFastHandlers;
1376
1373
  private Dictionary<Action<IUntargetedMessage>, int> _globalUntargetedHandlers;
1377
1374
  private Dictionary<Action<InstanceId, ITargetedMessage>, int> _globalTargetedHandlers;
@@ -1385,35 +1382,35 @@
1385
1382
  FastHandlerWithContext<IBroadcastMessage>,
1386
1383
  int
1387
1384
  > _globalBroadcastFastHandlers;
1388
- private SortedDictionary<
1385
+ private Dictionary<
1389
1386
  int,
1390
1387
  Dictionary<Action<InstanceId, T>, int>
1391
1388
  > _targetedWithoutTargetingHandlers;
1392
- private SortedDictionary<
1389
+ private Dictionary<
1393
1390
  int,
1394
1391
  Dictionary<FastHandlerWithContext<T>, int>
1395
1392
  > _fastTargetedWithoutTargetingHandlers;
1396
- private SortedDictionary<
1393
+ private Dictionary<
1397
1394
  int,
1398
1395
  Dictionary<Action<InstanceId, T>, int>
1399
1396
  > _broadcastWithoutSourceHandlers;
1400
- private SortedDictionary<
1397
+ private Dictionary<
1401
1398
  int,
1402
1399
  Dictionary<FastHandlerWithContext<T>, int>
1403
1400
  > _fastBroadcastWithoutSourceHandlers;
1404
- private SortedDictionary<
1401
+ private Dictionary<
1405
1402
  int,
1406
1403
  Dictionary<Action<InstanceId, T>, int>
1407
1404
  > _targetedWithoutTargetingPostProcessingHandlers;
1408
- private SortedDictionary<
1405
+ private Dictionary<
1409
1406
  int,
1410
1407
  Dictionary<FastHandlerWithContext<T>, int>
1411
1408
  > _fastTargetedWithoutTargetingPostProcessingHandlers;
1412
- private SortedDictionary<
1409
+ private Dictionary<
1413
1410
  int,
1414
1411
  Dictionary<Action<InstanceId, T>, int>
1415
1412
  > _broadcastWithoutSourcePostProcessingHandlers;
1416
- private SortedDictionary<
1413
+ private Dictionary<
1417
1414
  int,
1418
1415
  Dictionary<FastHandlerWithContext<T>, int>
1419
1416
  > _fastBroadcastWithoutSourcePostProcessingHandlers;
@@ -2249,10 +2246,7 @@
2249
2246
 
2250
2247
  private static void RunFastHandlersWithContext<TMessage>(
2251
2248
  ref InstanceId context,
2252
- SortedDictionary<
2253
- int,
2254
- Dictionary<FastHandlerWithContext<T>, int>
2255
- > fastHandlersByContext,
2249
+ Dictionary<int, Dictionary<FastHandlerWithContext<T>, int>> fastHandlersByContext,
2256
2250
  ref TMessage message,
2257
2251
  int priority
2258
2252
  )
@@ -2276,7 +2270,7 @@
2276
2270
  ref InstanceId context,
2277
2271
  Dictionary<
2278
2272
  InstanceId,
2279
- SortedDictionary<int, Dictionary<FastHandler<T>, int>>
2273
+ Dictionary<int, Dictionary<FastHandler<T>, int>>
2280
2274
  > fastHandlersByContext,
2281
2275
  ref TMessage message,
2282
2276
  int priority
@@ -2287,7 +2281,7 @@
2287
2281
  fastHandlersByContext is not { Count: > 0 }
2288
2282
  || !fastHandlersByContext.TryGetValue(
2289
2283
  context,
2290
- out SortedDictionary<int, Dictionary<FastHandler<T>, int>> fastHandlers
2284
+ out Dictionary<int, Dictionary<FastHandler<T>, int>> fastHandlers
2291
2285
  )
2292
2286
  )
2293
2287
  {
@@ -2298,7 +2292,7 @@
2298
2292
  }
2299
2293
 
2300
2294
  private static void RunFastHandlers<TMessage>(
2301
- SortedDictionary<int, Dictionary<FastHandler<T>, int>> fastHandlers,
2295
+ Dictionary<int, Dictionary<FastHandler<T>, int>> fastHandlers,
2302
2296
  ref TMessage message,
2303
2297
  int priority
2304
2298
  )
@@ -2406,7 +2400,7 @@
2406
2400
  private static void RunFastHandlers<TMessage, U>(
2407
2401
  ref InstanceId context,
2408
2402
  ref Stack<List<FastHandlerWithContext<U>>> stack,
2409
- SortedDictionary<int, Dictionary<FastHandlerWithContext<U>, int>> fastHandlers,
2403
+ Dictionary<int, Dictionary<FastHandlerWithContext<U>, int>> fastHandlers,
2410
2404
  ref TMessage message,
2411
2405
  int priority
2412
2406
  )
@@ -2451,7 +2445,7 @@
2451
2445
  ref InstanceId context,
2452
2446
  Dictionary<
2453
2447
  InstanceId,
2454
- SortedDictionary<int, Dictionary<Action<T>, int>>
2448
+ Dictionary<int, Dictionary<Action<T>, int>>
2455
2449
  > handlersByContext,
2456
2450
  ref TMessage message,
2457
2451
  int priority
@@ -2462,7 +2456,7 @@
2462
2456
  handlersByContext is not { Count: > 0 }
2463
2457
  || !handlersByContext.TryGetValue(
2464
2458
  context,
2465
- out SortedDictionary<int, Dictionary<Action<T>, int>> handlers
2459
+ out Dictionary<int, Dictionary<Action<T>, int>> handlers
2466
2460
  )
2467
2461
  )
2468
2462
  {
@@ -2473,7 +2467,7 @@
2473
2467
  }
2474
2468
 
2475
2469
  private static void RunHandlers<TMessage>(
2476
- SortedDictionary<int, Dictionary<Action<T>, int>> sortedHandlers,
2470
+ Dictionary<int, Dictionary<Action<T>, int>> sortedHandlers,
2477
2471
  ref TMessage message,
2478
2472
  int priority
2479
2473
  )
@@ -2510,7 +2504,7 @@
2510
2504
 
2511
2505
  private static void RunHandlers<TMessage>(
2512
2506
  ref InstanceId context,
2513
- SortedDictionary<int, Dictionary<Action<InstanceId, T>, int>> handlers,
2507
+ Dictionary<int, Dictionary<Action<InstanceId, T>, int>> handlers,
2514
2508
  ref TMessage message,
2515
2509
  int priority
2516
2510
  )
@@ -2568,26 +2562,23 @@
2568
2562
 
2569
2563
  private static Action AddHandler<U>(
2570
2564
  InstanceId context,
2571
- ref Dictionary<
2572
- InstanceId,
2573
- SortedDictionary<int, Dictionary<U, int>>
2574
- > handlersByContext,
2565
+ ref Dictionary<InstanceId, Dictionary<int, Dictionary<U, int>>> handlersByContext,
2575
2566
  U handler,
2576
2567
  Action deregistration,
2577
2568
  int priority
2578
2569
  )
2579
2570
  {
2580
2571
  handlersByContext ??=
2581
- new Dictionary<InstanceId, SortedDictionary<int, Dictionary<U, int>>>();
2572
+ new Dictionary<InstanceId, Dictionary<int, Dictionary<U, int>>>();
2582
2573
 
2583
2574
  if (
2584
2575
  !handlersByContext.TryGetValue(
2585
2576
  context,
2586
- out SortedDictionary<int, Dictionary<U, int>> sortedHandlers
2577
+ out Dictionary<int, Dictionary<U, int>> sortedHandlers
2587
2578
  )
2588
2579
  )
2589
2580
  {
2590
- sortedHandlers = new SortedDictionary<int, Dictionary<U, int>>();
2581
+ sortedHandlers = new Dictionary<int, Dictionary<U, int>>();
2591
2582
  handlersByContext[context] = sortedHandlers;
2592
2583
  }
2593
2584
 
@@ -2601,10 +2592,8 @@
2601
2592
 
2602
2593
  handlers[handler] = count + 1;
2603
2594
 
2604
- Dictionary<
2605
- InstanceId,
2606
- SortedDictionary<int, Dictionary<U, int>>
2607
- > localHandlersByContext = handlersByContext;
2595
+ Dictionary<InstanceId, Dictionary<int, Dictionary<U, int>>> localHandlersByContext =
2596
+ handlersByContext;
2608
2597
 
2609
2598
  return () =>
2610
2599
  {
@@ -2675,13 +2664,13 @@
2675
2664
  }
2676
2665
 
2677
2666
  private static Action AddHandler<U>(
2678
- ref SortedDictionary<int, Dictionary<U, int>> sortedHandlers,
2667
+ ref Dictionary<int, Dictionary<U, int>> sortedHandlers,
2679
2668
  U handler,
2680
2669
  Action deregistration,
2681
2670
  int priority
2682
2671
  )
2683
2672
  {
2684
- sortedHandlers ??= new SortedDictionary<int, Dictionary<U, int>>();
2673
+ sortedHandlers ??= new Dictionary<int, Dictionary<U, int>>();
2685
2674
 
2686
2675
  if (
2687
2676
  !sortedHandlers.TryGetValue(priority, out Dictionary<U, int> handlersByPriority)
@@ -2695,7 +2684,7 @@
2695
2684
 
2696
2685
  handlersByPriority[handler] = count + 1;
2697
2686
 
2698
- SortedDictionary<int, Dictionary<U, int>> localSortedHandlers = sortedHandlers;
2687
+ Dictionary<int, Dictionary<U, int>> localSortedHandlers = sortedHandlers;
2699
2688
  Dictionary<U, int> localHandlers = handlersByPriority;
2700
2689
 
2701
2690
  return () =>
@@ -6,6 +6,7 @@
6
6
  using Core;
7
7
  using DxMessaging.Core;
8
8
  using DxMessaging.Core.Extensions;
9
+ using global::Unity.PerformanceTesting;
9
10
  using NUnit.Framework;
10
11
  using Scripts.Components;
11
12
  using Scripts.Messages;
@@ -20,7 +21,7 @@
20
21
  public override void Setup()
21
22
  {
22
23
  base.Setup();
23
- MessagingDebug.LogFunction = (_1, _2) => { };
24
+ MessagingDebug.LogFunction = (_, _) => { };
24
25
  }
25
26
 
26
27
  [UnityTest]
@@ -39,23 +40,109 @@
39
40
  RunTest(component => NormalComponent(timer, timeout, component, message));
40
41
  RunTest(component => NoCopyGameObject(timer, timeout, component, message));
41
42
  RunTest(component => NoCopyComponent(timer, timeout, component, message));
42
-
43
+
43
44
  SimpleUntargetedMessage untargetedMessage = new();
44
45
  RunTest(component => NoCopyUntargeted(timer, timeout, component, untargetedMessage));
45
46
  yield break;
46
47
  }
47
48
 
49
+ [UnityTest]
50
+ [Performance]
51
+ public IEnumerator BenchmarkBroadcast()
52
+ {
53
+ GameObject go = CreateGameObject();
54
+ MessageRegistrationToken token = GetToken(
55
+ go.GetComponent<EmptyMessageAwareComponent>()
56
+ );
57
+ int count = 0;
58
+ token.RegisterGameObjectBroadcast<SimpleBroadcastMessage>(go, Handle);
59
+
60
+ SimpleBroadcastMessage message = new();
61
+
62
+ Measure
63
+ .Method(() => message.EmitGameObjectBroadcast(go))
64
+ .WarmupCount(10)
65
+ .IterationsPerMeasurement(10)
66
+ .MeasurementCount(1_000)
67
+ .Run();
68
+ yield break;
69
+
70
+ void Handle(SimpleBroadcastMessage _)
71
+ {
72
+ ++count;
73
+ }
74
+ }
75
+
76
+ [UnityTest]
77
+ [Performance]
78
+ public IEnumerator BenchmarkTargeted()
79
+ {
80
+ GameObject go = CreateGameObject();
81
+ MessageRegistrationToken token = GetToken(
82
+ go.GetComponent<EmptyMessageAwareComponent>()
83
+ );
84
+ int count = 0;
85
+ token.RegisterGameObjectTargeted<SimpleTargetedMessage>(go, Handle);
86
+
87
+ SimpleTargetedMessage message = new();
88
+
89
+ Measure
90
+ .Method(() => message.EmitGameObjectTargeted(go))
91
+ .WarmupCount(10)
92
+ .IterationsPerMeasurement(10)
93
+ .MeasurementCount(1_000)
94
+ .Run();
95
+ yield break;
96
+
97
+ void Handle(SimpleTargetedMessage _)
98
+ {
99
+ ++count;
100
+ }
101
+ }
102
+
103
+ [UnityTest]
104
+ [Performance]
105
+ public IEnumerator BenchmarkUntargeted()
106
+ {
107
+ GameObject go = CreateGameObject();
108
+ MessageRegistrationToken token = GetToken(
109
+ go.GetComponent<EmptyMessageAwareComponent>()
110
+ );
111
+ int count = 0;
112
+ token.RegisterUntargeted<SimpleUntargetedMessage>(Handle);
113
+
114
+ SimpleUntargetedMessage message = new();
115
+
116
+ Measure
117
+ .Method(() => message.EmitUntargeted())
118
+ .WarmupCount(10)
119
+ .IterationsPerMeasurement(10)
120
+ .MeasurementCount(1_000)
121
+ .Run();
122
+ yield break;
123
+
124
+ void Handle(SimpleUntargetedMessage _)
125
+ {
126
+ ++count;
127
+ }
128
+ }
129
+
48
130
  private GameObject CreateGameObject()
49
131
  {
50
132
  GameObject target = new(
51
- nameof(Benchmark), typeof(EmptyMessageAwareComponent), typeof(SpriteRenderer),
52
- typeof(Rigidbody2D), typeof(CircleCollider2D), typeof(LineRenderer));
133
+ nameof(Benchmark),
134
+ typeof(EmptyMessageAwareComponent),
135
+ typeof(SpriteRenderer),
136
+ typeof(Rigidbody2D),
137
+ typeof(CircleCollider2D),
138
+ typeof(LineRenderer)
139
+ );
53
140
  _spawned.Add(target);
54
141
 
55
142
  return target;
56
143
  }
57
144
 
58
- private void DisplayCount(string testName, int count, TimeSpan timeout)
145
+ private static void DisplayCount(string testName, int count, TimeSpan timeout)
59
146
  {
60
147
  Debug.Log($"| {testName} | {Math.Floor(count / timeout.TotalSeconds):N0} |");
61
148
  }
@@ -74,7 +161,12 @@
74
161
  }
75
162
  }
76
163
 
77
- private void Unity(Stopwatch timer, TimeSpan timeout, GameObject target, ComplexTargetedMessage message)
164
+ private static void Unity(
165
+ Stopwatch timer,
166
+ TimeSpan timeout,
167
+ GameObject target,
168
+ ComplexTargetedMessage message
169
+ )
78
170
  {
79
171
  int count = 0;
80
172
  var component = target.AddComponent<SimpleMessageAwareComponent>();
@@ -82,13 +174,20 @@
82
174
  timer.Restart();
83
175
  do
84
176
  {
85
- target.SendMessage(nameof(SimpleMessageAwareComponent.HandleSlowComplexTargetedMessage), message);
86
- }
87
- while (timer.Elapsed < timeout);
177
+ target.SendMessage(
178
+ nameof(SimpleMessageAwareComponent.HandleSlowComplexTargetedMessage),
179
+ message
180
+ );
181
+ } while (timer.Elapsed < timeout);
88
182
  DisplayCount("Unity", count, timeout);
89
183
  }
90
184
 
91
- private void NormalGameObject(Stopwatch timer, TimeSpan timeout, EmptyMessageAwareComponent component, ComplexTargetedMessage message)
185
+ private void NormalGameObject(
186
+ Stopwatch timer,
187
+ TimeSpan timeout,
188
+ EmptyMessageAwareComponent component,
189
+ ComplexTargetedMessage message
190
+ )
92
191
  {
93
192
  int count = 0;
94
193
  var token = GetToken(component);
@@ -104,12 +203,16 @@
104
203
  do
105
204
  {
106
205
  message.EmitGameObjectTargeted(go);
107
- }
108
- while (timer.Elapsed < timeout);
206
+ } while (timer.Elapsed < timeout);
109
207
  DisplayCount("DxMessaging (GameObject) - Normal", count, timeout);
110
208
  }
111
209
 
112
- private void NormalComponent(Stopwatch timer, TimeSpan timeout, EmptyMessageAwareComponent component, ComplexTargetedMessage message)
210
+ private void NormalComponent(
211
+ Stopwatch timer,
212
+ TimeSpan timeout,
213
+ EmptyMessageAwareComponent component,
214
+ ComplexTargetedMessage message
215
+ )
113
216
  {
114
217
  int count = 0;
115
218
  var token = GetToken(component);
@@ -124,12 +227,16 @@
124
227
  do
125
228
  {
126
229
  message.EmitComponentTargeted(component);
127
- }
128
- while (timer.Elapsed < timeout);
230
+ } while (timer.Elapsed < timeout);
129
231
  DisplayCount("DxMessaging (Component) - Normal", count, timeout);
130
232
  }
131
233
 
132
- private void NoCopyGameObject(Stopwatch timer, TimeSpan timeout, EmptyMessageAwareComponent component, ComplexTargetedMessage message)
234
+ private void NoCopyGameObject(
235
+ Stopwatch timer,
236
+ TimeSpan timeout,
237
+ EmptyMessageAwareComponent component,
238
+ ComplexTargetedMessage message
239
+ )
133
240
  {
134
241
  int count = 0;
135
242
  var token = GetToken(component);
@@ -146,12 +253,16 @@
146
253
  do
147
254
  {
148
255
  message.EmitGameObjectTargeted(component.gameObject);
149
- }
150
- while (timer.Elapsed < timeout);
256
+ } while (timer.Elapsed < timeout);
151
257
  DisplayCount("DxMessaging (GameObject) - No-Copy", count, timeout);
152
258
  }
153
259
 
154
- private void NoCopyComponent(Stopwatch timer, TimeSpan timeout, EmptyMessageAwareComponent component, ComplexTargetedMessage message)
260
+ private void NoCopyComponent(
261
+ Stopwatch timer,
262
+ TimeSpan timeout,
263
+ EmptyMessageAwareComponent component,
264
+ ComplexTargetedMessage message
265
+ )
155
266
  {
156
267
  int count = 0;
157
268
  var token = GetToken(component);
@@ -167,12 +278,16 @@
167
278
  do
168
279
  {
169
280
  message.EmitComponentTargeted(component);
170
- }
171
- while (timer.Elapsed < timeout);
281
+ } while (timer.Elapsed < timeout);
172
282
  DisplayCount("DxMessaging (Component) - No-Copy", count, timeout);
173
283
  }
174
284
 
175
- private void NoCopyUntargeted(Stopwatch timer, TimeSpan timeout, EmptyMessageAwareComponent component, SimpleUntargetedMessage message)
285
+ private void NoCopyUntargeted(
286
+ Stopwatch timer,
287
+ TimeSpan timeout,
288
+ EmptyMessageAwareComponent component,
289
+ SimpleUntargetedMessage message
290
+ )
176
291
  {
177
292
  int count = 0;
178
293
  var token = GetToken(component);
@@ -188,9 +303,8 @@
188
303
  do
189
304
  {
190
305
  message.EmitUntargeted();
191
- }
192
- while (timer.Elapsed < timeout);
306
+ } while (timer.Elapsed < timeout);
193
307
  DisplayCount("DxMessaging (Untargeted) - No-Copy", count, timeout);
194
308
  }
195
309
  }
196
- }
310
+ }
@@ -727,6 +727,10 @@
727
727
  {
728
728
  Assert.AreEqual(previous + 1, received[priority - 1]);
729
729
  }
730
+ for (int j = priority + 1; j < received.Length; ++j)
731
+ {
732
+ Assert.AreEqual(previous, received[j]);
733
+ }
730
734
  },
731
735
  priority: priority
732
736
  );
@@ -740,6 +744,10 @@
740
744
  {
741
745
  Assert.AreEqual(previous + 1, received[priority - 1]);
742
746
  }
747
+ for (int j = priority + 1; j < received.Length; ++j)
748
+ {
749
+ Assert.AreEqual(previous, received[j]);
750
+ }
743
751
  },
744
752
  priority: priority
745
753
  );
@@ -786,9 +794,13 @@
786
794
  (ref SimpleBroadcastMessage _) =>
787
795
  {
788
796
  int previous = received[priority]++;
789
- if (0 < priority)
797
+ for (int j = priority - 1; j >= 0; --j)
790
798
  {
791
- Assert.AreEqual(previous + 1, received[priority - 1]);
799
+ Assert.AreEqual(previous + 1, received[j]);
800
+ }
801
+ for (int j = priority + 1; j < received.Length; ++j)
802
+ {
803
+ Assert.AreEqual(previous, received[j]);
792
804
  }
793
805
  },
794
806
  priority: priority
@@ -799,9 +811,14 @@
799
811
  {
800
812
  int previous = received[priority]++;
801
813
  Assert.AreEqual(1, previous % 2);
802
- if (0 < priority)
814
+ for (int j = priority - 1; j >= 0; --j)
803
815
  {
804
- Assert.AreEqual(previous + 1, received[priority - 1]);
816
+ Assert.AreEqual(previous + 1, received[j]);
817
+ }
818
+
819
+ for (int j = priority + 1; j < received.Length; ++j)
820
+ {
821
+ Assert.AreEqual(previous, received[j]);
805
822
  }
806
823
  },
807
824
  priority: priority
@@ -828,5 +845,55 @@
828
845
  Assert.AreEqual(numRuns * 2, received.Distinct().Single());
829
846
  yield break;
830
847
  }
848
+
849
+ [UnityTest]
850
+ public IEnumerator Interceptor()
851
+ {
852
+ GameObject test = new(nameof(Interceptor), typeof(EmptyMessageAwareComponent));
853
+ _spawned.Add(test);
854
+
855
+ int[] received = new int[100];
856
+ EmptyMessageAwareComponent component = test.GetComponent<EmptyMessageAwareComponent>();
857
+ MessageRegistrationToken token = GetToken(component);
858
+ for (int i = 0; i < received.Length; ++i)
859
+ {
860
+ int priority = i;
861
+ token.RegisterBroadcastInterceptor(
862
+ (ref InstanceId source, ref SimpleBroadcastMessage _) =>
863
+ {
864
+ int previous = received[priority]++;
865
+ for (int j = priority - 1; j >= 0; --j)
866
+ {
867
+ Assert.AreEqual(previous + 1, received[j]);
868
+ }
869
+ for (int j = priority + 1; j < received.Length; ++j)
870
+ {
871
+ Assert.AreEqual(previous, received[j]);
872
+ }
873
+
874
+ return true;
875
+ },
876
+ priority: priority
877
+ );
878
+ }
879
+
880
+ SimpleBroadcastMessage message = new();
881
+ const int numRuns = 100;
882
+ for (int i = 0; i < numRuns; ++i)
883
+ {
884
+ message.EmitComponentBroadcast(component);
885
+ message.EmitGameObjectBroadcast(test);
886
+ }
887
+
888
+ Assert.AreEqual(
889
+ 1,
890
+ received.Distinct().Count(),
891
+ "Expected received to be uniform, found: [{0}].",
892
+ string.Join(",", received.Distinct().OrderBy(x => x))
893
+ );
894
+
895
+ Assert.AreEqual(numRuns * 2, received.Distinct().Single());
896
+ yield break;
897
+ }
831
898
  }
832
899
  }