com.wallstop-studios.dxmessaging 2.0.0-rc27.3.1 → 2.1.0

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 (185) hide show
  1. package/.github/workflows/format-on-demand.yml +2 -2
  2. package/.github/workflows/json-format-check.yml +1 -1
  3. package/.github/workflows/markdown-json.yml +1 -1
  4. package/.github/workflows/markdownlint.yml +1 -1
  5. package/.github/workflows/npm-publish.yml +1 -1
  6. package/.github/workflows/prettier-autofix.yml +2 -2
  7. package/.github/workflows/yaml-format-lint.yml +1 -1
  8. package/Docs/Advanced.md +26 -1
  9. package/Docs/Comparisons.md +1352 -141
  10. package/Docs/Compatibility.md +27 -0
  11. package/Docs/DesignAndArchitecture.md +41 -34
  12. package/Docs/EmitShorthands.md +34 -0
  13. package/Docs/GettingStarted.md +84 -17
  14. package/Docs/Helpers.md +1 -1
  15. package/Docs/Index.md +28 -25
  16. package/Docs/Install.md +29 -6
  17. package/Docs/Integrations/Reflex.md +292 -0
  18. package/Docs/Integrations/Reflex.md.meta +7 -0
  19. package/Docs/Integrations/VContainer.md +324 -0
  20. package/Docs/Integrations/VContainer.md.meta +7 -0
  21. package/Docs/Integrations/Zenject.md +333 -0
  22. package/Docs/Integrations/Zenject.md.meta +7 -0
  23. package/{Editor/Analyzers/WallstopStudios.DxMessaging.SourceGenerators.pdb.meta → Docs/Integrations.meta} +2 -1
  24. package/Docs/InterceptorsAndOrdering.md +371 -17
  25. package/Docs/ListeningPatterns.md +206 -0
  26. package/Docs/MessageBusProviders.md +496 -0
  27. package/Docs/MessageBusProviders.md.meta +7 -0
  28. package/Docs/MessageTypes.md +27 -0
  29. package/Docs/MigrationGuide.md +45 -0
  30. package/Docs/Overview.md +114 -20
  31. package/Docs/Patterns.md +327 -2
  32. package/Docs/Performance.md +9 -9
  33. package/Docs/QuickReference.md +31 -0
  34. package/Docs/RuntimeConfiguration.md +407 -0
  35. package/Docs/RuntimeConfiguration.md.meta +7 -0
  36. package/Docs/UnityIntegration.md +3 -1
  37. package/Docs/VisualGuide.md +281 -167
  38. package/Editor/Analyzers/Microsoft.CodeAnalysis.CSharp.dll +0 -0
  39. package/Editor/Analyzers/Microsoft.CodeAnalysis.CSharp.dll.meta +3 -3
  40. package/Editor/Analyzers/Microsoft.CodeAnalysis.dll +0 -0
  41. package/Editor/Analyzers/Microsoft.CodeAnalysis.dll.meta +2 -2
  42. package/Editor/Analyzers/System.Collections.Immutable.dll +0 -0
  43. package/Editor/Analyzers/System.Reflection.Metadata.dll +0 -0
  44. package/Editor/Analyzers/System.Runtime.CompilerServices.Unsafe.dll +0 -0
  45. package/Editor/CustomEditors/MessagingComponentEditor.cs +15 -6
  46. package/README.md +388 -67
  47. package/Runtime/AssemblyInfo.cs +4 -0
  48. package/Runtime/Core/Extensions/MessageBusExtensions.cs +253 -0
  49. package/Runtime/Core/Extensions/MessageBusExtensions.cs.meta +12 -0
  50. package/Runtime/Core/Extensions/MessageExtensions.cs +137 -89
  51. package/Runtime/Core/MessageBus/GlobalMessageBusProvider.cs +23 -0
  52. package/Runtime/Core/MessageBus/GlobalMessageBusProvider.cs.meta +11 -0
  53. package/Runtime/Core/MessageBus/IMessageBusProvider.cs +14 -0
  54. package/Runtime/Core/MessageBus/IMessageBusProvider.cs.meta +11 -0
  55. package/Runtime/Core/MessageBus/IMessageRegistrationBuilder.cs +18 -0
  56. package/Runtime/Core/MessageBus/IMessageRegistrationBuilder.cs.meta +11 -0
  57. package/Runtime/Core/MessageBus/MessageBusRebindMode.cs +26 -0
  58. package/Runtime/Core/MessageBus/MessageBusRebindMode.cs.meta +11 -0
  59. package/Runtime/Core/MessageBus/MessageRegistrationBuilder.cs +383 -0
  60. package/Runtime/Core/MessageBus/MessageRegistrationBuilder.cs.meta +11 -0
  61. package/Runtime/Core/MessageHandler.cs +198 -27
  62. package/Runtime/Core/MessageRegistrationToken.cs +67 -25
  63. package/Runtime/Unity/CurrentGlobalMessageBusProvider.cs +31 -0
  64. package/Runtime/Unity/CurrentGlobalMessageBusProvider.cs.meta +12 -0
  65. package/Runtime/Unity/InitialGlobalMessageBusProvider.cs +38 -0
  66. package/Runtime/Unity/InitialGlobalMessageBusProvider.cs.meta +12 -0
  67. package/Runtime/Unity/Integrations/Reflex/AssemblyInfo.cs +11 -0
  68. package/Runtime/Unity/Integrations/Reflex/AssemblyInfo.cs.meta +3 -0
  69. package/Runtime/Unity/Integrations/Reflex/ReflexRegistrationInstaller.cs +73 -0
  70. package/Runtime/Unity/Integrations/Reflex/ReflexRegistrationInstaller.cs.meta +11 -0
  71. package/Runtime/Unity/Integrations/Reflex/WallstopStudios.DxMessaging.Reflex.asmdef +20 -0
  72. package/Runtime/Unity/Integrations/Reflex/WallstopStudios.DxMessaging.Reflex.asmdef.meta +7 -0
  73. package/Runtime/Unity/Integrations/Reflex.meta +8 -0
  74. package/Runtime/Unity/Integrations/VContainer/AssemblyInfo.cs +11 -0
  75. package/Runtime/Unity/Integrations/VContainer/AssemblyInfo.cs.meta +3 -0
  76. package/Runtime/Unity/Integrations/VContainer/VContainerRegistrationExtensions.cs +46 -0
  77. package/Runtime/Unity/Integrations/VContainer/VContainerRegistrationExtensions.cs.meta +11 -0
  78. package/Runtime/Unity/Integrations/VContainer/WallstopStudios.DxMessaging.VContainer.asmdef +30 -0
  79. package/Runtime/Unity/Integrations/VContainer/WallstopStudios.DxMessaging.VContainer.asmdef.meta +7 -0
  80. package/Runtime/Unity/Integrations/VContainer.meta +8 -0
  81. package/Runtime/Unity/Integrations/Zenject/AssemblyInfo.cs +11 -0
  82. package/Runtime/Unity/Integrations/Zenject/AssemblyInfo.cs.meta +3 -0
  83. package/Runtime/Unity/Integrations/Zenject/WallstopStudios.DxMessaging.Zenject.asmdef +30 -0
  84. package/Runtime/Unity/Integrations/Zenject/WallstopStudios.DxMessaging.Zenject.asmdef.meta +7 -0
  85. package/Runtime/Unity/Integrations/Zenject/ZenjectRegistrationInstaller.cs +55 -0
  86. package/Runtime/Unity/Integrations/Zenject/ZenjectRegistrationInstaller.cs.meta +11 -0
  87. package/Runtime/Unity/Integrations/Zenject.meta +8 -0
  88. package/Runtime/Unity/Integrations.meta +8 -0
  89. package/Runtime/Unity/MessageAwareComponent.cs +102 -0
  90. package/Runtime/Unity/MessageBusProviderHandle.cs +97 -0
  91. package/Runtime/Unity/MessageBusProviderHandle.cs.meta +12 -0
  92. package/Runtime/Unity/MessagingComponent.cs +164 -2
  93. package/Runtime/Unity/MessagingComponentInstaller.cs +120 -0
  94. package/Runtime/Unity/MessagingComponentInstaller.cs.meta +12 -0
  95. package/Runtime/Unity/ScriptableMessageBusProvider.cs +14 -0
  96. package/Runtime/Unity/ScriptableMessageBusProvider.cs.meta +12 -0
  97. package/Samples~/DI/Prefabs/MessagingInstallerSample.prefab +98 -0
  98. package/Samples~/DI/Prefabs/MessagingInstallerSample.prefab.meta +7 -0
  99. package/Samples~/DI/Prefabs.meta +8 -0
  100. package/Samples~/DI/Providers/GlobalMessageBusProvider.asset +14 -0
  101. package/Samples~/DI/Providers/GlobalMessageBusProvider.asset.meta +8 -0
  102. package/Samples~/DI/Providers/InitialGlobalMessageBusProvider.asset +14 -0
  103. package/Samples~/DI/Providers/InitialGlobalMessageBusProvider.asset.meta +8 -0
  104. package/Samples~/DI/Providers.meta +8 -0
  105. package/Samples~/DI/README.md +51 -0
  106. package/Samples~/DI/README.md.meta +7 -0
  107. package/Samples~/DI/Reflex/SampleInstaller.cs +75 -0
  108. package/Samples~/DI/Reflex/SampleInstaller.cs.meta +11 -0
  109. package/Samples~/DI/Reflex.meta +8 -0
  110. package/Samples~/DI/VContainer/SampleLifetimeScope.cs +81 -0
  111. package/Samples~/DI/VContainer/SampleLifetimeScope.cs.meta +11 -0
  112. package/Samples~/DI/VContainer.meta +8 -0
  113. package/Samples~/DI/Zenject/SampleInstaller.cs +67 -0
  114. package/Samples~/DI/Zenject/SampleInstaller.cs.meta +11 -0
  115. package/Samples~/DI/Zenject.meta +8 -0
  116. package/Samples~/DI.meta +8 -0
  117. package/Samples~/Mini Combat/README.md +86 -28
  118. package/Samples~/Mini Combat/Walkthrough.md +41 -25
  119. package/Samples~/UI Buttons + Inspector/DiagnosticsEnabler.cs +12 -2
  120. package/Samples~/UI Buttons + Inspector/README.md +55 -12
  121. package/Samples~/UI Buttons + Inspector/README.md.meta +7 -0
  122. package/Tests/Runtime/Benchmarks/BenchmarkSession.cs +444 -0
  123. package/Tests/Runtime/Benchmarks/BenchmarkSession.cs.meta +11 -0
  124. package/Tests/Runtime/Benchmarks/BenchmarkTestBase.cs +94 -0
  125. package/Tests/Runtime/Benchmarks/BenchmarkTestBase.cs.meta +11 -0
  126. package/Tests/Runtime/Benchmarks/ComparisonPerformanceTests.cs +395 -0
  127. package/Tests/Runtime/Benchmarks/ComparisonPerformanceTests.cs.meta +11 -0
  128. package/Tests/Runtime/Benchmarks/PerformanceTests.cs +77 -429
  129. package/Tests/Runtime/Benchmarks/ProviderResolutionBenchmarks.cs +142 -0
  130. package/Tests/Runtime/Benchmarks/ProviderResolutionBenchmarks.cs.meta +12 -0
  131. package/Tests/Runtime/Benchmarks/WallstopStudios.DxMessaging.Tests.Runtime.Benchmarks.asmdef +50 -0
  132. package/Tests/Runtime/Benchmarks/WallstopStudios.DxMessaging.Tests.Runtime.Benchmarks.asmdef.meta +7 -0
  133. package/Tests/Runtime/Core/DefaultBusFallbackTests.cs +333 -0
  134. package/Tests/Runtime/Core/DefaultBusFallbackTests.cs.meta +11 -0
  135. package/Tests/Runtime/Core/Extensions/MessageBusExtensionsTests.cs +278 -0
  136. package/Tests/Runtime/Core/Extensions/MessageBusExtensionsTests.cs.meta +11 -0
  137. package/Tests/Runtime/Core/Extensions/MessageExtensionsProviderTests.cs +289 -0
  138. package/Tests/Runtime/Core/Extensions/MessageExtensionsProviderTests.cs.meta +11 -0
  139. package/Tests/Runtime/Core/Extensions.meta +8 -0
  140. package/Tests/Runtime/Core/IntegrationShimSmokeTests.cs +57 -0
  141. package/Tests/Runtime/Core/IntegrationShimSmokeTests.cs.meta +11 -0
  142. package/Tests/Runtime/Core/MessageHandlerGlobalBusTests.cs +219 -0
  143. package/Tests/Runtime/Core/MessageHandlerGlobalBusTests.cs.meta +11 -0
  144. package/Tests/Runtime/Core/MessageRegistrationBuilderTests.cs +204 -0
  145. package/Tests/Runtime/Core/MessageRegistrationBuilderTests.cs.meta +11 -0
  146. package/Tests/Runtime/Core/MessagingTestBase.cs +4 -4
  147. package/Tests/Runtime/Core/NominalTests.cs +2 -2
  148. package/Tests/Runtime/Core/SourceGeneratorNestedTests.cs +1 -1
  149. package/Tests/Runtime/Core/TypedShorthandTests.cs +2 -2
  150. package/Tests/Runtime/Core/UntargetedEquivalenceTests.cs +1 -1
  151. package/Tests/Runtime/Core/UntargetedPrefreezeTests.cs +2 -4
  152. package/Tests/Runtime/Integrations/Reflex/ReflexIntegrationTests.cs +162 -0
  153. package/Tests/Runtime/Integrations/Reflex/ReflexIntegrationTests.cs.meta +11 -0
  154. package/Tests/Runtime/Integrations/Reflex/Resources/ReflexSettings.asset +16 -0
  155. package/Tests/Runtime/Integrations/Reflex/Resources/ReflexSettings.asset.meta +8 -0
  156. package/Tests/Runtime/Integrations/Reflex/Resources.meta +8 -0
  157. package/Tests/Runtime/Integrations/Reflex/WallstopStudios.DxMessaging.Tests.Runtime.Reflex.asmdef +27 -0
  158. package/Tests/Runtime/Integrations/Reflex/WallstopStudios.DxMessaging.Tests.Runtime.Reflex.asmdef.meta +7 -0
  159. package/Tests/Runtime/Integrations/Reflex.meta +8 -0
  160. package/Tests/Runtime/Integrations/VContainer/VContainerIntegrationTests.cs +140 -0
  161. package/Tests/Runtime/Integrations/VContainer/VContainerIntegrationTests.cs.meta +11 -0
  162. package/Tests/Runtime/Integrations/VContainer/WallstopStudios.DxMessaging.Tests.Runtime.VContainer.asmdef +37 -0
  163. package/Tests/Runtime/Integrations/VContainer/WallstopStudios.DxMessaging.Tests.Runtime.VContainer.asmdef.meta +7 -0
  164. package/Tests/Runtime/Integrations/VContainer.meta +8 -0
  165. package/Tests/Runtime/Integrations/Zenject/WallstopStudios.DxMessaging.Tests.Runtime.Zenject.asmdef +37 -0
  166. package/Tests/Runtime/Integrations/Zenject/WallstopStudios.DxMessaging.Tests.Runtime.Zenject.asmdef.meta +7 -0
  167. package/Tests/Runtime/Integrations/Zenject/ZenjectIntegrationTests.cs +140 -0
  168. package/Tests/Runtime/Integrations/Zenject/ZenjectIntegrationTests.cs.meta +11 -0
  169. package/Tests/Runtime/Integrations/Zenject.meta +8 -0
  170. package/Tests/Runtime/Integrations.meta +8 -0
  171. package/Tests/Runtime/Scripts/Components/EmptyMessageAwareComponent.cs +1 -1
  172. package/Tests/Runtime/Scripts/Components/GenericMessageAwareComponent.cs +1 -1
  173. package/Tests/Runtime/Scripts/Components/SimpleMessageAwareComponent.cs +1 -1
  174. package/Tests/Runtime/TestUtilities/UnityFixtureBase.cs +64 -0
  175. package/Tests/Runtime/TestUtilities/UnityFixtureBase.cs.meta +12 -0
  176. package/Tests/Runtime/TestUtilities.meta +9 -0
  177. package/Tests/Runtime/Unity/MessageBusProviderAssetTests.cs +57 -0
  178. package/Tests/Runtime/Unity/MessageBusProviderAssetTests.cs.meta +11 -0
  179. package/Tests/Runtime/Unity/MessageBusProviderHandleTests.cs +107 -0
  180. package/Tests/Runtime/Unity/MessageBusProviderHandleTests.cs.meta +12 -0
  181. package/Tests/Runtime/Unity/MessagingComponentProviderIntegrationTests.cs +210 -0
  182. package/Tests/Runtime/Unity/MessagingComponentProviderIntegrationTests.cs.meta +12 -0
  183. package/Tests/Runtime/Unity.meta +9 -0
  184. package/Tests/Runtime/WallstopStudios.DxMessaging.Tests.Runtime.asmdef +3 -1
  185. package/package.json +1 -1
