com.wallstop-studios.dxmessaging 2.1.2 → 2.1.3

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.
Files changed (60) hide show
  1. package/.github/workflows/dotnet-tests.yml +1 -1
  2. package/AGENTS.md +12 -12
  3. package/Docs/Comparisons.md +5 -5
  4. package/Docs/InterceptorsAndOrdering.md +1 -1
  5. package/Docs/Performance.md +13 -13
  6. package/Docs/QuickReference.md +1 -1
  7. package/Docs/Reference.md +5 -5
  8. package/Editor/Analyzers/WallstopStudios.DxMessaging.SourceGenerators.dll +0 -0
  9. package/Editor/CustomEditors/MessagingComponentEditor.cs +3 -0
  10. package/Editor/DxMessagingEditorInitializer.cs +58 -1
  11. package/Editor/DxMessagingMenu.cs +38 -0
  12. package/Editor/DxMessagingMenu.cs.meta +11 -0
  13. package/Editor/DxMessagingSceneBuildProcessor.cs +81 -0
  14. package/Editor/DxMessagingSceneBuildProcessor.cs.meta +11 -0
  15. package/Editor/Settings/DxMessagingSettings.cs +37 -6
  16. package/Editor/Settings/DxMessagingSettingsProvider.cs +45 -7
  17. package/README.md +1 -1
  18. package/Runtime/Core/Attributes/DxOptionalParameterAttribute.cs +52 -0
  19. package/Runtime/Core/DataStructure/CyclicBuffer.cs +16 -0
  20. package/Runtime/Core/Diagnostics/MessageEmissionData.cs +1 -1
  21. package/Runtime/Core/Diagnostics/MessageRegistrationType.cs +62 -0
  22. package/Runtime/Core/DxMessagingStaticState.cs +108 -0
  23. package/Runtime/Core/DxMessagingStaticState.cs.meta +11 -0
  24. package/Runtime/Core/Extensions/IListExtensions.cs +24 -0
  25. package/Runtime/Core/Extensions/MessageBusExtensions.cs +142 -0
  26. package/Runtime/Core/Helper/MessageCache.cs +16 -0
  27. package/Runtime/Core/Helper/MessageHelperIndexer.cs +77 -0
  28. package/Runtime/Core/InstanceId.cs +86 -0
  29. package/Runtime/Core/MessageBus/DiagnosticsTarget.cs +31 -0
  30. package/Runtime/Core/MessageBus/DiagnosticsTarget.cs.meta +11 -0
  31. package/Runtime/Core/MessageBus/IMessageBus.cs +44 -16
  32. package/Runtime/Core/MessageBus/MessageBus.cs +92 -21
  33. package/Runtime/Core/MessageBus/MessageRegistrationBuilder.cs +44 -0
  34. package/Runtime/Core/MessageBus/MessagingRegistration.cs +60 -2
  35. package/Runtime/Core/MessageBus/RegistrationLog.cs +10 -0
  36. package/Runtime/Core/MessageHandler.cs +107 -6
  37. package/Runtime/Core/MessageRegistrationHandle.cs +59 -0
  38. package/Runtime/Core/MessageRegistrationToken.cs +18 -2
  39. package/Runtime/Core/Messages/ReflexiveMessage.cs +38 -0
  40. package/Runtime/Core/MessagingDebug.cs +16 -1
  41. package/Runtime/Unity/CurrentGlobalMessageBusProvider.cs +4 -0
  42. package/Runtime/Unity/DxMessagingRuntimeInitializer.cs +19 -0
  43. package/Runtime/Unity/DxMessagingRuntimeInitializer.cs.meta +11 -0
  44. package/Runtime/Unity/InitialGlobalMessageBusProvider.cs +4 -0
  45. package/Runtime/Unity/Integrations/Reflex/ReflexRegistrationInstaller.cs +17 -0
  46. package/Runtime/Unity/Integrations/VContainer/VContainerRegistrationExtensions.cs +8 -0
  47. package/Runtime/Unity/Integrations/Zenject/ZenjectRegistrationInstaller.cs +12 -0
  48. package/Runtime/Unity/MessagingComponent.cs +93 -0
  49. package/Samples~/DI/README.md +13 -13
  50. package/Samples~/Mini Combat/README.md +15 -15
  51. package/Samples~/Mini Combat/Walkthrough.md +12 -12
  52. package/Samples~/UI Buttons + Inspector/README.md +4 -4
  53. package/SourceGenerators/WallstopStudios.DxMessaging.SourceGenerators/DxAutoConstructorGenerator.cs +4 -0
  54. package/SourceGenerators/WallstopStudios.DxMessaging.SourceGenerators/DxMessageIdGenerator.cs +4 -0
  55. package/Tests/Runtime/Core/DiagnosticsTests.cs +3 -3
  56. package/Tests/Runtime/Core/DxMessagingStaticStateTests.cs +69 -0
  57. package/Tests/Runtime/Core/DxMessagingStaticStateTests.cs.meta +11 -0
  58. package/package.json +1 -1
  59. package/Tests/Runtime/WallstopStudios.DxMessaging.Tests.Runtime.csproj +0 -20
  60. package/Tests/Runtime/WallstopStudios.DxMessaging.Tests.Runtime.csproj.meta +0 -7
