com.wallstop-studios.dxmessaging 2.0.0-rc16 → 2.0.0-rc18
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/Editor/Analyzers/System.Runtime.CompilerServices.Unsafe.dll +0 -0
- package/Editor/Analyzers/System.Runtime.CompilerServices.Unsafe.dll.meta +33 -0
- package/Editor/Analyzers/WallstopStudios.DxMessaging.SourceGenerators.dll +0 -0
- package/Editor/Analyzers/WallstopStudios.DxMessaging.SourceGenerators.pdb.meta +7 -0
- package/Editor/SetupCscRsp.cs +37 -12
- package/README.md +8 -21
- package/Runtime/Core/Attributes/DxBroadcastMessageAttribute.cs +5 -1
- package/Runtime/Core/Attributes/DxTargetedMessageAttribute.cs +5 -1
- package/Runtime/Core/Attributes/DxUntargetedMessageAttribute.cs +5 -1
- package/Runtime/Core/IMessage.cs +13 -0
- package/Runtime/Core/InstanceId.cs +6 -16
- package/Runtime/Core/MessageBus/MessageBus.cs +1751 -828
- package/Runtime/Core/MessageHandler.cs +408 -292
- package/SourceGenerators/WallstopStudios.DxMessaging.SourceGenerators/DxMessageIdGenerator.cs +445 -0
- package/SourceGenerators/WallstopStudios.DxMessaging.SourceGenerators/DxMessageIdGenerator.cs.meta +3 -0
- package/Tests/Runtime/Benchmarks/PerformanceTests.cs +41 -26
- package/Tests/Runtime/Core/EnablementTests.cs +69 -0
- package/Tests/Runtime/Core/EnablementTests.cs.meta +3 -0
- package/Tests/Runtime/Scripts/Components/GenericMessageAwareComponent.cs +19 -0
- package/Tests/Runtime/Scripts/Components/GenericMessageAwareComponent.cs.meta +3 -0
- package/Tests/Runtime/Scripts/Messages/GenericUntargetedMessage.cs +7 -0
- package/Tests/Runtime/Scripts/Messages/GenericUntargetedMessage.cs.meta +3 -0
- package/package.json +2 -4
- package/Runtime/Core/Attributes/DxAutoMessageTypeAttribute.cs +0 -7
- package/Runtime/Core/Attributes/DxAutoMessageTypeAttribute.cs.meta +0 -3
- package/SourceGenerators/WallstopStudios.DxMessaging.SourceGenerators/DxAutoMessageTypeGenerator.cs +0 -92
- package/SourceGenerators/WallstopStudios.DxMessaging.SourceGenerators/DxAutoMessageTypeGenerator.cs.meta +0 -11
- package/SourceGenerators/WallstopStudios.DxMessaging.SourceGenerators/DxBroadcastMessageGenerator.cs +0 -94
- package/SourceGenerators/WallstopStudios.DxMessaging.SourceGenerators/DxBroadcastMessageGenerator.cs.meta +0 -3
- package/SourceGenerators/WallstopStudios.DxMessaging.SourceGenerators/DxTargetedMessageGenerator.cs +0 -94
- package/SourceGenerators/WallstopStudios.DxMessaging.SourceGenerators/DxTargetedMessageGenerator.cs.meta +0 -3
- package/SourceGenerators/WallstopStudios.DxMessaging.SourceGenerators/DxUntargetedMessageGenerator.cs +0 -94
- package/SourceGenerators/WallstopStudios.DxMessaging.SourceGenerators/DxUntargetedMessageGenerator.cs.meta +0 -3
|
Binary file
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
fileFormatVersion: 2
|
|
2
|
+
guid: 8c1cadaf86b083c49aac429e53fa3008
|
|
3
|
+
PluginImporter:
|
|
4
|
+
externalObjects: {}
|
|
5
|
+
serializedVersion: 2
|
|
6
|
+
iconMap: {}
|
|
7
|
+
executionOrder: {}
|
|
8
|
+
defineConstraints: []
|
|
9
|
+
isPreloaded: 0
|
|
10
|
+
isOverridable: 1
|
|
11
|
+
isExplicitlyReferenced: 0
|
|
12
|
+
validateReferences: 1
|
|
13
|
+
platformData:
|
|
14
|
+
- first:
|
|
15
|
+
Any:
|
|
16
|
+
second:
|
|
17
|
+
enabled: 0
|
|
18
|
+
settings: {}
|
|
19
|
+
- first:
|
|
20
|
+
Editor: Editor
|
|
21
|
+
second:
|
|
22
|
+
enabled: 1
|
|
23
|
+
settings:
|
|
24
|
+
DefaultValueInitialized: true
|
|
25
|
+
- first:
|
|
26
|
+
Windows Store Apps: WindowsStoreApps
|
|
27
|
+
second:
|
|
28
|
+
enabled: 0
|
|
29
|
+
settings:
|
|
30
|
+
CPU: AnyCPU
|
|
31
|
+
userData:
|
|
32
|
+
assetBundleName:
|
|
33
|
+
assetBundleVariant:
|
|
Binary file
|
package/Editor/SetupCscRsp.cs
CHANGED
|
@@ -35,10 +35,13 @@ namespace DxMessaging.Editor
|
|
|
35
35
|
"Microsoft.CodeAnalysis.dll",
|
|
36
36
|
"Microsoft.CodeAnalysis.CSharp.dll",
|
|
37
37
|
"System.Reflection.Metadata.dll",
|
|
38
|
+
"System.Runtime.CompilerServices.Unsafe.dll",
|
|
38
39
|
};
|
|
39
40
|
|
|
40
41
|
private static readonly string LibraryArgument = $"-a:\"{LibraryPathRelative}\"";
|
|
41
42
|
|
|
43
|
+
private static readonly HashSet<string> DllNames = new(StringComparer.OrdinalIgnoreCase);
|
|
44
|
+
|
|
42
45
|
static SetupCscRsp()
|
|
43
46
|
{
|
|
44
47
|
EditorApplication.delayCall += EnsureDLLsExistInAssets;
|
|
@@ -47,19 +50,27 @@ namespace DxMessaging.Editor
|
|
|
47
50
|
|
|
48
51
|
private static void EnsureDLLsExistInAssets()
|
|
49
52
|
{
|
|
50
|
-
|
|
53
|
+
DllNames.Clear();
|
|
51
54
|
foreach (
|
|
52
55
|
string dllGuid in AssetDatabase.FindAssets("t:DefaultAsset", new[] { "Assets" })
|
|
53
56
|
)
|
|
54
57
|
{
|
|
55
58
|
string dllPath = AssetDatabase.GUIDToAssetPath(dllGuid);
|
|
56
|
-
if (!dllPath.EndsWith(".dll"))
|
|
59
|
+
if (!dllPath.EndsWith(".dll", StringComparison.OrdinalIgnoreCase))
|
|
57
60
|
{
|
|
58
61
|
continue;
|
|
59
62
|
}
|
|
60
63
|
|
|
61
|
-
|
|
62
|
-
|
|
64
|
+
if (
|
|
65
|
+
!dllPath.Contains(
|
|
66
|
+
"Assets/Plugins/WallstopStudios.DxMessaging",
|
|
67
|
+
StringComparison.OrdinalIgnoreCase
|
|
68
|
+
)
|
|
69
|
+
)
|
|
70
|
+
{
|
|
71
|
+
string dllName = Path.GetFileName(dllPath);
|
|
72
|
+
DllNames.Add(dllName);
|
|
73
|
+
}
|
|
63
74
|
}
|
|
64
75
|
|
|
65
76
|
string[] dllRelativeDirectories = { LibraryPathRelative, AnalyzerPathRelative };
|
|
@@ -67,7 +78,7 @@ namespace DxMessaging.Editor
|
|
|
67
78
|
bool anyFound = false;
|
|
68
79
|
foreach (
|
|
69
80
|
string requiredDllName in RequiredDllNames.Where(dllName =>
|
|
70
|
-
!
|
|
81
|
+
!DllNames.Contains(dllName)
|
|
71
82
|
)
|
|
72
83
|
)
|
|
73
84
|
{
|
|
@@ -85,13 +96,31 @@ namespace DxMessaging.Editor
|
|
|
85
96
|
const string pluginsDirectory =
|
|
86
97
|
"Assets/Plugins/WallstopStudios.DxMessaging/";
|
|
87
98
|
string outputAsset = $"{pluginsDirectory}{requiredDllName}";
|
|
99
|
+
string sourceAsset = $"{relativeDirectory}{requiredDllName}";
|
|
88
100
|
Directory.CreateDirectory(pluginsDirectory);
|
|
89
101
|
if (!File.Exists(outputAsset))
|
|
90
102
|
{
|
|
91
|
-
File.Copy(
|
|
103
|
+
File.Copy(sourceAsset, outputAsset);
|
|
92
104
|
AssetDatabase.ImportAsset(outputAsset);
|
|
93
105
|
found = true;
|
|
94
106
|
}
|
|
107
|
+
else
|
|
108
|
+
{
|
|
109
|
+
FileInfo sourceInfo = new(sourceAsset);
|
|
110
|
+
FileInfo destInfo = new(outputAsset);
|
|
111
|
+
|
|
112
|
+
if (destInfo.LastWriteTime < sourceInfo.LastWriteTime)
|
|
113
|
+
{
|
|
114
|
+
// Source file is newer, so copy the file (overwrite destination)
|
|
115
|
+
File.Copy(sourceAsset, outputAsset, true);
|
|
116
|
+
AssetDatabase.ImportAsset(outputAsset);
|
|
117
|
+
found = true;
|
|
118
|
+
}
|
|
119
|
+
else
|
|
120
|
+
{
|
|
121
|
+
continue;
|
|
122
|
+
}
|
|
123
|
+
}
|
|
95
124
|
|
|
96
125
|
if (requiredDllName == SourceGeneratorDllName)
|
|
97
126
|
{
|
|
@@ -120,10 +149,6 @@ namespace DxMessaging.Editor
|
|
|
120
149
|
}
|
|
121
150
|
|
|
122
151
|
anyFound |= found;
|
|
123
|
-
Debug.Log(
|
|
124
|
-
$"Missing required dll '{requiredDllName}', "
|
|
125
|
-
+ $"{(found ? "creation successful." : "WARNING! Manual creation required.")}"
|
|
126
|
-
);
|
|
127
152
|
}
|
|
128
153
|
|
|
129
154
|
if (anyFound)
|
|
@@ -143,12 +168,12 @@ namespace DxMessaging.Editor
|
|
|
143
168
|
}
|
|
144
169
|
|
|
145
170
|
string rspContent = File.ReadAllText(RspFilePath);
|
|
146
|
-
if (rspContent.Contains(LibraryArgument))
|
|
171
|
+
if (rspContent.Contains(LibraryArgument, StringComparison.OrdinalIgnoreCase))
|
|
147
172
|
{
|
|
148
173
|
return;
|
|
149
174
|
}
|
|
150
175
|
|
|
151
|
-
File.AppendAllText(RspFilePath, $"{LibraryArgument}
|
|
176
|
+
File.AppendAllText(RspFilePath, $"{LibraryArgument}{Environment.NewLine}");
|
|
152
177
|
AssetDatabase.ImportAsset("csc.rsp");
|
|
153
178
|
Debug.Log("Updated csc.rsp.");
|
|
154
179
|
}
|
package/README.md
CHANGED
|
@@ -26,26 +26,23 @@ Check out the latest [Releases](https://github.com/wallstop/DxMessaging/releases
|
|
|
26
26
|
4. Add an entry for a new "Scoped Registry"
|
|
27
27
|
- Name: `NPM`
|
|
28
28
|
- URL: `https://registry.npmjs.org`
|
|
29
|
-
- Scope(s): `com.wallstop-studios.dxmessaging`
|
|
29
|
+
- Scope(s): `com.wallstop-studios.dxmessaging`
|
|
30
30
|
5. Resolve the latest `DxMessaging`
|
|
31
31
|
|
|
32
32
|
## From Source
|
|
33
33
|
Grab a copy of this repo (either `git clone` both [this repo](https://github.com/wallstop/DxMessaging) *and* [Unity Helpers](https://github.com/wallstop/unity-helpers) or [download a zip of the source](https://github.com/wallstop/DxMessaging/archive/refs/heads/master.zip) and [Unity Helper's source](https://github.com/wallstop/unity-helpers/archive/refs/heads/main.zip)) and copy the contents to your project's `Assets` folder.
|
|
34
34
|
|
|
35
|
-
# Dependencies
|
|
36
|
-
This project has a dependency on my [`Unity Helpers`](https://github.com/wallstop/unity-helpers) project, which contains the `System.Runtime.CompilerServices.Unsafe.dll`, which is used for some speed hacks in DxMessaging directly. Unity Helpers bundles a few (small) dependencies, including protobuf. If you don't want these dependencies, or if they conflict in some way, you can either include a copy of the `System.Runtime.CompilerServices.Unsafe.dll` yourself without relying on UnityHelpers, or manually download and include the Unity Helpers project and delete anything that conflicts with your project. Or, manually download this project without UnityHelpers. The choice is yours.
|
|
37
|
-
|
|
38
35
|
# Benchmarks
|
|
39
|
-
DxMessaging is currently
|
|
36
|
+
DxMessaging is currently roughly on-par with than Unity's built in messaging solution (when running in Unity). [Source](./Tests/Runtime/Benchmarks/PerformanceTests.cs). However, it is allocation-free and can be used in hot paths.
|
|
40
37
|
|
|
41
38
|
| Message Tech | Operations / Second | Allocations? |
|
|
42
39
|
| ------------ | ------------------- | ------------ |
|
|
43
|
-
| Unity | 2,
|
|
44
|
-
| DxMessaging (GameObject) - Normal |
|
|
45
|
-
| DxMessaging (Component) - Normal |
|
|
46
|
-
| DxMessaging (GameObject) - No-Copy |
|
|
47
|
-
| DxMessaging (Component) - No-Copy |
|
|
48
|
-
| DxMessaging (Untargeted) - No-Copy |
|
|
40
|
+
| Unity | 2,621,200 | Yes |
|
|
41
|
+
| DxMessaging (GameObject) - Normal | 2,048,600 | No |
|
|
42
|
+
| DxMessaging (Component) - Normal | 2,054,600 | No |
|
|
43
|
+
| DxMessaging (GameObject) - No-Copy | 2,137,800 | No |
|
|
44
|
+
| DxMessaging (Component) - No-Copy | 2,136,400 | No |
|
|
45
|
+
| DxMessaging (Untargeted) - No-Copy | 3,028,400 | No |
|
|
49
46
|
|
|
50
47
|
# Functionality
|
|
51
48
|
While not as fast, DxMessaging offers *additional functionality* as compared to Unity's messaging solution.
|
|
@@ -121,16 +118,6 @@ public partial struct SimpleUntargetedMessage // No longer needed : IUntargetedM
|
|
|
121
118
|
}
|
|
122
119
|
```
|
|
123
120
|
|
|
124
|
-
Or, if you already have messages, you can leave the interface implementations as-is and get a no-boxing implementation with the `DxAutoMessageType` attribute. `partial` is still required.
|
|
125
|
-
|
|
126
|
-
To use:
|
|
127
|
-
```csharp
|
|
128
|
-
[DxAutoMessageType]
|
|
129
|
-
public partial struct SimpleTargetedMessage : ITargetedMessage<SimpleTargetedMessage>
|
|
130
|
-
{
|
|
131
|
-
}
|
|
132
|
-
```
|
|
133
|
-
|
|
134
121
|
## Integration
|
|
135
122
|
See the [tests](./Tests/Runtime/Scripts/) directory for examples about how to integrate with the MessageAwareComponent. But, for some starters:
|
|
136
123
|
```csharp
|
|
@@ -2,6 +2,10 @@
|
|
|
2
2
|
{
|
|
3
3
|
using System;
|
|
4
4
|
|
|
5
|
-
[AttributeUsage(
|
|
5
|
+
[AttributeUsage(
|
|
6
|
+
AttributeTargets.Class | AttributeTargets.Struct,
|
|
7
|
+
Inherited = false,
|
|
8
|
+
AllowMultiple = false
|
|
9
|
+
)]
|
|
6
10
|
public sealed class DxBroadcastMessageAttribute : Attribute { }
|
|
7
11
|
}
|
|
@@ -2,6 +2,10 @@
|
|
|
2
2
|
{
|
|
3
3
|
using System;
|
|
4
4
|
|
|
5
|
-
[AttributeUsage(
|
|
5
|
+
[AttributeUsage(
|
|
6
|
+
AttributeTargets.Class | AttributeTargets.Struct,
|
|
7
|
+
Inherited = false,
|
|
8
|
+
AllowMultiple = false
|
|
9
|
+
)]
|
|
6
10
|
public sealed class DxTargetedMessageAttribute : Attribute { }
|
|
7
11
|
}
|
|
@@ -2,6 +2,10 @@
|
|
|
2
2
|
{
|
|
3
3
|
using System;
|
|
4
4
|
|
|
5
|
-
[AttributeUsage(
|
|
5
|
+
[AttributeUsage(
|
|
6
|
+
AttributeTargets.Class | AttributeTargets.Struct,
|
|
7
|
+
Inherited = false,
|
|
8
|
+
AllowMultiple = false
|
|
9
|
+
)]
|
|
6
10
|
public sealed class DxUntargetedMessageAttribute : Attribute { }
|
|
7
11
|
}
|
package/Runtime/Core/IMessage.cs
CHANGED
|
@@ -8,5 +8,18 @@
|
|
|
8
8
|
public interface IMessage
|
|
9
9
|
{
|
|
10
10
|
Type MessageType => GetType();
|
|
11
|
+
|
|
12
|
+
/// <summary>
|
|
13
|
+
/// Gets the optimized, unique integer ID for this message type, if available.
|
|
14
|
+
/// Returns null if this type uses the fallback mechanism (e.g., due to a compile-time
|
|
15
|
+
/// hash collision or manual implementation without an assigned ID).
|
|
16
|
+
/// </summary>
|
|
17
|
+
/// <remarks>
|
|
18
|
+
/// The ID is generated at compile-time for attributed types and is stable
|
|
19
|
+
/// across builds assuming the type's fully qualified name does not change.
|
|
20
|
+
/// It facilitates faster dictionary lookups compared to using System.Type directly.
|
|
21
|
+
/// Check for HasValue before using the Value.
|
|
22
|
+
/// </remarks>
|
|
23
|
+
int? OptimizedMessageId => null;
|
|
11
24
|
}
|
|
12
25
|
}
|
|
@@ -46,22 +46,12 @@
|
|
|
46
46
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
47
47
|
public static implicit operator InstanceId(UnityEngine.GameObject gameObject)
|
|
48
48
|
{
|
|
49
|
-
if (gameObject == null)
|
|
50
|
-
{
|
|
51
|
-
throw new ArgumentNullException(nameof(gameObject));
|
|
52
|
-
}
|
|
53
|
-
|
|
54
49
|
return new InstanceId(gameObject);
|
|
55
50
|
}
|
|
56
51
|
|
|
57
52
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
58
53
|
public static implicit operator InstanceId(UnityEngine.Component component)
|
|
59
54
|
{
|
|
60
|
-
if (component == null)
|
|
61
|
-
{
|
|
62
|
-
throw new ArgumentNullException(nameof(component));
|
|
63
|
-
}
|
|
64
|
-
|
|
65
55
|
return new InstanceId(component);
|
|
66
56
|
}
|
|
67
57
|
#endif
|
|
@@ -98,37 +88,37 @@
|
|
|
98
88
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
99
89
|
public static bool operator ==(InstanceId lhs, InstanceId rhs)
|
|
100
90
|
{
|
|
101
|
-
return lhs.
|
|
91
|
+
return lhs._id == rhs._id;
|
|
102
92
|
}
|
|
103
93
|
|
|
104
94
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
105
95
|
public static bool operator !=(InstanceId lhs, InstanceId rhs)
|
|
106
96
|
{
|
|
107
|
-
return
|
|
97
|
+
return lhs._id != rhs._id;
|
|
108
98
|
}
|
|
109
99
|
|
|
110
100
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
111
101
|
public static bool operator <(InstanceId lhs, InstanceId rhs)
|
|
112
102
|
{
|
|
113
|
-
return lhs.CompareTo(rhs) < 0;
|
|
103
|
+
return lhs._id.CompareTo(rhs._id) < 0;
|
|
114
104
|
}
|
|
115
105
|
|
|
116
106
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
117
107
|
public static bool operator <=(InstanceId lhs, InstanceId rhs)
|
|
118
108
|
{
|
|
119
|
-
return lhs.CompareTo(rhs) <= 0;
|
|
109
|
+
return lhs._id.CompareTo(rhs._id) <= 0;
|
|
120
110
|
}
|
|
121
111
|
|
|
122
112
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
123
113
|
public static bool operator >(InstanceId lhs, InstanceId rhs)
|
|
124
114
|
{
|
|
125
|
-
return lhs.CompareTo(rhs) > 0;
|
|
115
|
+
return lhs._id.CompareTo(rhs._id) > 0;
|
|
126
116
|
}
|
|
127
117
|
|
|
128
118
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
129
119
|
public static bool operator >=(InstanceId lhs, InstanceId rhs)
|
|
130
120
|
{
|
|
131
|
-
return lhs.CompareTo(rhs) >= 0;
|
|
121
|
+
return lhs._id.CompareTo(rhs._id) >= 0;
|
|
132
122
|
}
|
|
133
123
|
|
|
134
124
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|