@@ -6,45 +6,67 @@ If you're brand new to messaging systems, this visual guide will help you unders
6
6
 
7
7
  ### The Old Way (Spaghetti Code)
8
8
 
9
- ````text
10
- ┌─────────────┐
11
- Player │───────┐
12
- └─────────────┘ │
13
- ├──→ ┌─────────┐
14
- ┌─────────────┐ │ UI
15
- │ Enemy │───────┤ └─────────┘
16
- └─────────────┘ │
17
- ┌─────────┐
18
- ┌─────────────┐ └───→│ Audio
19
- Inventory │───────────→└─────────┘
20
- └─────────────┘
21
-
22
- Problems:
23
- Everyone needs to know everyone else
24
- Hard to add/remove systems
25
- Memory leaks from forgotten unsubscribes
26
- ```text
9
+ ```mermaid
10
+ graph LR
11
+ Player[Player]
12
+ Enemy[Enemy]
13
+ Inventory[Inventory]
14
+ UI[UI]
15
+ Audio[Audio]
16
+
17
+ Player -->|direct ref| UI
18
+ Player -->|direct ref| Audio
19
+ Enemy -->|direct ref| UI
20
+ Enemy -->|direct ref| Audio
21
+ Inventory -->|direct ref| Audio
22
+
23
+ style Player fill:#ffa39e,stroke:#cf1322,stroke-width:2px,color:#000
24
+ style Enemy fill:#ffa39e,stroke:#cf1322,stroke-width:2px,color:#000
25
+ style Inventory fill:#ffa39e,stroke:#cf1322,stroke-width:2px,color:#000
26
+ style UI fill:#b7eb8f,stroke:#389e0d,stroke-width:2px,color:#000
27
+ style Audio fill:#b7eb8f,stroke:#389e0d,stroke-width:2px,color:#000
28
+ ```
29
+
30
+ #### Problems
31
+
32
+ - ❌ Everyone needs to know everyone else
33
+ - ❌ Hard to add/remove systems
34
+ - ❌ Memory leaks from forgotten unsubscribes
27
35
 
28
36
  ### The DxMessaging Way (Clean Separation)
29
37
 
30
- ```text
31
- ┌─────────┐ ┌─────────┐
32
- Player │──→ Message ──→ │ UI │
33
- └─────────┘ ↓ └─────────┘
34
-
35
- ┌─────────┐ ↓ ┌─────────┐
36
- │ Enemy │──→ BUS ──→ │ Audio │
37
- └─────────┘ ↓ └─────────┘
38
-
39
- ┌──────────┐ ↓ ┌──────────┐
40
- │Inventory │──→ Message ──→ │Analytics │
41
- └──────────┘ └──────────┘
42
-
43
- Benefits:
44
- Nobody knows about anyone else
45
- Easy to add/remove systems
46
- Zero memory leaks (automatic cleanup)
47
- ```text
38
+ ```mermaid
39
+ graph TB
40
+ Player[Player]
41
+ Enemy[Enemy]
42
+ Inventory[Inventory]
43
+ Bus((Message<br/>Bus))
44
+ UI[UI]
45
+ Audio[Audio]
46
+ Analytics[Analytics]
47
+
48
+ Player -->|message| Bus
49
+ Enemy -->|message| Bus
50
+ Inventory -->|message| Bus
51
+
52
+ Bus -->|notify| UI
53
+ Bus -->|notify| Audio
54
+ Bus -->|notify| Analytics
55
+
56
+ style Player fill:#91d5ff,stroke:#096dd9,stroke-width:2px,color:#000
57
+ style Enemy fill:#91d5ff,stroke:#096dd9,stroke-width:2px,color:#000
58
+ style Inventory fill:#91d5ff,stroke:#096dd9,stroke-width:2px,color:#000
59
+ style Bus fill:#ffd591,stroke:#d46b08,stroke-width:3px,color:#000
60
+ style UI fill:#95de64,stroke:#237804,stroke-width:2px,color:#000
61
+ style Audio fill:#95de64,stroke:#237804,stroke-width:2px,color:#000
62
+ style Analytics fill:#95de64,stroke:#237804,stroke-width:2px,color:#000
63
+ ```
64
+
65
+ #### Benefits
66
+
67
+ - ✅ Nobody knows about anyone else
68
+ - ✅ Easy to add/remove systems
69
+ - ✅ Zero memory leaks (automatic cleanup)
48
70
 
49
71
  ## 📨 The Three Message Types (Simple!)
50
72
 
@@ -66,9 +88,9 @@ msg.Emit();
66
88
 
67
89
  // Anyone can listen
68
90
  _ = token.RegisterUntargeted<GamePaused>(OnPause);
69
- ```text
91
+ ```
70
92
 
71
- #### Real-world uses:
93
+ #### Real-world uses
72
94
 
73
95
  - "Game paused!"
74
96
  - "Settings changed!"
@@ -90,9 +112,9 @@ heal.EmitGameObjectTargeted(playerObject);
90
112
 
91
113
  // Only the player listens
92
114
  _ = token.RegisterComponentTargeted<Heal>(this, OnHeal);
93
- ```text
115
+ ```
94
116
 
95
- #### Real-world uses:
117
+ #### Real-world uses
96
118
 
97
119
  - "Player, heal yourself!"
98
120
  - "Enemy #3, take damage!"
@@ -117,9 +139,9 @@ _ = token.RegisterGameObjectBroadcast<TookDamage>(enemyObject, OnThisEnemy);
117
139
 
118
140
  // OR achievement system can listen to ALL enemies
119
141
  _ = token.RegisterBroadcastWithoutSource<TookDamage>(OnAnyEnemy);
120
- ```text
142
+ ```
121
143
 
122
- #### Real-world uses:
144
+ #### Real-world uses
123
145
 
124
146
  - "I (player) took damage!"
125
147
  - "I (enemy) died!"
@@ -129,33 +151,49 @@ _ = token.RegisterBroadcastWithoutSource<TookDamage>(OnAnyEnemy);
129
151
 
130
152
  When you send a message, here's what happens:
131
153
 
132
- ```text
133
- 1. You create a message
134
- var heal = new Heal(10);
135
-
136
- 2. You emit it
137
- heal.EmitGameObjectTargeted(player);
138
-
139
- 3. [OPTIONAL] Interceptors check it
140
- ┌─────────────────────────────┐
141
- │ Is damage valid? (>0) │
142
- Should we clamp it? (<999) │
143
- Cancel bad messages? ❌ │
144
- └─────────────────────────────┘
145
-
146
- 4. Handlers receive it (your main logic)
147
- ┌─────────────────────────────┐
148
- priority: 0 → SaveSystem │
149
- │ priority: 5 → AudioSystem │
150
- │ priority: 10 UISystem │
151
- └─────────────────────────────┘
152
-
153
- 5. [OPTIONAL] Post-processors log it
154
- ┌─────────────────────────────┐
155
- │ Analytics.Track(...) │
156
- │ Debug.Log(...) │
157
- └─────────────────────────────┘
158
- ```text
154
+ ```mermaid
155
+ sequenceDiagram
156
+ participant You as Your Code
157
+ participant Msg as Message
158
+ participant Int as Interceptors<br/>(Optional)
159
+ participant H0 as Handler<br/>priority: 0
160
+ participant H5 as Handler<br/>priority: 5
161
+ participant H10 as Handler<br/>priority: 10
162
+ participant PP as Post-Processors<br/>(Optional)
163
+
164
+ Note over You: 1. Create message
165
+ You->>Msg: var heal = new Heal(10);
166
+
167
+ Note over You,Msg: 2. Emit message
168
+ You->>Msg: heal.EmitGameObjectTargeted(player);
169
+
170
+ Note over Int: 3. Validate & Normalize
171
+ Msg->>Int: Check message
172
+ Int->>Int: Is valid? (>0)<br/>Clamp if needed (<999)
173
+ alt Invalid message
174
+ Int--xMsg: ❌ Cancel
175
+ else Valid message
176
+ Int->>H0: ✅ Continue
177
+ end
178
+
179
+ Note over H0,H10: 4. Execute handlers (by priority)
180
+ H0->>H0: SaveSystem runs first
181
+ H0->>H5: Next priority
182
+ H5->>H5: AudioSystem runs
183
+ H5->>H10: Next priority
184
+ H10->>H10: UISystem runs last
185
+
186
+ Note over PP: 5. Analytics & Logging
187
+ H10->>PP: All handlers complete
188
+ PP->>PP: Analytics.Track(...)<br/>Debug.Log(...)
189
+ ```
190
+
191
+ ### Key points
192
+
193
+ - **Step 1-2:** You create and emit the message
194
+ - **Step 3 (Optional):** Interceptors can validate, modify, or cancel
195
+ - **Step 4:** Handlers run in priority order (lower number = earlier)
196
+ - **Step 5 (Optional):** Post-processors run after everything (perfect for analytics)
159
197
 
160
198
  ## 🎮 Your First Message (3 Easy Steps)
161
199
 
@@ -169,7 +207,7 @@ using DxMessaging.Core.Attributes;
169
207
  public readonly partial struct Heal {
170
208
  public readonly int amount;
171
209
  }
172
- ````
210
+ ```
173
211
 
174
212
  #### What are those `[DxSomething]` tags?
175
213
 
@@ -228,20 +266,29 @@ healMsg.EmitComponentTargeted(playerComponent);
228
266
 
229
267
  ### Pattern: Scene Transition
230
268
 
231
- ```text
232
- SceneManager AudioSystem
233
- │ │
234
- │ [SceneChanged] │
235
- ├────────────────────────→ FadeOutMusic()
236
- │ │
237
- │ SaveSystem
238
- │ │
239
- │ [SceneChanged] │
240
- └────────────────────────→ │ SaveGame()
241
-
242
- All independent! No coupling!
269
+ ```mermaid
270
+ sequenceDiagram
271
+ participant SM as SceneManager
272
+ participant Bus as Message Bus
273
+ participant Audio as AudioSystem
274
+ participant Save as SaveSystem
275
+
276
+ Note over SM: Scene is changing
277
+ SM->>Bus: SceneChanged(sceneIndex: 2)
278
+
279
+ Note over Bus: Message broadcast to all listeners
280
+
281
+ Bus->>Audio: SceneChanged received
282
+ Audio->>Audio: FadeOutMusic()
283
+
284
+ Bus->>Save: SceneChanged received
285
+ Save->>Save: SaveGame()
286
+
287
+ Note over Audio,Save: ✅ All independent!<br/>No coupling!
243
288
  ```
244
289
 
290
+ **Why this works:** AudioSystem and SaveSystem don't know about SceneManager or each other. They just listen for `SceneChanged` messages and react independently.
291
+
245
292
  Code:
246
293
 
247
294
  ```csharp
@@ -261,16 +308,23 @@ _ = saveToken.RegisterUntargeted<SceneChanged>(OnScene);
261
308
 
262
309
  ### Pattern: Player Input → Action
263
310
 
264
- ```text
265
- InputSystem Player
266
- │ │
267
- │ [Jump] │
268
- ├───────────────→ ApplyForce()
269
- │ │
311
+ ```mermaid
312
+ sequenceDiagram
313
+ participant Input as InputSystem
314
+ participant Bus as Message Bus
315
+ participant Player as Player
316
+
317
+ Note over Input: User presses Space
318
+ Input->>Bus: Jump(force: 10f)<br/>[Targeted to Player]
270
319
 
271
- Decoupled! Input doesn't need reference to Player.
320
+ Bus->>Player: Jump message received
321
+ Player->>Player: ApplyForce()<br/>rb.AddForce(...)
322
+
323
+ Note over Input,Player: ✅ Decoupled!<br/>Input doesn't reference Player
272
324
  ```
273
325
 
326
+ **Why this works:** InputSystem doesn't need a reference to Player. It just sends a `Jump` message targeted at the player, and the player responds.
327
+
274
328
  Code:
275
329
 
276
330
  ```csharp
@@ -291,15 +345,29 @@ void OnJump(ref Jump msg) {
291
345
 
292
346
  ### Pattern: Achievement Tracking
293
347
 
294
- ````text
295
- Any System Achievement System
296
- │ │
297
- │ [Any Message] │
298
- ├─────────────────────────→ CheckProgress()
299
- │ │ UnlockIfReady()
348
+ ```mermaid
349
+ sequenceDiagram
350
+ participant E as Enemy
351
+ participant P as Player
352
+ participant C as Chest
353
+ participant Bus as Message Bus
354
+ participant Ach as Achievement System
355
+
356
+ Note over Ach: Listens to ALL messages
357
+
358
+ E->>Bus: EnemyKilled
359
+ Bus->>Ach: CheckProgress()<br/>UnlockIfReady()
300
360
 
301
- Achievements see EVERYTHING without coupling!
302
- ```text
361
+ P->>Bus: LevelCompleted
362
+ Bus->>Ach: CheckProgress()<br/>UnlockIfReady()
363
+
364
+ C->>Bus: ChestOpened
365
+ Bus->>Ach: CheckProgress()<br/>UnlockIfReady()
366
+
367
+ Note over Ach: ✅ Sees EVERYTHING<br/>without coupling!
368
+ ```
369
+
370
+ **Why this works:** Achievement System uses `RegisterGlobalAcceptAll()` to observe every message type, tracking progress across the entire game without any system knowing about it.
303
371
 
304
372
  Code:
305
373
 
@@ -315,7 +383,7 @@ public class AchievementSystem : MessageAwareComponent {
315
383
  );
316
384
  }
317
385
  }
318
- ````
386
+ ```
319
387
 
320
388
  ## 🚦 When to Use Which Message Type
321
389
 
@@ -344,64 +412,51 @@ Think of DxMessaging like a restaurant:
344
412
 
345
413
  ### Untargeted = Restaurant Announcement
346
414
 
347
- ````text
348
- "Attention all customers: We're closing in 10 minutes!"
349
- → Everyone hears it
350
- ```text
415
+ > "Attention all customers: We're closing in 10 minutes!"
416
+ >
417
+ > → Everyone hears it
351
418
 
352
419
  ### Targeted = Waiter Delivering Food
353
420
 
354
- ```text
355
- "Order for table 5: Here's your burger"
356
- → Only table 5 gets it
357
- ````
421
+ > "Order for table 5: Here's your burger"
422
+ >
423
+ > → Only table 5 gets it
358
424
 
359
425
  ### Broadcast = Customer Calling Waiter
360
426
 
361
- ````text
362
- "Excuse me, I need a refill!" (from table 3)
363
- → Comes from table 3
364
- → Any available waiter can respond
365
- Manager might track it for statistics
366
- ```text
427
+ > "Excuse me, I need a refill!" (from table 3)
428
+ >
429
+ > → Comes from table 3
430
+ >
431
+ > Any available waiter can respond
432
+ >
433
+ > → Manager might track it for statistics
367
434
 
368
435
  ## 🔍 Debugging Visualized
369
436
 
370
437
  DxMessaging has built-in Inspector support!
371
438
 
372
- ```text
373
- MessagingComponent Inspector:
374
- ┌─────────────────────────────────────┐
375
- │ Message History (last 10) │
376
- │ ┌─────────────────────────────────┐ │
377
- │ │ 12:34:05 - Heal → Player (50) │ │
378
- │ │ 12:34:03 - Jump → Player │ │
379
- │ │ 12:34:01 - GamePaused (global) │ │
380
- │ └─────────────────────────────────┘ │
381
- │ │
382
- │ Registrations: │
383
- │ ┌─────────────────────────────────┐ │
384
- │ │ ✓ Heal (priority: 0, 5 calls) │ │
385
- │ │ ✓ Jump (priority: 0, 2 calls) │ │
386
- │ │ ✓ TookDamage (priority: 10) │ │
387
- │ └─────────────────────────────────┘ │
388
- └─────────────────────────────────────┘
389
- ````
439
+ ### MessagingComponent Inspector
390
440
 
391
- ## Performance at a Glance
441
+ #### Message History (last 10)
392
442
 
393
- ```text
394
- Traditional C# Event: ████░░░░░░ (baseline)
395
- DxMessaging: █████░░░░░ (~10ns slower, negligible)
443
+ - `12:34:05 - Heal → Player (50)`
444
+ - `12:34:03 - Jump → Player`
445
+ - `12:34:01 - GamePaused (global)`
396
446
 
397
- Memory:
398
- Traditional Events: ████████░░ (can leak!)
399
- DxMessaging: ██░░░░░░░░ (zero leaks, struct messages)
447
+ ##### Registrations
400
448
 
401
- Coupling:
402
- Traditional Events: ██████████ (tight!)
403
- DxMessaging: ░░░░░░░░░░ (zero!)
404
- ```
449
+ - ✓ Heal (priority: 0, 5 calls)
450
+ - ✓ Jump (priority: 0, 2 calls)
451
+ - ✓ TookDamage (priority: 10)
452
+
453
+ ## ⚡ Performance at a Glance
454
+
455
+ | Metric | Traditional C# Events | DxMessaging |
456
+ | ------------ | --------------------- | ----------------------------------- |
457
+ | **Speed** | ⚡⚡⚡⚡ (baseline) | ⚡⚡⚡⚡ (~10ns slower, negligible) |
458
+ | **Memory** | ⚠️ Can leak! | ✅ Zero leaks (struct messages) |
459
+ | **Coupling** | ❌ Tight coupling | ✅ Zero coupling |
405
460
 
406
461
  **Bottom line:** Slightly slower than raw events, but:
407
462
 
@@ -412,57 +467,116 @@ DxMessaging: ░░░░░░░░░░ (zero!)
412
467
 
413
468
  ## 🎓 Learning Path
414
469
 
415
- ```text
416
- START HERE
417
-
418
- ├─→ 1. Read this Visual Guide (5 min)
419
-
420
- ├─→ 2. Try Quick Start example (5 min)
421
- [Define Listen Send]
422
-
423
- ├─→ 3. Import Mini Combat sample (10 min)
424
- │ [See it in action!]
425
-
426
- ├─→ 4. Read Common Patterns (15 min)
427
- │ [Real-world solutions]
428
-
429
- └─→ 5. Build your first feature! (30 min)
430
- [You're ready!]
470
+ ```mermaid
471
+ graph TD
472
+ Start[START HERE<br/>Read this Visual Guide<br/>5 min ✓]
473
+ Start --> Step2[Try Quick Start example<br/>5 min<br/>Define → Listen → Send]
474
+ Step2 --> Step3[Import Mini Combat sample<br/>10 min<br/>See it in action!]
475
+ Step3 --> Step4[Read Common Patterns<br/>15 min<br/>Real-world solutions]
476
+ Step4 --> Step5[Build your first feature!<br/>30 min<br/>You're ready!]
477
+
478
+ style Start fill:#91d5ff,stroke:#096dd9,stroke-width:3px,color:#000
479
+ style Step5 fill:#95de64,stroke:#237804,stroke-width:2px,color:#000
431
480
  ```
432
481
 
433
482
  ## 🆘 Common Beginner Questions
434
483
 
435
484
  ### "Do I always need MessageAwareComponent?"
436
485
 
437
- **For Unity:** Yes, it's the easiest way! It handles all lifecycle automatically.
486
+ **For Unity:** Yes! It's the easiest way. Think of it like `MonoBehaviour` - you inherit from it and it handles all the messy lifecycle stuff automatically.
487
+
488
+ **For pure C#:** No, you can use `MessageRegistrationToken` directly if you're not in Unity.
438
489
 
439
- **For pure C#:** No, you can use `MessageRegistrationToken` directly.
490
+ **Bottom line:** If you're in Unity, just use `MessageAwareComponent`. It'll save you hours of debugging.
440
491
 
441
492
  ### "Can I send a message to multiple targets?"
442
493
 
443
- **No** - Targeted is for ONE target. Instead:
494
+ **No** - Targeted messages go to ONE specific entity (like mailing a letter to one address).
495
+
496
+ #### Instead, use
497
+
498
+ - **Untargeted** if literally everyone should hear it (like a megaphone announcement)
499
+ - **Broadcast** if it's from one source and many can observe (like a news broadcast)
500
+
501
+ ##### Example
502
+
503
+ ```csharp
504
+ // ❌ DON'T: Try to target multiple entities
505
+ msg.EmitComponentTargeted(player1);
506
+ msg.EmitComponentTargeted(player2); // Feels wrong, right?
444
507
 
445
- - Use **Untargeted** if everyone should hear it
446
- - Use **Broadcast** if it's from a source and many can observe
508
+ // ✅ DO: Use broadcast so everyone can listen
509
+ msg.EmitGameObjectBroadcast(enemy); // Now anyone can observe this enemy
510
+ ```
447
511
 
448
512
  ### "What if I forget to unsubscribe?"
449
513
 
450
- **You can't!** DxMessaging handles it automatically when your component is destroyed. That's the magic! ✨
514
+ **You literally can't forget!** 🎉
515
+
516
+ When your component is destroyed, DxMessaging automatically cleans up. No `OnDestroy()` needed. No memory leaks possible.
517
+
518
+ #### Old way (easy to forget)
519
+
520
+ ```csharp
521
+ void OnEnable() { GameManager.OnScoreChanged += Update; }
522
+ void OnDisable() { GameManager.OnScoreChanged -= Update; } // Forgot this? LEAK!
523
+ ```
524
+
525
+ ##### DxMessaging way (impossible to forget)
526
+
527
+ ```csharp
528
+ protected override void RegisterMessageHandlers() {
529
+ _ = Token.RegisterUntargeted<ScoreChanged>(Update);
530
+ }
531
+ // That's it! Automatic cleanup when component dies.
532
+ ```
451
533
 
452
534
  ### "Is it slower than regular events?"
453
535
 
454
- **Barely** (~10ns per handler). You get SO much more (safety, observability, ordering) for negligible cost.
536
+ **Barely** (~10ns per handler = 0.00001 milliseconds).
537
+
538
+ #### Put it this way
539
+
540
+ - Regular C# event: ~50ns
541
+ - DxMessaging: ~60ns
542
+ - The difference: Drinking a coffee takes 3 billion nanoseconds
543
+
544
+ You get automatic lifecycle, zero leaks, full observability, and predictable ordering for a 20% overhead that's **completely negligible** in any real game.
455
545
 
456
546
  ### "Can I cancel a message?"
457
547
 
458
- **Yes!** Use an **Interceptor**:
548
+ #### Yes! That's what interceptors are for
459
549
 
460
550
  ```csharp
461
- _ = token.RegisterInterceptor<Damage>(
462
- (ref Damage msg) => msg.amount > 0 // Return false to cancel
551
+ // Cancel invalid damage
552
+ _ = token.RegisterBroadcastInterceptor<TookDamage>(
553
+ (ref InstanceId source, ref TookDamage msg) => {
554
+ if (msg.amount <= 0) return false; // Cancel invalid damage
555
+ if (IsInvincible(source)) return false; // Cancel during invincibility
556
+ return true; // Allow
557
+ }
463
558
  );
464
559
  ```
465
560
 
561
+ ##### Real-world uses
562
+
563
+ - Block input during cutscenes
564
+ - Cancel damage when invincible
565
+ - Prevent cheating (clamp values)
566
+ - Enforce game rules globally
567
+
568
+ ### "Can I see what messages are firing?"
569
+
570
+ #### Yes! Open any component in the Inspector and scroll down
571
+
572
+ You'll see:
573
+
574
+ - Message history (last 50 messages with timestamps)
575
+ - Active registrations (what you're listening to)
576
+ - Call counts (how many times each handler ran)
577
+
578
+ **No more guessing.** You can literally see your event flow in real-time.
579
+
466
580
  ## ✅ Quick Checklist: Am I Doing It Right
467
581
 
468
582
  - [ ] Using `MessageAwareComponent` for Unity components? ✅
@@ -1,5 +1,5 @@
1
1
  fileFormatVersion: 2
2
- guid: f3159f12192b58547a5f8576eeca5fcf
2
+ guid: ac94a51a66736f443b68aa222d32eb04
3
3
  PluginImporter:
4
4
  externalObjects: {}
5
5
  serializedVersion: 2
@@ -14,12 +14,12 @@ PluginImporter:
14
14
  - first:
15
15
  Any:
16
16
  second:
17
- enabled: 0
17
+ enabled: 1
18
18
  settings: {}
19
19
  - first:
20
20
  Editor: Editor
21
21
  second:
22
- enabled: 1
22
+ enabled: 0
23
23
  settings:
24
24
  DefaultValueInitialized: true
25
25
  - first:
@@ -14,12 +14,12 @@ PluginImporter:
14
14
  - first:
15
15
  Any:
16
16
  second:
17
- enabled: 1
17
+ enabled: 0
18
18
  settings: {}
19
19
  - first:
20
20
  Editor: Editor
21
21
  second:
22
- enabled: 0
22
+ enabled: 1
23
23
  settings:
24
24
  DefaultValueInitialized: true
25
25
  - first: