com.wallstop-studios.dxmessaging 2.1.5 → 2.1.7

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 (163) hide show
  1. package/.artifacts/SourceGenerators.Tests/obj/Debug/net9.0/WallstopStudios.DxMessaging.SourceGenerators.Tests.AssemblyInfo.cs +1 -1
  2. package/.cspell.json +4 -1
  3. package/.github/workflows/actionlint.yml +11 -1
  4. package/.github/workflows/csharpier-autofix.yml +34 -3
  5. package/.github/workflows/dotnet-tests.yml +13 -0
  6. package/.github/workflows/format-on-demand.yml +38 -44
  7. package/.github/workflows/json-format-check.yml +24 -0
  8. package/.github/workflows/lint-doc-links.yml +13 -0
  9. package/.github/workflows/markdown-json.yml +21 -4
  10. package/.github/workflows/markdown-link-text-check.yml +10 -0
  11. package/.github/workflows/markdown-link-validity.yml +10 -0
  12. package/.github/workflows/markdownlint.yml +7 -5
  13. package/.github/workflows/prettier-autofix.yml +67 -11
  14. package/.github/workflows/release-drafter.yml +2 -2
  15. package/.github/workflows/sync-wiki.yml +3 -3
  16. package/.github/workflows/yaml-format-lint.yml +26 -0
  17. package/.llm/context.md +113 -3
  18. package/.llm/skills/documentation/changelog-management.md +38 -0
  19. package/.llm/skills/documentation/documentation-style-guide.md +18 -0
  20. package/.llm/skills/documentation/documentation-update-workflow.md +2 -0
  21. package/.llm/skills/documentation/documentation-updates.md +2 -0
  22. package/.llm/skills/documentation/markdown-compatibility.md +476 -0
  23. package/.llm/skills/documentation/mermaid-theming.md +326 -0
  24. package/.llm/skills/documentation/mkdocs-navigation.md +290 -0
  25. package/.llm/skills/github-actions/git-renormalize-patterns.md +231 -0
  26. package/.llm/skills/github-actions/workflow-consistency.md +346 -0
  27. package/.llm/skills/index.md +53 -27
  28. package/.llm/skills/scripting/javascript-code-quality.md +417 -0
  29. package/.llm/skills/scripting/regex-documentation.md +461 -0
  30. package/.llm/skills/scripting/shell-best-practices.md +55 -4
  31. package/.llm/skills/scripting/validation-patterns.md +418 -0
  32. package/.llm/skills/specification.md +4 -1
  33. package/.llm/skills/testing/test-code-quality.md +243 -0
  34. package/.llm/skills/testing/test-production-code.md +348 -0
  35. package/CHANGELOG.md +24 -0
  36. package/README.md +113 -24
  37. package/Tests/Runtime/Benchmarks/WallstopStudios.DxMessaging.Tests.Runtime.Benchmarks.asmdef +1 -6
  38. package/Tests/Runtime/Integrations/Reflex/WallstopStudios.DxMessaging.Tests.Runtime.Reflex.asmdef +1 -1
  39. package/Tests/Runtime/Integrations/VContainer/WallstopStudios.DxMessaging.Tests.Runtime.VContainer.asmdef +1 -1
  40. package/Tests/Runtime/Integrations/Zenject/WallstopStudios.DxMessaging.Tests.Runtime.Zenject.asmdef +1 -1
  41. package/coverage/clover.xml +216 -3
  42. package/coverage/clover.xml.meta +7 -7
  43. package/coverage/coverage-final.json +2 -1
  44. package/coverage/coverage-final.json.meta +7 -7
  45. package/coverage/lcov-report/base.css.meta +1 -1
  46. package/coverage/lcov-report/block-navigation.js.meta +1 -1
  47. package/coverage/lcov-report/favicon.png.meta +1 -1
  48. package/coverage/lcov-report/index.html +25 -10
  49. package/coverage/lcov-report/index.html.meta +7 -7
  50. package/coverage/lcov-report/prettify.css.meta +1 -1
  51. package/coverage/lcov-report/prettify.js.meta +1 -1
  52. package/coverage/lcov-report/sort-arrow-sprite.png.meta +1 -1
  53. package/coverage/lcov-report/sorter.js.meta +1 -1
  54. package/coverage/lcov-report/transform-docs-to-wiki.js.html +1 -1
  55. package/coverage/lcov-report/transform-docs-to-wiki.js.html.meta +7 -7
  56. package/coverage/lcov-report/vendor.meta +1 -1
  57. package/coverage/lcov-report.meta +8 -8
  58. package/coverage/lcov.info +365 -0
  59. package/coverage/lcov.info.meta +7 -7
  60. package/docs/architecture/design-and-architecture.md +0 -1
  61. package/docs/concepts/index.md +37 -0
  62. package/docs/concepts/index.md.meta +7 -0
  63. package/docs/concepts/interceptors-and-ordering.md +0 -2
  64. package/docs/concepts/mental-model.md +390 -0
  65. package/docs/concepts/mental-model.md.meta +7 -0
  66. package/docs/concepts/message-types.md +0 -1
  67. package/docs/getting-started/getting-started.md +1 -0
  68. package/docs/getting-started/index.md +6 -5
  69. package/docs/getting-started/overview.md +1 -0
  70. package/docs/getting-started/quick-start.md +2 -1
  71. package/docs/getting-started/visual-guide.md +4 -10
  72. package/docs/hooks.py +10 -1
  73. package/docs/images/DxMessaging-banner.svg +1 -1
  74. package/docs/index.md +7 -7
  75. package/docs/javascripts/mermaid-config.js +44 -4
  76. package/docs/reference/helpers.md +130 -154
  77. package/docs/reference/quick-reference.md +5 -1
  78. package/docs/reference/reference.md +124 -130
  79. package/mkdocs.yml +2 -0
  80. package/package.json +7 -2
  81. package/scripts/__tests__/generate-skills-index.test.js +397 -0
  82. package/scripts/__tests__/generate-skills-index.test.js.meta +7 -0
  83. package/scripts/__tests__/mermaid-config.test.js +467 -0
  84. package/scripts/__tests__/mermaid-config.test.js.meta +7 -0
  85. package/scripts/__tests__/validate-skills-optional-fields.test.js +1474 -0
  86. package/scripts/__tests__/validate-skills-optional-fields.test.js.meta +7 -0
  87. package/scripts/__tests__/validate-skills-required-fields.test.js +188 -0
  88. package/scripts/__tests__/validate-skills-required-fields.test.js.meta +7 -0
  89. package/scripts/__tests__/validate-skills-tags.test.js +353 -0
  90. package/scripts/__tests__/validate-skills-tags.test.js.meta +7 -0
  91. package/scripts/__tests__/validate-workflows.test.js +188 -0
  92. package/scripts/__tests__/validate-workflows.test.js.meta +7 -0
  93. package/scripts/generate-skills-index.js +88 -3
  94. package/scripts/validate-skills.js +230 -30
  95. package/scripts/validate-workflows.js +272 -0
  96. package/scripts/validate-workflows.js.meta +7 -0
  97. package/scripts/wiki/generate-wiki-sidebar.js.meta +1 -8
  98. package/scripts/wiki/transform-docs-to-wiki.js.meta +1 -1
  99. package/site/404.html +1 -1
  100. package/site/advanced/emit-shorthands/index.html +2 -2
  101. package/site/advanced/message-bus-providers/index.html +2 -2
  102. package/site/advanced/registration-builders/index.html +2 -2
  103. package/site/advanced/runtime-configuration/index.html +2 -2
  104. package/site/advanced/string-messages/index.html +2 -2
  105. package/site/advanced.meta +1 -1
  106. package/site/architecture/comparisons/index.html +2 -2
  107. package/site/architecture/design-and-architecture/index.html +2 -2
  108. package/site/architecture/performance/index.html +1 -1
  109. package/site/architecture.meta +1 -1
  110. package/site/concepts/index.html +1 -0
  111. package/site/concepts/index.html.meta +7 -0
  112. package/site/concepts/interceptors-and-ordering/index.html +4 -4
  113. package/site/concepts/listening-patterns/index.html +2 -2
  114. package/site/concepts/mental-model/index.html +146 -0
  115. package/site/concepts/mental-model/index.html.meta +7 -0
  116. package/site/concepts/mental-model.meta +8 -0
  117. package/site/concepts/message-types/index.html +2 -2
  118. package/site/concepts/targeting-and-context/index.html +2 -2
  119. package/site/concepts.meta +1 -1
  120. package/site/examples/end-to-end/index.html +2 -2
  121. package/site/examples/end-to-end-scene-transitions/index.html +2 -2
  122. package/site/examples.meta +1 -1
  123. package/site/getting-started/getting-started/index.html +3 -3
  124. package/site/getting-started/index.html +4 -4
  125. package/site/getting-started/install/index.html +3 -3
  126. package/site/getting-started/overview/index.html +2 -2
  127. package/site/getting-started/quick-start/index.html +2 -2
  128. package/site/getting-started/visual-guide/index.html +11 -11
  129. package/site/getting-started.meta +1 -1
  130. package/site/guides/advanced/index.html +2 -2
  131. package/site/guides/diagnostics/index.html +2 -2
  132. package/site/guides/migration-guide/index.html +2 -2
  133. package/site/guides/patterns/index.html +2 -2
  134. package/site/guides/testing/index.html +2 -2
  135. package/site/guides/unity-integration/index.html +2 -2
  136. package/site/guides.meta +1 -1
  137. package/site/hooks.py.meta +1 -1
  138. package/site/images/DxMessaging-banner.svg +119 -0
  139. package/site/images/DxMessaging-banner.svg.meta +7 -0
  140. package/site/images.meta +8 -0
  141. package/site/index.html +2 -2
  142. package/site/integrations/index.html +2 -2
  143. package/site/integrations/reflex/index.html +2 -2
  144. package/site/integrations/vcontainer/index.html +2 -2
  145. package/site/integrations/zenject/index.html +2 -2
  146. package/site/integrations.meta +1 -1
  147. package/site/javascripts/csharp-highlight.js.meta +7 -7
  148. package/site/javascripts/mermaid-config.js +4 -1
  149. package/site/javascripts/mermaid-config.js.meta +1 -1
  150. package/site/javascripts.meta +1 -1
  151. package/site/reference/compatibility/index.html +1 -1
  152. package/site/reference/faq/index.html +1 -1
  153. package/site/reference/glossary/index.html +2 -2
  154. package/site/reference/helpers/index.html +15 -15
  155. package/site/reference/quick-reference/index.html +3 -3
  156. package/site/reference/reference/index.html +37 -37
  157. package/site/reference/troubleshooting/index.html +1 -1
  158. package/site/reference.meta +1 -1
  159. package/site/search/search_index.json +1 -1
  160. package/site/sitemap.xml +46 -38
  161. package/site/sitemap.xml.gz +0 -0
  162. package/site/stylesheets/extra.css.meta +1 -1
  163. package/site/stylesheets.meta +1 -1
@@ -0,0 +1,390 @@
1
+ # Mental Model: How to Think About DxMessaging
2
+
3
+ [← Concepts Index](index.md) | [Message Types](message-types.md) | [Getting Started](../getting-started/getting-started.md)
4
+
5
+ ---
6
+
7
+ This guide explains how to think about DxMessaging from first principles. Understanding the mental model makes everything else easier.
8
+
9
+ ## The Core Idea
10
+
11
+ DxMessaging is built around one principle: **it gets out of your way**.
12
+
13
+ You have data. You need to pass it around. That's the problem.
14
+
15
+ DxMessaging provides fast, simple primitives as building blocks. You model changes as message types with optional context, using game primitives (GameObjects, components) as that context. The library handles the plumbing.
16
+
17
+ You don't build your game INTO the messaging system. The messaging system is opt-in and optional - a tool you reach for when it helps.
18
+
19
+ ## What Problem Does This Solve?
20
+
21
+ In a typical Unity project, you face a common challenge:
22
+
23
+ ```text
24
+ Player takes damage
25
+ ├── Health bar needs updating
26
+ ├── Sound system plays damage audio
27
+ ├── Camera shakes
28
+ ├── Achievement system checks milestones
29
+ ├── Analytics logs the event
30
+ └── Tutorial system checks for tips
31
+ ```
32
+
33
+ Traditional approaches require tight coupling: either the Player knows about all these systems, or they all hold references to the Player. Both paths lead to tangled dependencies.
34
+
35
+ DxMessaging inverts this relationship. The Player broadcasts a fact - "I took 25 damage" - and interested systems subscribe to receive it. Systems come and go without the Player knowing or caring.
36
+
37
+ ## The Three Message Categories
38
+
39
+ DxMessaging models three fundamental patterns of communication. Each maps to a real-world analogy.
40
+
41
+ ### Untargeted: The PA System
42
+
43
+ ```mermaid
44
+ flowchart LR
45
+ S[Someone] -->|announces| PA[📢 PA System]
46
+ PA --> L1[Listener A]
47
+ PA --> L2[Listener B]
48
+ PA --> L3[Listener C]
49
+ ```
50
+
51
+ Untargeted messages are announcements. No specific recipient. No specific sender that matters. Everyone who cares can hear it.
52
+
53
+ > 📝 **Note: No sender identity**
54
+ >
55
+ > Unlike a real PA system, untargeted messages carry no concept of "who announced it." There is no sender identity attached - only the message content itself.
56
+
57
+ #### Real examples
58
+
59
+ - "The game is paused"
60
+ - "Settings changed"
61
+ - "Scene finished loading"
62
+ - "Day/night cycle switched to night"
63
+
64
+ ```csharp
65
+ // Define an untargeted message with attributes
66
+ [DxUntargetedMessage]
67
+ [DxAutoConstructor]
68
+ public readonly partial struct GamePaused
69
+ {
70
+ public readonly bool isPaused;
71
+ }
72
+
73
+ // Multiple fields are supported
74
+ [DxUntargetedMessage]
75
+ [DxAutoConstructor]
76
+ public readonly partial struct SettingsChanged
77
+ {
78
+ public readonly float volume;
79
+ public readonly int quality;
80
+ }
81
+ ```
82
+
83
+ **Use when:** You need to announce something to whoever might care. The sender doesn't know or care who's listening.
84
+
85
+ ### Targeted: The Addressed Letter
86
+
87
+ ```mermaid
88
+ flowchart LR
89
+ S[Sender] -->|"To: Player"| Letter[📬 Message Bus]
90
+ Letter --> Player[Player receives]
91
+ Other1[Enemy A] -.->|ignores| Letter
92
+ Other2[Enemy B] -.->|ignores| Letter
93
+ ```
94
+
95
+ Targeted messages are commands or directed events. They have a specific recipient. Only that recipient (and any interested observers) receives them.
96
+
97
+ #### Real examples
98
+
99
+ - "Player, heal for 10 HP"
100
+ - "Door #7, open"
101
+ - "This specific enemy, take 25 damage"
102
+ - "Inventory slot 3, equip this weapon"
103
+
104
+ ```csharp
105
+ // Define a targeted message with attributes
106
+ [DxTargetedMessage]
107
+ [DxAutoConstructor]
108
+ public readonly partial struct Heal
109
+ {
110
+ public readonly int amount;
111
+ }
112
+
113
+ // Emit to a specific target
114
+ Heal heal = new Heal(10);
115
+ heal.EmitGameObjectTargeted(playerGameObject);
116
+ ```
117
+
118
+ **Use when:** You're commanding a specific entity to do something, or notifying a specific entity about something that happened to it.
119
+
120
+ ### Broadcast: The Radio Station
121
+
122
+ ```mermaid
123
+ flowchart LR
124
+ Source[Enemy] -->|"I took damage!"| Radio[📻 Message Bus]
125
+ Radio --> L1[Damage Numbers UI]
126
+ Radio --> L2[Achievement Tracker]
127
+ Radio --> L3[Analytics]
128
+ Radio --> L4[Combat Log]
129
+ ```
130
+
131
+ Broadcast messages are facts emitted by a specific source. Unlike targeted messages, there's no intended recipient - just an origin. Anyone who wants to observe can tune in.
132
+
133
+ #### Real examples
134
+
135
+ - "This enemy took 25 damage" (from the enemy)
136
+ - "The player picked up item X" (from the player)
137
+ - "This chest opened" (from the chest)
138
+ - "Projectile hit something" (from the projectile)
139
+
140
+ ```csharp
141
+ // Define a broadcast message with attributes
142
+ [DxBroadcastMessage]
143
+ [DxAutoConstructor]
144
+ public readonly partial struct TookDamage
145
+ {
146
+ public readonly int amount;
147
+ }
148
+
149
+ // Emit from a specific source
150
+ TookDamage damage = new TookDamage(25);
151
+ damage.EmitGameObjectBroadcast(thisEnemy);
152
+ ```
153
+
154
+ **Use when:** Something happened to an entity, and other systems might want to know about it. The entity doesn't care who's listening.
155
+
156
+ ## Deciding Which Type to Use
157
+
158
+ ```mermaid
159
+ flowchart TD
160
+ Start([I need to send a message])
161
+ Start --> Q1{Does it matter<br/>WHO sent it?}
162
+
163
+ Q1 -->|No| Q2{Does it matter<br/>WHO receives it?}
164
+ Q2 -->|No| Untargeted[Use UNTARGETED<br/>Global announcement]
165
+ Q2 -->|Yes| Targeted[Use TARGETED<br/>Directed command]
166
+
167
+ Q1 -->|Yes| Q3{Am I commanding<br/>someone to act?}
168
+ Q3 -->|Yes| Targeted
169
+ Q3 -->|No| Broadcast[Use BROADCAST<br/>Observable fact]
170
+ ```
171
+
172
+ | Question | Untargeted | Targeted | Broadcast |
173
+ | ----------------------------------- | :--------: | :------: | :-------: |
174
+ | Has a specific sender that matters? | ❌ | ❌ | ✅ |
175
+ | Has a specific recipient? | ❌ | ✅ | ❌ |
176
+ | Is it a command? | ❌ | ✅ | ❌ |
177
+ | Is it an observable fact? | Maybe | ❌ | ✅ |
178
+ | Is it a global announcement? | ✅ | ❌ | ❌ |
179
+
180
+ ## Tokens and Lifecycle
181
+
182
+ Registration in DxMessaging happens through tokens. A `MessageRegistrationToken` collects your registrations and ties them to a lifecycle.
183
+
184
+ ### The Pattern
185
+
186
+ ```csharp
187
+ public class HealthDisplay : MessageAwareComponent
188
+ {
189
+ protected override void RegisterMessageHandlers()
190
+ {
191
+ base.RegisterMessageHandlers();
192
+
193
+ // Register handlers through the Token
194
+ _ = Token.RegisterGameObjectBroadcast<TookDamage>(player, OnPlayerDamaged);
195
+ _ = Token.RegisterUntargeted<GamePaused>(OnGamePaused);
196
+ }
197
+
198
+ private void OnPlayerDamaged(ref TookDamage msg) { /* update display */ }
199
+ private void OnGamePaused(ref GamePaused msg) { /* pause animations */ }
200
+ }
201
+ ```
202
+
203
+ > ⚠️ **Warning: Always call `base.RegisterMessageHandlers()`**
204
+ >
205
+ > When overriding `RegisterMessageHandlers()`, always call `base.RegisterMessageHandlers()` first. This ensures that any registrations from parent classes are preserved. Forgetting this call can silently break inherited behavior.
206
+
207
+ ### What the Token Does
208
+
209
+ ```mermaid
210
+ sequenceDiagram
211
+ participant C as Component
212
+ participant T as Token
213
+ participant B as MessageBus
214
+
215
+ Note over C,B: Awake
216
+ C->>T: Create Token
217
+ C->>T: Register handlers
218
+ T-->>T: Stage (not active yet)
219
+
220
+ Note over C,B: OnEnable
221
+ C->>T: Enable()
222
+ T->>B: Activate registrations
223
+
224
+ Note over C,B: Messages flow
225
+ B->>C: Handler called
226
+
227
+ Note over C,B: OnDisable
228
+ C->>T: Disable()
229
+ T->>B: Deactivate registrations
230
+
231
+ Note over C,B: OnDestroy
232
+ C->>T: Dispose/Release
233
+ T->>B: Remove registrations
234
+ ```
235
+
236
+ The token:
237
+
238
+ 1. **Stages** registrations when you call `Register*` methods
239
+ 1. **Activates** them when you call `Enable()`
240
+ 1. **Deactivates** them when you call `Disable()`
241
+ 1. **Cleans up** when the token is disposed or the component is destroyed
242
+
243
+ This maps directly to Unity's lifecycle: registrations activate in `OnEnable`, deactivate in `OnDisable`, and clean up in `OnDestroy`.
244
+
245
+ ### Why Tokens Matter
246
+
247
+ Tokens prevent common event system bugs:
248
+
249
+ - **No forgotten unsubscribes**: The token tracks everything
250
+ - **No null reference handlers**: Disabled tokens don't receive messages
251
+ - **No memory leaks**: Token cleanup is automatic with `MessageAwareComponent`
252
+ - **Predictable timing**: Enable/disable follows Unity's enable state
253
+
254
+ ## Context Through Game Primitives
255
+
256
+ DxMessaging uses Unity's primitives (GameObjects, Components) as natural context for messages.
257
+
258
+ ### InstanceId
259
+
260
+ Every registration and emission uses an `InstanceId` - a lightweight identifier that wraps a Unity Object's instance ID. You rarely need to create these manually because extension methods handle the conversion:
261
+
262
+ ```csharp
263
+ // These are equivalent:
264
+ heal.EmitGameObjectTargeted(playerGameObject);
265
+ heal.EmitTargeted((InstanceId)playerGameObject);
266
+
267
+ // Registering for a specific component
268
+ Token.RegisterComponentTargeted<Damage>(this, OnDamage);
269
+
270
+ // Registering for a whole GameObject
271
+ Token.RegisterGameObjectTargeted<Damage>(gameObject, OnDamage);
272
+ ```
273
+
274
+ ### GameObject vs Component Targeting
275
+
276
+ You can target at two levels:
277
+
278
+ **GameObject level**: All components on that GameObject can respond
279
+
280
+ ```csharp
281
+ // Registration
282
+ Token.RegisterGameObjectTargeted<Command>(gameObject, HandleCommand);
283
+
284
+ // Emission (any component on playerGO can receive this)
285
+ command.EmitGameObjectTargeted(playerGO);
286
+ ```
287
+
288
+ **Component level**: Only that specific component responds
289
+
290
+ ```csharp
291
+ // Registration
292
+ Token.RegisterComponentTargeted<Command>(this, HandleCommand);
293
+
294
+ // Emission (only this specific component instance receives this)
295
+ command.EmitComponentTargeted(specificComponent);
296
+ ```
297
+
298
+ ## Observing Without Targeting
299
+
300
+ Sometimes you want to see all messages of a type, regardless of their target or source.
301
+
302
+ ### Observing All Targeted Messages
303
+
304
+ ```csharp
305
+ // See every Heal message, no matter who it's for
306
+ Token.RegisterTargetedWithoutTargeting<Heal>(OnAnyHeal);
307
+
308
+ void OnAnyHeal(ref InstanceId target, ref Heal msg)
309
+ {
310
+ // 'target' tells you who was healed
311
+ Debug.Log($"Someone healed {target} for {msg.amount}");
312
+ }
313
+ ```
314
+
315
+ ### Observing All Broadcast Messages
316
+
317
+ ```csharp
318
+ // See every TookDamage message, no matter who broadcast it
319
+ Token.RegisterBroadcastWithoutSource<TookDamage>(OnAnyDamage);
320
+
321
+ void OnAnyDamage(ref InstanceId source, ref TookDamage msg)
322
+ {
323
+ // 'source' tells you who took damage
324
+ Debug.Log($"{source} took {msg.amount} damage");
325
+ }
326
+ ```
327
+
328
+ These patterns are useful for:
329
+
330
+ - Analytics systems
331
+ - Combat logs
332
+ - Debug overlays
333
+ - Achievement tracking
334
+ - Network replication
335
+
336
+ ## The "Gets Out of the Way" Philosophy
337
+
338
+ DxMessaging is designed to be invisible when you don't need it:
339
+
340
+ 1. **No global state pollution**: Messages are just data. Define them anywhere.
341
+ 1. **No inheritance requirements**: Implement an interface or add an attribute. That's it.
342
+ 1. **No framework lock-in**: Your message structs are plain C#. They work outside DxMessaging.
343
+ 1. **No ceremony**: Define a struct, emit it, handle it. Three steps.
344
+ 1. **Optional everywhere**: Don't want to use it for something? Don't. Mix and match.
345
+
346
+ The library provides primitives. You compose them into patterns that fit your game.
347
+
348
+ ## Common Patterns at a Glance
349
+
350
+ | Pattern | Message Type | Registration | Emission |
351
+ | --------------------- | ------------ | ------------------------------------- | --------------------------------- |
352
+ | Global setting change | Untargeted | `RegisterUntargeted<T>` | `msg.EmitUntargeted()` |
353
+ | Command to entity | Targeted | `RegisterGameObjectTargeted<T>` | `msg.EmitGameObjectTargeted(go)` |
354
+ | Something happened | Broadcast | `RegisterGameObjectBroadcast<T>` | `msg.EmitGameObjectBroadcast(go)` |
355
+ | Observe all of type | Targeted | `RegisterTargetedWithoutTargeting<T>` | (normal emission) |
356
+ | Observe all sources | Broadcast | `RegisterBroadcastWithoutSource<T>` | (normal emission) |
357
+
358
+ ## Common Mistakes
359
+
360
+ When getting started with DxMessaging, watch out for these common pitfalls:
361
+
362
+ ### Forgetting to Enable the Token
363
+
364
+ Registrations are **staged** when you call `Register*` methods, but they don't become active until the token is enabled. If you're using `MessageAwareComponent`, this is handled automatically. If managing tokens manually, remember to call `Token.Enable()` after registering.
365
+
366
+ ### Targeting Component When You Meant GameObject (or Vice Versa)
367
+
368
+ Component-level targeting (`EmitComponentTargeted`) and GameObject-level targeting (`EmitGameObjectTargeted`) are distinct. A message emitted to a specific component won't be received by handlers registered at the GameObject level for the same object, and vice versa. Be deliberate about which level you're targeting.
369
+
370
+ ### Forgetting to Call `base.RegisterMessageHandlers()`
371
+
372
+ See the warning in [The Pattern](#the-pattern) above. Always call the base method first when overriding `RegisterMessageHandlers()`.
373
+
374
+ ### Not Understanding Synchronous Handler Execution
375
+
376
+ Message handlers are called **synchronously** and **immediately** when a message is emitted. This means:
377
+
378
+ - The emitting code blocks until all handlers complete
379
+ - Long-running handlers will cause frame hitches
380
+ - Handlers execute in registration order (modified by priority)
381
+ - Exceptions in handlers can affect other handlers if not caught
382
+
383
+ Design your handlers to be fast and non-blocking.
384
+
385
+ ## Next Steps
386
+
387
+ - [Message Types](message-types.md): Detailed reference for all three types
388
+ - [Listening Patterns](listening-patterns.md): All the ways to receive messages
389
+ - [Getting Started](../getting-started/getting-started.md): Hands-on walkthrough
390
+ - [Patterns Guide](../guides/patterns.md): Real-world usage patterns
@@ -0,0 +1,7 @@
1
+ fileFormatVersion: 2
2
+ guid: 0c9de8e7ff245f9418daa03503a37ad8
3
+ TextScriptImporter:
4
+ externalObjects: {}
5
+ userData:
6
+ assetBundleName:
7
+ assetBundleVariant:
@@ -15,7 +15,6 @@ This guide introduces the three message categories in DxMessaging with concepts,
15
15
  ### Quick Decision Guide
16
16
 
17
17
  ```mermaid
18
- %%{init: {'theme': 'neutral'}}%%
19
18
  flowchart TD
20
19
  Start([Choose Message Type])
21
20
 
@@ -182,6 +182,7 @@ Checklist:
182
182
 
183
183
  ## Next Steps
184
184
 
185
+ - [Mental Model](../concepts/mental-model.md) - Understand the philosophy behind DxMessaging
185
186
  - [Visual Guide](visual-guide.md)
186
187
  - [Quick Reference](../reference/quick-reference.md)
187
188
  - [Diagnostics](../guides/diagnostics.md)
@@ -5,8 +5,7 @@ This is the documentation for DxMessaging, a type-safe messaging system for Unit
5
5
  ## Visual Documentation Map
6
6
 
7
7
  ```mermaid
8
- %%{init: {'theme': 'neutral'}}%%
9
- graph TD
8
+ flowchart TD
10
9
  Start[START HERE<br/>Visual Guide<br/>5 minutes]
11
10
  Start --> Quick[Quick Start<br/>5 min]
12
11
  Start --> Getting[Getting Started<br/>10 min]
@@ -39,6 +38,7 @@ graph TD
39
38
 
40
39
  **Never used a messaging system before?** Start here:
41
40
 
41
+ 1. **[Mental Model](../concepts/mental-model.md)** - How to think about DxMessaging (10 min)
42
42
  1. **[Visual Guide](visual-guide.md)** - Beginner-friendly visual introduction (5 min)
43
43
  1. **[Getting Started Guide](getting-started.md)** - Comprehensive guide with examples (10 min)
44
44
  1. **[Quick Start](quick-start.md)** - Your first working message (5 min)
@@ -48,6 +48,7 @@ graph TD
48
48
 
49
49
  ### For Absolute Beginners (Never Used Messaging Before)
50
50
 
51
+ 1. Read [Mental Model](../concepts/mental-model.md) (10 min) - Philosophy first!
51
52
  1. Read [Visual Guide](visual-guide.md) (5 min) - Pictures and analogies!
52
53
  1. Read [Getting Started](getting-started.md) (10 min) - Complete introduction
53
54
  1. Try [Quick Start](quick-start.md) (5 min) - Hands-on tutorial
@@ -166,7 +167,6 @@ From [Common Patterns](../guides/patterns.md):
166
167
  Every message flows through 3 stages:
167
168
 
168
169
  ```mermaid
169
- %%{init: {'theme': 'neutral'}}%%
170
170
  flowchart LR
171
171
  P[Producer] --> I[Interceptors<br/>validate/mutate/cancel]
172
172
  I --> H[Handlers<br/>main logic by priority]
@@ -298,9 +298,10 @@ From [Comparisons](../architecture/comparisons.md):
298
298
 
299
299
  ## Quick Start Path
300
300
 
301
- **Absolute Beginner?** Follow this 30-minute path:
301
+ **Absolute Beginner?** Follow this 40-minute path:
302
302
 
303
- 1. 5 min: [Visual Guide](visual-guide.md) - Start here for pictures & analogies!
303
+ 1. 10 min: [Mental Model](../concepts/mental-model.md) - Understand the philosophy first!
304
+ 1. 5 min: [Visual Guide](visual-guide.md) - Pictures & analogies
304
305
  1. 10 min: [Getting Started](getting-started.md) - Deep dive
305
306
  1. 5 min: [Quick Start](quick-start.md) - Hands-on code
306
307
  1. 10 min: Try a [Sample](https://github.com/wallstop/DxMessaging/blob/master/Samples~/Mini%20Combat/README.md) - See it in action
@@ -142,6 +142,7 @@ _ = Token.RegisterBroadcastWithoutSource<TookDamage>(
142
142
 
143
143
  ### Start Here
144
144
 
145
+ - -> [Mental Model](../concepts/mental-model.md) (10 min) - Philosophy and first principles
145
146
  - -> [Visual Guide](visual-guide.md) (5 min) - Beginner-friendly introduction
146
147
  - -> [Getting Started](getting-started.md) (10 min) - Complete guide
147
148
  - -> [Quick Start](quick-start.md) (5 min) - Working example
@@ -143,7 +143,8 @@ Registration cleanup is automatic. Messages are type-safe.
143
143
  ## Next Steps
144
144
 
145
145
  - **Understand What You Did**
146
- - -> [Getting Started Guide](getting-started.md) (10 min) - Full explanation with mental models
146
+ - -> [Mental Model](../concepts/mental-model.md) (10 min) - Philosophy and first principles
147
+ - -> [Getting Started Guide](getting-started.md) (10 min) - Full explanation with examples
147
148
  - -> [Visual Guide](visual-guide.md) (5 min) - Pictures and analogies
148
149
  - **Try Real Examples**
149
150
  - -> [Mini Combat sample](https://github.com/wallstop/DxMessaging/blob/master/Samples~/Mini%20Combat/README.md) - Working combat example
@@ -7,8 +7,7 @@ If you're brand new to messaging systems, this visual guide will help you unders
7
7
  ### The Old Way (Spaghetti Code)
8
8
 
9
9
  ```mermaid
10
- %%{init: {'theme': 'neutral'}}%%
11
- graph LR
10
+ flowchart LR
12
11
  Player[Player]
13
12
  Enemy[Enemy]
14
13
  Inventory[Inventory]
@@ -36,8 +35,7 @@ graph LR
36
35
  ### The DxMessaging Way (Clean Separation)
37
36
 
38
37
  ```mermaid
39
- %%{init: {'theme': 'neutral'}}%%
40
- graph TB
38
+ flowchart TB
41
39
  Player[Player]
42
40
  Enemy[Enemy]
43
41
  Inventory[Inventory]
@@ -152,7 +150,6 @@ _ = token.RegisterBroadcastWithoutSource<TookDamage>(OnAnyEnemy);
152
150
  When you send a message, here's what happens:
153
151
 
154
152
  ```mermaid
155
- %%{init: {'theme': 'neutral'}}%%
156
153
  sequenceDiagram
157
154
  participant You as Your Code
158
155
  participant Msg as Message
@@ -268,7 +265,6 @@ healMsg.EmitComponentTargeted(playerComponent);
268
265
  ### Pattern: Scene Transition
269
266
 
270
267
  ```mermaid
271
- %%{init: {'theme': 'neutral'}}%%
272
268
  sequenceDiagram
273
269
  participant SM as SceneManager
274
270
  participant Bus as Message Bus
@@ -311,7 +307,6 @@ _ = saveToken.RegisterUntargeted<SceneChanged>(OnScene);
311
307
  ### Pattern: Player Input -> Action
312
308
 
313
309
  ```mermaid
314
- %%{init: {'theme': 'neutral'}}%%
315
310
  sequenceDiagram
316
311
  participant Input as InputSystem
317
312
  participant Bus as Message Bus
@@ -349,7 +344,6 @@ void OnJump(ref Jump msg) {
349
344
  ### Pattern: Achievement Tracking
350
345
 
351
346
  ```mermaid
352
- %%{init: {'theme': 'neutral'}}%%
353
347
  sequenceDiagram
354
348
  participant E as Enemy
355
349
  participant P as Player
@@ -472,8 +466,7 @@ DxMessaging has built-in Inspector support!
472
466
  ## Learning Path
473
467
 
474
468
  ```mermaid
475
- %%{init: {'theme': 'neutral'}}%%
476
- graph TD
469
+ flowchart TD
477
470
  Start[START HERE<br/>Read this Visual Guide<br/>5 min]
478
471
  Start --> Step2[Try Quick Start example<br/>5 min<br/>Define -> Listen -> Send]
479
472
  Step2 --> Step3[Import Mini Combat sample<br/>10 min<br/>See it in action!]
@@ -601,6 +594,7 @@ If you checked all these, you are following best practices.
601
594
 
602
595
  Ready to dive deeper?
603
596
 
597
+ 1. **[Mental Model](../concepts/mental-model.md)** - Understand the philosophy
604
598
  1. **[Getting Started Guide](getting-started.md)** - Full guide with more details
605
599
  1. **[Common Patterns](../guides/patterns.md)** - Real-world examples
606
600
  1. **[Message Types](../concepts/message-types.md)** - Deep dive into when to use what
package/docs/hooks.py CHANGED
@@ -28,11 +28,20 @@ SOURCE_PREFIXES = ("Runtime/", "Tests/", "Editor/", "Samples~/")
28
28
  MARKDOWN_LINK_PATTERN = re.compile(r"\[([^\]]+)\]\(([^)]+)\)")
29
29
 
30
30
  # Regex to match fenced code blocks (``` or ~~~ with optional language specifier)
31
- # Uses DOTALL to match across newlines
31
+ # Regex flags used:
32
+ # - DOTALL (s): Makes . match newline characters, allowing pattern to span multiple lines
33
+ # The re.sub() method with this pattern finds all occurrences (equivalent to 'g' global flag)
34
+ # Pattern is case-sensitive (no IGNORECASE flag needed - backticks are symbols)
35
+ # No MULTILINE flag needed - we don't use ^ or $ anchors
32
36
  FENCED_CODE_BLOCK_PATTERN = re.compile(r"(```|~~~)[^\n]*\n.*?\1", re.DOTALL)
33
37
 
34
38
  # Regex to match inline code (handles multiple backticks like `` or ```)
35
39
  # Matches backtick(s), then content that doesn't contain that same sequence, then same backticks
40
+ # Regex flags used:
41
+ # - DOTALL (s): Makes . match newline characters, allowing inline code to span lines
42
+ # The re.sub() method with this pattern finds all occurrences (equivalent to 'g' global flag)
43
+ # Pattern is case-sensitive (no IGNORECASE flag needed - backticks are symbols)
44
+ # No MULTILINE flag needed - we don't use ^ or $ anchors
36
45
  INLINE_CODE_PATTERN = re.compile(r"(`+)(?!`)(.*?)(?<!`)\1(?!`)", re.DOTALL)
37
46
 
38
47
 
@@ -107,7 +107,7 @@
107
107
  <!-- Version badge (top right) - text must contain vX.Y.Z for version sync -->
108
108
  <g transform="translate(720, 25)">
109
109
  <rect x="0" y="-12" width="60" height="22" rx="11" fill="#e94560" filter="url(#softShadow)"/>
110
- <text x="30" y="4" text-anchor="middle" font-family="'SF Mono', 'Fira Code', monospace" font-size="12" font-weight="600" fill="#ffffff" letter-spacing="0.5">v2.1.5</text>
110
+ <text x="30" y="4" text-anchor="middle" font-family="'SF Mono', 'Fira Code', monospace" font-size="12" font-weight="600" fill="#ffffff" letter-spacing="0.5">v2.1.7</text>
111
111
  </g>
112
112
 
113
113
  <!-- Wallstop Studios branding (bottom right) -->
package/docs/index.md CHANGED
@@ -7,19 +7,19 @@ description: High-performance type-safe messaging library for Unity
7
7
 
8
8
  **DxMessaging** is a high-performance, type-safe messaging library for Unity that provides a clean, decoupled communication pattern between game components.
9
9
 
10
- [Get Started](getting-started/index.md){ .md-button .md-button--primary }
11
- [View on GitHub](https://github.com/wallstop/DxMessaging){ .md-button }
10
+ **[Get Started](getting-started/index.md)** | [View on GitHub](https://github.com/wallstop/DxMessaging)
12
11
 
13
12
  ## Why DxMessaging?
14
13
 
15
- - :zap: **High Performance** — Zero-allocation message dispatch with pooled handlers
16
- - :shield: **Type-Safe** — Compile-time message type checking prevents runtime errors
17
- - :package: **Decoupled Architecture** — Components communicate without direct references
18
- - :dart: **Flexible Targeting** — Untargeted, Targeted, and Broadcast message patterns
19
- - :wrench: **Unity-Native** — Built specifically for Unity with MonoBehaviour integration
14
+ - **High Performance** — Zero-allocation message dispatch with pooled handlers
15
+ - 🛡️ **Type-Safe** — Compile-time message type checking prevents runtime errors
16
+ - 📦 **Decoupled Architecture** — Components communicate without direct references
17
+ - 🎯 **Flexible Targeting** — Untargeted, Targeted, and Broadcast message patterns
18
+ - 🔧 **Unity-Native** — Built specifically for Unity with MonoBehaviour integration
20
19
 
21
20
  ## Quick Links
22
21
 
22
+ - **[Mental Model](concepts/mental-model.md)** — How to think about DxMessaging
23
23
  - **[Visual Guide](getting-started/visual-guide.md)** — Beginner-friendly introduction with diagrams
24
24
  - **[Quick Start](getting-started/quick-start.md)** — Your first message in 5 minutes
25
25
  - **[Message Types](concepts/message-types.md)** — Untargeted, Targeted, Broadcast patterns