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.
- package/.github/workflows/dotnet-tests.yml +1 -1
- package/AGENTS.md +12 -12
- package/Docs/Comparisons.md +5 -5
- package/Docs/InterceptorsAndOrdering.md +1 -1
- package/Docs/Performance.md +13 -13
- package/Docs/QuickReference.md +1 -1
- package/Docs/Reference.md +5 -5
- package/Editor/Analyzers/WallstopStudios.DxMessaging.SourceGenerators.dll +0 -0
- package/Editor/CustomEditors/MessagingComponentEditor.cs +3 -0
- package/Editor/DxMessagingEditorInitializer.cs +58 -1
- package/Editor/DxMessagingMenu.cs +38 -0
- package/Editor/DxMessagingMenu.cs.meta +11 -0
- package/Editor/DxMessagingSceneBuildProcessor.cs +81 -0
- package/Editor/DxMessagingSceneBuildProcessor.cs.meta +11 -0
- package/Editor/Settings/DxMessagingSettings.cs +37 -6
- package/Editor/Settings/DxMessagingSettingsProvider.cs +45 -7
- package/README.md +1 -1
- package/Runtime/Core/Attributes/DxOptionalParameterAttribute.cs +52 -0
- package/Runtime/Core/DataStructure/CyclicBuffer.cs +16 -0
- package/Runtime/Core/Diagnostics/MessageEmissionData.cs +1 -1
- package/Runtime/Core/Diagnostics/MessageRegistrationType.cs +62 -0
- package/Runtime/Core/DxMessagingStaticState.cs +108 -0
- package/Runtime/Core/DxMessagingStaticState.cs.meta +11 -0
- package/Runtime/Core/Extensions/IListExtensions.cs +24 -0
- package/Runtime/Core/Extensions/MessageBusExtensions.cs +142 -0
- package/Runtime/Core/Helper/MessageCache.cs +16 -0
- package/Runtime/Core/Helper/MessageHelperIndexer.cs +77 -0
- package/Runtime/Core/InstanceId.cs +86 -0
- package/Runtime/Core/MessageBus/DiagnosticsTarget.cs +31 -0
- package/Runtime/Core/MessageBus/DiagnosticsTarget.cs.meta +11 -0
- package/Runtime/Core/MessageBus/IMessageBus.cs +44 -16
- package/Runtime/Core/MessageBus/MessageBus.cs +92 -21
- package/Runtime/Core/MessageBus/MessageRegistrationBuilder.cs +44 -0
- package/Runtime/Core/MessageBus/MessagingRegistration.cs +60 -2
- package/Runtime/Core/MessageBus/RegistrationLog.cs +10 -0
- package/Runtime/Core/MessageHandler.cs +107 -6
- package/Runtime/Core/MessageRegistrationHandle.cs +59 -0
- package/Runtime/Core/MessageRegistrationToken.cs +18 -2
- package/Runtime/Core/Messages/ReflexiveMessage.cs +38 -0
- package/Runtime/Core/MessagingDebug.cs +16 -1
- package/Runtime/Unity/CurrentGlobalMessageBusProvider.cs +4 -0
- package/Runtime/Unity/DxMessagingRuntimeInitializer.cs +19 -0
- package/Runtime/Unity/DxMessagingRuntimeInitializer.cs.meta +11 -0
- package/Runtime/Unity/InitialGlobalMessageBusProvider.cs +4 -0
- package/Runtime/Unity/Integrations/Reflex/ReflexRegistrationInstaller.cs +17 -0
- package/Runtime/Unity/Integrations/VContainer/VContainerRegistrationExtensions.cs +8 -0
- package/Runtime/Unity/Integrations/Zenject/ZenjectRegistrationInstaller.cs +12 -0
- package/Runtime/Unity/MessagingComponent.cs +93 -0
- package/Samples~/DI/README.md +13 -13
- package/Samples~/Mini Combat/README.md +15 -15
- package/Samples~/Mini Combat/Walkthrough.md +12 -12
- package/Samples~/UI Buttons + Inspector/README.md +4 -4
- package/SourceGenerators/WallstopStudios.DxMessaging.SourceGenerators/DxAutoConstructorGenerator.cs +4 -0
- package/SourceGenerators/WallstopStudios.DxMessaging.SourceGenerators/DxMessageIdGenerator.cs +4 -0
- package/Tests/Runtime/Core/DiagnosticsTests.cs +3 -3
- package/Tests/Runtime/Core/DxMessagingStaticStateTests.cs +69 -0
- package/Tests/Runtime/Core/DxMessagingStaticStateTests.cs.meta +11 -0
- package/package.json +1 -1
- package/Tests/Runtime/WallstopStudios.DxMessaging.Tests.Runtime.csproj +0 -20
- 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
|
package/Samples~/DI/README.md
CHANGED
|
@@ -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
|
|
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
|
-
-
|
|
23
|
-
-
|
|
24
|
-
-
|
|
25
|
-
-
|
|
26
|
-
-
|
|
27
|
-
-
|
|
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
|
|
37
|
-
- Drop
|
|
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
|
|
40
|
-
- Add
|
|
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
|
|
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
|
|
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
|
|
130
|
-
- **Enemy** GameObject → Add
|
|
131
|
-
- **UIOverlay** GameObject → Add
|
|
132
|
-
- **Boot** GameObject → Add
|
|
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
|
|
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
|
|
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:
|
|
206
|
-
- Patterns and recipes:
|
|
207
|
-
- Explore another sample:
|
|
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.
|
package/SourceGenerators/WallstopStudios.DxMessaging.SourceGenerators/DxAutoConstructorGenerator.cs
CHANGED
|
@@ -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
|
package/SourceGenerators/WallstopStudios.DxMessaging.SourceGenerators/DxMessageIdGenerator.cs
CHANGED
|
@@ -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
|
-
|
|
54
|
+
DiagnosticsTarget originalDiagnostics = IMessageBus.GlobalDiagnosticsTargets;
|
|
55
55
|
int originalBufferSize = IMessageBus.GlobalMessageBufferSize;
|
|
56
56
|
try
|
|
57
57
|
{
|
|
58
|
-
IMessageBus.
|
|
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.
|
|
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
|
package/package.json
CHANGED
|
@@ -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>
|