@@ -3,6 +3,7 @@ namespace DxMessaging.Unity
3
3
  {
4
4
  using System;
5
5
  using System.Collections.Generic;
6
+ using System.Linq;
6
7
  using Core;
7
8
  using Core.MessageBus;
8
9
  using UnityEngine;
@@ -326,6 +327,98 @@ namespace DxMessaging.Unity
326
327
 
327
328
  return null;
328
329
  }
330
+
331
+ #if UNITY_EDITOR
332
+ [ContextMenu("DxMessaging/Dump Registrations")]
333
+ private void ContextDumpRegistrations()
334
+ {
335
+ DumpRegistrations();
336
+ }
337
+
338
+ internal void DumpRegistrations()
339
+ {
340
+ if (_registeredListeners.Count == 0)
341
+ {
342
+ Debug.Log($"[DxMessaging] {name} has no registered listeners.");
343
+ return;
344
+ }
345
+
346
+ foreach (
347
+ KeyValuePair<MonoBehaviour, MessageRegistrationToken> pair in _registeredListeners
348
+ )
349
+ {
350
+ MonoBehaviour listener = pair.Key;
351
+ MessageRegistrationToken token = pair.Value;
352
+ Debug.Log(
353
+ $"[DxMessaging] Listener '{listener}' (Enabled: {token.Enabled}, Diagnostic: {token.DiagnosticMode}) "
354
+ + $"with {token._metadata.Count} registrations on '{name}'."
355
+ );
356
+ }
357
+ }
358
+
359
+ [ContextMenu("DxMessaging/Reset Runtime State")]
360
+ private void ContextResetRuntimeState()
361
+ {
362
+ if (EditorResetRuntimeState())
363
+ {
364
+ Debug.Log($"[DxMessaging] Cleared runtime state for '{name}'.");
365
+ }
366
+ else
367
+ {
368
+ Debug.Log($"[DxMessaging] No runtime state to clear on '{name}'.");
369
+ }
370
+ }
371
+
372
+ internal bool EditorResetRuntimeState()
373
+ {
374
+ bool cleared = false;
375
+
376
+ if (_registeredListeners.Count > 0)
377
+ {
378
+ foreach (MessageRegistrationToken token in _registeredListeners.Values.ToArray())
379
+ {
380
+ try
381
+ {
382
+ if (token.Enabled)
383
+ {
384
+ token.Disable();
385
+ }
386
+
387
+ token.Dispose();
388
+ }
389
+ catch (Exception exception)
390
+ {
391
+ Debug.LogWarning(
392
+ $"[DxMessaging] Disposing stale token on {name} failed. {exception}"
393
+ );
394
+ }
395
+ }
396
+
397
+ _registeredListeners.Clear();
398
+ cleared = true;
399
+ }
400
+
401
+ if (_messageHandler != null)
402
+ {
403
+ _messageHandler = null;
404
+ cleared = true;
405
+ }
406
+
407
+ if (_messageBusOverride != null)
408
+ {
409
+ _messageBusOverride = null;
410
+ cleared = true;
411
+ }
412
+
413
+ if (_messageBusProvider != null)
414
+ {
415
+ _messageBusProvider = null;
416
+ cleared = true;
417
+ }
418
+
419
+ return cleared;
420
+ }
421
+ #endif
329
422
  }
330
423
  }
331
424
  #endif
@@ -13,18 +13,18 @@ These snippets illustrate how to consume `IMessageRegistrationBuilder` inside co
13
13
 
14
14
  Each sample shows:
15
15
 
16
- - Registering `IMessageRegistrationBuilder` via the provided shim under `Runtime/Unity/Integrations/`.
16
+ - Registering `IMessageRegistrationBuilder` via the provided shim under [Runtime/Unity/Integrations](../../Runtime/Unity/Integrations/).
17
17
  - Constructing a `MessageRegistrationLease` in a container-managed service.
18
18
  - Activating/deactivating the lease using the container lifecycle.
19
19
 
20
20
  ### Structure
21
21
 
22
- - `Zenject/SampleInstaller.cs`
23
- - `VContainer/SampleLifetimeScope.cs`
24
- - `Reflex/SampleInstaller.cs`
25
- - `Providers/CurrentGlobalMessageBusProvider.asset` — ScriptableObject that resolves whichever bus is currently configured as global.
26
- - `Providers/InitialGlobalMessageBusProvider.asset` — ScriptableObject that always returns the original startup global bus, ignoring later overrides.
27
- - `Prefabs/MessagingInstallerSample.prefab` — ready-to-use hierarchy with `MessagingComponentInstaller` configuring a child `MessagingComponent` using the provider asset. Drop it into a scene to see provider-driven wiring without writing setup code.
22
+ - Zenject sample installer: [SampleInstaller.cs](./Zenject/SampleInstaller.cs)
23
+ - VContainer sample lifetime scope: [SampleLifetimeScope.cs](./VContainer/SampleLifetimeScope.cs)
24
+ - Reflex sample installer: [SampleInstaller.cs](./Reflex/SampleInstaller.cs)
25
+ - Current global message bus provider asset: [CurrentGlobalMessageBusProvider.asset](./Providers/CurrentGlobalMessageBusProvider.asset) — ScriptableObject that resolves whichever bus is currently configured as global.
26
+ - Initial global message bus provider asset: [InitialGlobalMessageBusProvider.asset](./Providers/InitialGlobalMessageBusProvider.asset) — ScriptableObject that always returns the original startup global bus, ignoring later overrides.
27
+ - Prefab setup: [MessagingInstallerSample.prefab](./Prefabs/MessagingInstallerSample.prefab) — ready-to-use hierarchy with `MessagingComponentInstaller` configuring a child `MessagingComponent` using the provider asset. Drop it into a scene to see provider-driven wiring without writing setup code.
28
28
 
29
29
  ## Walkthrough
30
30
 
@@ -33,19 +33,19 @@ Each sample shows:
33
33
 
34
34
  2. **Hook up the container**
35
35
  - **Zenject**:
36
- - Add `DxMessagingRegistrationInstaller` (from `Runtime/Unity/Integrations/`) to your ProjectContext or scene installer list.
37
- - Drop `Zenject/SampleInstaller.cs` into your project and register it alongside other installers. When the scene runs, the installer resolves `IMessageRegistrationBuilder`, stages a `PlayerSpawned` listener, and activates via the Zenject lifecycle.
36
+ - Add `DxMessagingRegistrationInstaller` (from [Runtime/Unity/Integrations](../../Runtime/Unity/Integrations/)) to your ProjectContext or scene installer list.
37
+ - Drop [SampleInstaller.cs](./Zenject/SampleInstaller.cs) into your project and register it alongside other installers. When the scene runs, the installer resolves `IMessageRegistrationBuilder`, stages a `PlayerSpawned` listener, and activates via the Zenject lifecycle.
38
38
  - **VContainer**:
39
- - Define `VCONTAINER_PRESENT` and reference the optional extension under `Runtime/Unity/Integrations/VContainerRegistrationExtensions.cs`.
40
- - Add `VContainer/SampleLifetimeScope` to the scene (or derive from it); the sample scope registers the builder and an entry point that emits/consumes `ScoreUpdated` messages each tick.
39
+ - Define `VCONTAINER_PRESENT` and reference the optional extension under [VContainerRegistrationExtensions.cs](../../Runtime/Unity/Integrations/VContainerRegistrationExtensions.cs).
40
+ - Add [SampleLifetimeScope.cs](./VContainer/SampleLifetimeScope.cs) to the scene (or derive from it); the sample scope registers the builder and an entry point that emits/consumes `ScoreUpdated` messages each tick.
41
41
  - **Reflex**:
42
42
  - Enable `REFLEX_PRESENT` and install `DxMessagingRegistrationInstaller` into your container bootstrap.
43
- - Include `Reflex/SampleInstaller` in your installer chain. The sample service resolves `IMessageRegistrationBuilder`, subscribes to `PlayerAlert`, and can emit alerts via `EmitAlertFor`.
43
+ - Include [SampleInstaller.cs](./Reflex/SampleInstaller.cs) in your installer chain. The sample service resolves `IMessageRegistrationBuilder`, subscribes to `PlayerAlert`, and can emit alerts via `EmitAlertFor`.
44
44
 
45
45
  3. **Emit a message**
46
46
  Use the service exposed by the container (e.g., call into `ScoreboardService` or `PlayerAlertService`) to emit a message. Because the prefab already configured `MessagingComponent` instances via the installer, the listeners run immediately.
47
47
 
48
48
  4. **Swap providers** (optional)
49
- Duplicate `Providers/CurrentGlobalMessageBusProvider.asset`, modify it to return a custom bus, assign it on the prefab root, and observe how builder-created leases now resolve that bus instead.
49
+ Duplicate [CurrentGlobalMessageBusProvider.asset](./Providers/CurrentGlobalMessageBusProvider.asset), modify it to return a custom bus, assign it on the prefab root, and observe how builder-created leases now resolve that bus instead.
50
50
 
51
51
  Feel free to duplicate these scripts into your own project and adjust lifecycles or message types as needed.
@@ -83,11 +83,11 @@ Here's what each script does:
83
83
 
84
84
  | File | Purpose | Message Type |
85
85
  |------|---------|--------------|
86
- | **Messages.cs** | Defines all message types | Contains `VideoSettingsChanged`, `Heal`, and `TookDamage` |
87
- | **Player.cs** | Handles receiving healing | Listens for `Heal` (Targeted) |
88
- | **Enemy.cs** | Announces when damaged | Emits `TookDamage` (Broadcast) |
89
- | **UIOverlay.cs** | Updates UI based on events | Listens to settings and `TookDamage` (Broadcast) |
90
- | **Boot.cs** | Starts the demo | Simulates message flow |
86
+ | **[Messages.cs](./Messages.cs)** | Defines all message types | Contains `VideoSettingsChanged`, `Heal`, and `TookDamage` |
87
+ | **[Player.cs](./Player.cs)** | Handles receiving healing | Listens for `Heal` (Targeted) |
88
+ | **[Enemy.cs](./Enemy.cs)** | Announces when damaged | Emits `TookDamage` (Broadcast) |
89
+ | **[UIOverlay.cs](./UIOverlay.cs)** | Updates UI based on events | Listens to settings and `TookDamage` (Broadcast) |
90
+ | **[Boot.cs](./Boot.cs)** | Starts the demo | Simulates message flow |
91
91
 
92
92
  ---
93
93
 
@@ -126,10 +126,10 @@ For **each GameObject**, you need TWO components:
126
126
  - Click GameObject → Add Component → "MessagingComponent"
127
127
 
128
128
  1. **Add the sample script**:
129
- - **Player** GameObject → Add `Player.cs` script
130
- - **Enemy** GameObject → Add `Enemy.cs` script
131
- - **UIOverlay** GameObject → Add `UIOverlay.cs` script
132
- - **Boot** GameObject → Add `Boot.cs` script
129
+ - **Player** GameObject → Add [Player.cs](./Player.cs) script
130
+ - **Enemy** GameObject → Add [Enemy.cs](./Enemy.cs) script
131
+ - **UIOverlay** GameObject → Add [UIOverlay.cs](./UIOverlay.cs) script
132
+ - **Boot** GameObject → Add [Boot.cs](./Boot.cs) script
133
133
 
134
134
  #### Step 3: Run and Observe
135
135
 
@@ -147,11 +147,11 @@ Press Play! The Boot script will automatically:
147
147
 
148
148
  ### The Message Flow
149
149
 
150
- #### Boot.cs sends messages:
150
+ #### [Boot.cs](./Boot.cs) sends messages:
151
151
 
152
- 1. `VideoSettingsChanged` (Untargeted) → UIOverlay.cs receives
153
- 2. `Heal` (Targeted to Player) → Player.cs receives
154
- 3. `TookDamage` (Broadcast from Enemy) → UIOverlay.cs receives
152
+ 1. `VideoSettingsChanged` (Untargeted) → [UIOverlay.cs](./UIOverlay.cs) receives
153
+ 2. `Heal` (Targeted to Player) → [Player.cs](./Player.cs) receives
154
+ 3. `TookDamage` (Broadcast from Enemy) → [UIOverlay.cs](./UIOverlay.cs) receives
155
155
 
156
156
  ### Understanding Message Types
157
157
 
@@ -318,6 +318,6 @@ protected override void OnEnable() {
318
318
  ## Quick Reference
319
319
 
320
320
  **Enable Diagnostics**: Select MessagingComponent in Inspector → Enable Diagnostics
321
- **Message Types**: See `Messages.cs` for all available messages
322
- **Modify Behavior**: Edit handler methods in Player.cs, Enemy.cs, or UIOverlay.cs
321
+ **Message Types**: See [Messages.cs](./Messages.cs) for all available messages
322
+ **Modify Behavior**: Edit handler methods in [Player.cs](./Player.cs), [Enemy.cs](./Enemy.cs), or [UIOverlay.cs](./UIOverlay.cs)
323
323
  **Extend Scripts**: Always call `base.RegisterMessageHandlers()` and other `base.*` methods
@@ -17,7 +17,7 @@
17
17
  After reading this walkthrough, you'll know:
18
18
 
19
19
  1. **Why each message type was chosen** - the reasoning behind Untargeted vs Targeted vs Broadcast
20
- 2. **How the code flows** - step-by-step from Boot.cs through every script
20
+ 2. **How the code flows** - step-by-step from [Boot.cs](./Boot.cs) through every script
21
21
  3. **Common patterns** - Observer, Broadcaster, Orchestrator, and more
22
22
  4. **Debugging strategies** - how to find and fix issues
23
23
  5. **How to extend it** - add your own messages and handlers
@@ -43,7 +43,7 @@ After reading this walkthrough, you'll know:
43
43
 
44
44
  Let's understand what each script does:
45
45
 
46
- ### Messages.cs
46
+ ### [Messages.cs](./Messages.cs)
47
47
 
48
48
  **Purpose**: Defines all message types used in the sample
49
49
 
@@ -56,7 +56,7 @@ Let's understand what each script does:
56
56
 
57
57
  **Why separate file?** Keeping messages in one place makes them easy to find and prevents circular dependencies.
58
58
 
59
- ### Player.cs
59
+ ### [Player.cs](./Player.cs)
60
60
 
61
61
  **What it does**: Listens for healing messages targeted specifically at this player
62
62
 
@@ -68,7 +68,7 @@ Let's understand what each script does:
68
68
 
69
69
  **Real-world analogy**: Like having your name called in a doctor's office—only you respond.
70
70
 
71
- ### Enemy.cs
71
+ ### [Enemy.cs](./Enemy.cs)
72
72
 
73
73
  **What it does**: Broadcasts when it takes damage
74
74
 
@@ -80,7 +80,7 @@ Let's understand what each script does:
80
80
 
81
81
  **Real-world analogy**: Like ringing a bell—anyone nearby can hear it.
82
82
 
83
- ### UIOverlay.cs
83
+ ### [UIOverlay.cs](./UIOverlay.cs)
84
84
 
85
85
  **What it does**: Monitors game events and updates the UI
86
86
 
@@ -92,7 +92,7 @@ Let's understand what each script does:
92
92
 
93
93
  **Real-world analogy**: Like a news reporter watching everything and reporting it.
94
94
 
95
- ### Boot.cs
95
+ ### [Boot.cs](./Boot.cs)
96
96
 
97
97
  **What it does**: Starts the demo by simulating a sequence of events
98
98
 
@@ -141,8 +141,8 @@ Settings changes are **global events**—they don't target anyone specifically.
141
141
 
142
142
  ### The Code Flow
143
143
 
144
- 1. **Boot.cs** calls: `MessageHub.Publish(new VideoSettingsChanged())`
145
- 1. **UIOverlay.cs** receives it through its registered handler
144
+ 1. **[Boot.cs](./Boot.cs)** calls: `MessageHub.Publish(new VideoSettingsChanged())`
145
+ 1. **[UIOverlay.cs](./UIOverlay.cs)** receives it through its registered handler
146
146
  1. **UIOverlay** rebuilds the UI with new settings
147
147
 
148
148
  ### Developer Notes
@@ -178,9 +178,9 @@ We want to heal **one specific player**, not all players in the scene.
178
178
 
179
179
  ### The Code Flow
180
180
 
181
- 1. **Boot.cs** finds the Player Component reference
182
- 1. **Boot.cs** calls: `MessageHub.Publish(new Heal(amount), targetComponent)`
183
- 1. **Only the targeted Player.cs** receives it through its handler
181
+ 1. **[Boot.cs](./Boot.cs)** finds the Player Component reference
182
+ 1. **[Boot.cs](./Boot.cs)** calls: `MessageHub.Publish(new Heal(amount), targetComponent)`
183
+ 1. **Only the targeted [Player.cs](./Player.cs)** receives it through its handler
184
184
  1. **Player** increases its HP
185
185
 
186
186
  ### Developer Notes
@@ -216,7 +216,7 @@ The Enemy doesn't know (or care) who needs to know about the damage. It just ann
216
216
 
217
217
  ### The Code Flow
218
218
 
219
- 1. **Enemy.cs** detects it took damage
219
+ 1. **[Enemy.cs](./Enemy.cs)** detects it took damage
220
220
  1. **Enemy** calls: `this.EmitBroadcast(new TookDamage(amount))`
221
221
  1. **UIOverlay** receives it via `RegisterBroadcastWithoutSource`
222
222
  1. **UIOverlay** displays the damage event
@@ -120,7 +120,7 @@ MessageHandler.MessageBus.DiagnosticsMode = true;
120
120
 
121
121
  - Multiple buttons: Add more UI Buttons, add more `UIButtonEmitter`s, and give each a unique `buttonId`.
122
122
  - Targeted vs. untargeted: Notice the sample also sends a targeted `StringMessage` to the emitter’s `gameObject`.
123
- - Your own message type: Open `Messages.cs` to see how `ButtonClicked` is declared using attributes:
123
+ - Your own message type: Open [Messages.cs](./Messages.cs) to see how `ButtonClicked` is declared using attributes:
124
124
 
125
125
  ```csharp
126
126
  [DxUntargetedMessage]
@@ -202,8 +202,8 @@ public class MyObserver : MessageAwareComponent {
202
202
 
203
203
  ## Next Steps
204
204
 
205
- - Quick tour: `Docs/GettingStarted.md`
206
- - Patterns and recipes: `Docs/Patterns.md`
207
- - Explore another sample: `../Mini%20Combat/README.md`
205
+ - Quick tour: [Getting Started guide](../../Docs/GettingStarted.md)
206
+ - Patterns and recipes: [Common Patterns](../../Docs/Patterns.md)
207
+ - Explore another sample: [Mini Combat sample](../Mini%20Combat/README.md)
208
208
 
209
209
  You now have an easy, inspector-first way to publish and observe messages. Build up from here by swapping in your own message types and listeners.
@@ -56,6 +56,10 @@ namespace WallstopStudios.DxMessaging.SourceGenerators
56
56
  ImmutableArray<IFieldSymbol> FieldsToInject // Public readonly non-static fields
57
57
  );
58
58
 
59
+ /// <summary>
60
+ /// Configures the incremental generator pipeline that discovers annotated types and emits constructors.
61
+ /// </summary>
62
+ /// <param name="context">Initialization context provided by Roslyn.</param>
59
63
  public void Initialize(IncrementalGeneratorInitializationContext context)
60
64
  {
61
65
  // Find all class/struct/record declarations that have attribute lists
@@ -70,6 +70,10 @@ namespace WallstopStudios.DxMessaging.SourceGenerators
70
70
  bool HasConflictingMessageAttributes
71
71
  );
72
72
 
73
+ /// <summary>
74
+ /// Configures the incremental generator pipeline that assigns deterministic message identifiers.
75
+ /// </summary>
76
+ /// <param name="context">Initialization context provided by Roslyn.</param>
73
77
  public void Initialize(IncrementalGeneratorInitializationContext context)
74
78
  {
75
79
  // Find all class/struct/record declarations with attributes
@@ -51,11 +51,11 @@ namespace DxMessaging.Tests.Runtime.Core
51
51
  [UnityTest]
52
52
  public IEnumerator MessageBusDiagnosticsRespectBufferSize()
53
53
  {
54
- bool originalDiagnostics = IMessageBus.GlobalDiagnosticsMode;
54
+ DiagnosticsTarget originalDiagnostics = IMessageBus.GlobalDiagnosticsTargets;
55
55
  int originalBufferSize = IMessageBus.GlobalMessageBufferSize;
56
56
  try
57
57
  {
58
- IMessageBus.GlobalDiagnosticsMode = true;
58
+ IMessageBus.GlobalDiagnosticsTargets = DiagnosticsTarget.All;
59
59
  IMessageBus.GlobalMessageBufferSize = 2;
60
60
 
61
61
  GameObject host = new(nameof(MessageBusDiagnosticsRespectBufferSize));
@@ -90,7 +90,7 @@ namespace DxMessaging.Tests.Runtime.Core
90
90
  }
91
91
  finally
92
92
  {
93
- IMessageBus.GlobalDiagnosticsMode = originalDiagnostics;
93
+ IMessageBus.GlobalDiagnosticsTargets = originalDiagnostics;
94
94
  IMessageBus.GlobalMessageBufferSize = originalBufferSize;
95
95
  }
96
96
 
@@ -0,0 +1,69 @@
1
+ #if UNITY_2021_3_OR_NEWER
2
+ namespace DxMessaging.Tests.Runtime.Core
3
+ {
4
+ using System;
5
+ using System.Reflection;
6
+ using DxMessaging.Core;
7
+ using DxMessaging.Core.Helper;
8
+ using DxMessaging.Core.MessageBus;
9
+ using DxMessaging.Core.Messages;
10
+ using NUnit.Framework;
11
+
12
+ public sealed class DxMessagingStaticStateTests
13
+ {
14
+ [Test]
15
+ public void ResetRestoresDefaultStaticState()
16
+ {
17
+ DxMessagingStaticState.Reset();
18
+ IMessageBus baselineBus = MessageHandler.MessageBus;
19
+ MessageRegistrationHandle baselineHandle =
20
+ MessageRegistrationHandle.CreateMessageRegistrationHandle();
21
+
22
+ MessageRegistrationHandle.CreateMessageRegistrationHandle();
23
+ MessagingDebug.enabled = true;
24
+ MessagingDebug.LogFunction = (logLevel, message) => { };
25
+
26
+ IMessageBus.GlobalDiagnosticsTargets = DiagnosticsTarget.All;
27
+ IMessageBus.GlobalMessageBufferSize = 128;
28
+ IMessageBus.GlobalSequentialIndex = 7;
29
+
30
+ Type builderType = typeof(MessageRegistrationBuilder);
31
+ FieldInfo syntheticOwnerField = builderType.GetField(
32
+ "_syntheticOwnerCounter",
33
+ BindingFlags.NonPublic | BindingFlags.Static
34
+ );
35
+ Assert.IsNotNull(syntheticOwnerField);
36
+ syntheticOwnerField.SetValue(null, 3);
37
+
38
+ MessageCache<object> cache = new MessageCache<object>();
39
+ cache.GetOrAdd<DummyUntargetedMessage>();
40
+
41
+ MessageHandler.SetGlobalMessageBus(new MessageBus());
42
+
43
+ DxMessagingStaticState.Reset();
44
+
45
+ Assert.IsFalse(MessagingDebug.enabled);
46
+ Assert.IsNull(MessagingDebug.LogFunction);
47
+ Assert.AreEqual(DiagnosticsTarget.Off, IMessageBus.GlobalDiagnosticsTargets);
48
+ Assert.AreEqual(0, IMessageBus.GlobalMessageBufferSize);
49
+ Assert.AreEqual(-1, IMessageBus.GlobalSequentialIndex);
50
+
51
+ MessageRegistrationHandle resetHandle =
52
+ MessageRegistrationHandle.CreateMessageRegistrationHandle();
53
+ Assert.AreEqual(baselineHandle, resetHandle);
54
+
55
+ object syntheticOwnerValue = syntheticOwnerField.GetValue(null);
56
+ Assert.AreEqual(0, (int)syntheticOwnerValue);
57
+
58
+ Assert.AreEqual(0, MessageHelperIndexer.TotalMessages);
59
+ Assert.AreEqual(-1, MessageHelperIndexer<DummyUntargetedMessage>.SequentialId);
60
+ Assert.AreSame(MessageHandler.InitialGlobalMessageBus, MessageHandler.MessageBus);
61
+ Assert.AreSame(baselineBus, MessageHandler.MessageBus);
62
+
63
+ DxMessagingStaticState.Reset();
64
+ }
65
+
66
+ private struct DummyUntargetedMessage : IUntargetedMessage { }
67
+ }
68
+ }
69
+ #endif
@@ -0,0 +1,11 @@
1
+ fileFormatVersion: 2
2
+ guid: 5a3c452f2f1b48a1b66e8a7a05d3b7a8
3
+ MonoImporter:
4
+ externalObjects: {}
5
+ serializedVersion: 2
6
+ defaultReferences: []
7
+ executionOrder: 0
8
+ icon: {instanceID: 0}
9
+ userData:
10
+ assetBundleName:
11
+ assetBundleVariant:
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "com.wallstop-studios.dxmessaging",
3
- "version": "2.1.2",
3
+ "version": "2.1.3",
4
4
  "displayName": "DxMessaging",
5
5
  "description": "Synchronous Event Bus for Unity",
6
6
  "unity": "2021.3",
@@ -1,20 +0,0 @@
1
- <Project Sdk="Microsoft.NET.Sdk">
2
- <PropertyGroup>
3
- <TargetFramework>net8.0</TargetFramework>
4
- <Nullable>disable</Nullable>
5
- <ImplicitUsings>disable</ImplicitUsings>
6
- <EnableDefaultCompileItems>false</EnableDefaultCompileItems>
7
- <EnableDefaultNoneItems>false</EnableDefaultNoneItems>
8
- <IsPackable>false</IsPackable>
9
- <GenerateAssemblyInfo>false</GenerateAssemblyInfo>
10
- <NoWarn>1701;1702</NoWarn>
11
- </PropertyGroup>
12
- <ItemGroup>
13
- <None Include="Benchmarks\**\*.cs" LinkBase="Benchmarks" />
14
- <None Include="Core\**\*.cs" LinkBase="Core" />
15
- <None Include="Integrations\**\*.cs" LinkBase="Integrations" />
16
- <None Include="Scripts\**\*.cs" LinkBase="Scripts" />
17
- <None Include="TestUtilities\**\*.cs" LinkBase="TestUtilities" />
18
- <None Include="Unity\**\*.cs" LinkBase="Unity" />
19
- </ItemGroup>
20
- </Project>
@@ -1,7 +0,0 @@
1
- fileFormatVersion: 2
2
- guid: 939c668fdbd24a74591e482310e0e40f
3
- DefaultImporter:
4
- externalObjects: {}
5
- userData:
6
- assetBundleName:
7
- assetBundleVariant: