com.wallstop-studios.dxmessaging 2.0.0-rc26 → 2.0.0-rc26.2
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/.config/dotnet-tools.json +2 -2
- package/.pre-commit-config.yaml +1 -1
- package/Editor/CustomEditors/MessagingComponentEditor.cs +470 -0
- package/Editor/CustomEditors/MessagingComponentEditor.cs.meta +3 -0
- package/Editor/CustomEditors.meta +3 -0
- package/Editor/DxMessagingEditorInitializer.cs +19 -0
- package/Editor/DxMessagingEditorInitializer.cs.meta +3 -0
- package/Editor/Settings/DxMessagingSettings.cs +68 -0
- package/Editor/Settings/DxMessagingSettings.cs.meta +3 -0
- package/Editor/Settings/DxMessagingSettingsProvider.cs +55 -0
- package/Editor/Settings/DxMessagingSettingsProvider.cs.meta +3 -0
- package/Editor/Settings.meta +3 -0
- package/Editor/SetupCscRsp.cs +7 -8
- package/README.md +16 -0
- package/Runtime/Core/DataStructure/CyclicBuffer.cs +265 -0
- package/Runtime/Core/DataStructure/CyclicBuffer.cs.meta +3 -0
- package/Runtime/Core/DataStructure.meta +3 -0
- package/Runtime/Core/Diagnostics/MessageEmissionData.cs +53 -0
- package/Runtime/Core/Diagnostics/MessageEmissionData.cs.meta +3 -0
- package/Runtime/Core/Diagnostics/MessageRegistrationData.cs +25 -0
- package/Runtime/Core/Diagnostics/MessageRegistrationData.cs.meta +3 -0
- package/Runtime/Core/Diagnostics/MessageRegistrationType.cs +21 -0
- package/Runtime/Core/Diagnostics/MessageRegistrationType.cs.meta +3 -0
- package/Runtime/Core/Diagnostics.meta +3 -0
- package/Runtime/Core/Extensions/IListExtensions.cs +48 -0
- package/Runtime/Core/Extensions/IListExtensions.cs.meta +3 -0
- package/Runtime/Core/Extensions/MessageExtensions.cs +66 -0
- package/Runtime/Core/MessageBus/IMessageBus.cs +5 -3
- package/Runtime/Core/MessageBus/MessageBus.cs +28 -0
- package/Runtime/Core/MessageHandler.cs +200 -40
- package/Runtime/Core/MessageRegistrationToken.cs +645 -57
- package/Runtime/{Unity → Core}/Messages/GlobalStringMessage.cs +1 -2
- package/Runtime/Core/Messages/ReflexiveMessage.cs +20 -1
- package/Runtime/{Unity → Core}/Messages/StringMessage.cs +1 -2
- package/Runtime/Unity/MessageAwareComponent.cs +1 -1
- package/Runtime/Unity/MessagingComponent.cs +1 -1
- package/SourceGenerators/WallstopStudios.DxMessaging.SourceGenerators/WallstopStudios.DxMessaging.SourceGenerators.csproj +10 -13
- package/Tests/Runtime/Benchmarks/PerformanceTests.cs +0 -91
- package/Tests/Runtime/Core/NominalTests.cs +2 -8
- package/Tests/Runtime/WallstopStudios.DxMessaging.Tests.Runtime.csproj +7 -1
- package/package.json +3 -1
- package/Runtime/Unity/Messages.meta +0 -3
- /package/Runtime/{Unity → Core}/Messages/GlobalStringMessage.cs.meta +0 -0
- /package/Runtime/{Unity → Core}/Messages/StringMessage.cs.meta +0 -0
package/Editor/SetupCscRsp.cs
CHANGED
|
@@ -62,12 +62,7 @@ namespace DxMessaging.Editor
|
|
|
62
62
|
continue;
|
|
63
63
|
}
|
|
64
64
|
|
|
65
|
-
if (
|
|
66
|
-
!dllPath.Contains(
|
|
67
|
-
"Assets/Plugins/WallstopStudios.DxMessaging",
|
|
68
|
-
StringComparison.OrdinalIgnoreCase
|
|
69
|
-
)
|
|
70
|
-
)
|
|
65
|
+
if (!dllPath.Contains("Assets/Plugins", StringComparison.OrdinalIgnoreCase))
|
|
71
66
|
{
|
|
72
67
|
string dllName = Path.GetFileName(dllPath);
|
|
73
68
|
DllNames.Add(dllName);
|
|
@@ -95,10 +90,14 @@ namespace DxMessaging.Editor
|
|
|
95
90
|
}
|
|
96
91
|
|
|
97
92
|
const string pluginsDirectory =
|
|
98
|
-
"Assets/Plugins/WallstopStudios.DxMessaging/";
|
|
93
|
+
"Assets/Plugins/Editor/WallstopStudios.DxMessaging/";
|
|
99
94
|
string outputAsset = $"{pluginsDirectory}{requiredDllName}";
|
|
100
95
|
string sourceAsset = $"{relativeDirectory}{requiredDllName}";
|
|
101
|
-
Directory.
|
|
96
|
+
if (!Directory.Exists(pluginsDirectory))
|
|
97
|
+
{
|
|
98
|
+
Directory.CreateDirectory(pluginsDirectory);
|
|
99
|
+
AssetDatabase.Refresh();
|
|
100
|
+
}
|
|
102
101
|
if (!File.Exists(outputAsset))
|
|
103
102
|
{
|
|
104
103
|
File.Copy(sourceAsset, outputAsset);
|
package/README.md
CHANGED
|
@@ -37,6 +37,8 @@ In addition to providing a richer feature set, DxMessaging is *faster* than Unit
|
|
|
37
37
|
|
|
38
38
|
For UntargetedMessages, DxMessaging is significantly faster (roughly 2x) than Unity.
|
|
39
39
|
|
|
40
|
+
## Windows
|
|
41
|
+
|
|
40
42
|
| Message Tech | Operations / Second | Allocations? |
|
|
41
43
|
| ------------ | ------------------- | ------------ |
|
|
42
44
|
| Unity | 2,649,000 | Yes |
|
|
@@ -49,6 +51,20 @@ For UntargetedMessages, DxMessaging is significantly faster (roughly 2x) than Un
|
|
|
49
51
|
| Reflexive (Two Arguments) | 1,000,400 | No |
|
|
50
52
|
| Reflexive (Three Arguments) | 993,800 | No |
|
|
51
53
|
|
|
54
|
+
## Linux
|
|
55
|
+
|
|
56
|
+
Message Tech | Operations / Second | Allocations? |
|
|
57
|
+
| ------------ | ------------------- | ------------ |
|
|
58
|
+
| Unity | 1,538,000 | Yes |
|
|
59
|
+
| DxMessaging (GameObject) - Normal | 5,653,200 | No |
|
|
60
|
+
| DxMessaging (Component) - Normal | 4,998,800 | No |
|
|
61
|
+
| DxMessaging (GameObject) - No-Copy | 6,388,800 | No |
|
|
62
|
+
| DxMessaging (Component) - No-Copy | 6,332,800 | No |
|
|
63
|
+
| DxMessaging (Untargeted) - No-Copy | 9,805,200 | No |
|
|
64
|
+
| Reflexive (One Argument) | 1,692,600 | No |
|
|
65
|
+
| Reflexive (Two Arguments) | 1,348,000 | No |
|
|
66
|
+
| Reflexive (Three Arguments) | 1,368,000 | No |
|
|
67
|
+
|
|
52
68
|
# Functionality
|
|
53
69
|
While not as fast, DxMessaging offers *additional functionality* as compared to Unity's messaging solution.
|
|
54
70
|
| Feature | Unity | DxMessaging |
|
|
@@ -0,0 +1,265 @@
|
|
|
1
|
+
namespace DxMessaging.Core.DataStructure
|
|
2
|
+
{
|
|
3
|
+
using System;
|
|
4
|
+
using System.Collections;
|
|
5
|
+
using System.Collections.Generic;
|
|
6
|
+
using Extensions;
|
|
7
|
+
|
|
8
|
+
[Serializable]
|
|
9
|
+
internal sealed class CyclicBuffer<T> : IReadOnlyList<T>
|
|
10
|
+
{
|
|
11
|
+
public struct CyclicBufferEnumerator : IEnumerator<T>
|
|
12
|
+
{
|
|
13
|
+
private readonly CyclicBuffer<T> _buffer;
|
|
14
|
+
|
|
15
|
+
private int _index;
|
|
16
|
+
private T _current;
|
|
17
|
+
|
|
18
|
+
internal CyclicBufferEnumerator(CyclicBuffer<T> buffer)
|
|
19
|
+
{
|
|
20
|
+
_buffer = buffer;
|
|
21
|
+
_index = -1;
|
|
22
|
+
_current = default;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
public bool MoveNext()
|
|
26
|
+
{
|
|
27
|
+
if (++_index < _buffer.Count)
|
|
28
|
+
{
|
|
29
|
+
_current = _buffer._buffer[_buffer.AdjustedIndexFor(_index)];
|
|
30
|
+
return true;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
_current = default;
|
|
34
|
+
return false;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
public T Current => _current;
|
|
38
|
+
|
|
39
|
+
object IEnumerator.Current => Current;
|
|
40
|
+
|
|
41
|
+
public void Reset()
|
|
42
|
+
{
|
|
43
|
+
_index = -1;
|
|
44
|
+
_current = default;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
public void Dispose() { }
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
public int Capacity { get; private set; }
|
|
51
|
+
public int Count { get; private set; }
|
|
52
|
+
|
|
53
|
+
private readonly List<T> _buffer;
|
|
54
|
+
private int _position;
|
|
55
|
+
|
|
56
|
+
public T this[int index]
|
|
57
|
+
{
|
|
58
|
+
get
|
|
59
|
+
{
|
|
60
|
+
BoundsCheck(index);
|
|
61
|
+
return _buffer[AdjustedIndexFor(index)];
|
|
62
|
+
}
|
|
63
|
+
set
|
|
64
|
+
{
|
|
65
|
+
BoundsCheck(index);
|
|
66
|
+
_buffer[AdjustedIndexFor(index)] = value;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
public CyclicBuffer(int capacity, IEnumerable<T> initialContents = null)
|
|
71
|
+
{
|
|
72
|
+
if (capacity < 0)
|
|
73
|
+
{
|
|
74
|
+
throw new ArgumentException(nameof(capacity));
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
Capacity = capacity;
|
|
78
|
+
_position = 0;
|
|
79
|
+
Count = 0;
|
|
80
|
+
_buffer = new List<T>();
|
|
81
|
+
if (initialContents != null)
|
|
82
|
+
{
|
|
83
|
+
foreach (T item in initialContents)
|
|
84
|
+
{
|
|
85
|
+
Add(item);
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
public CyclicBufferEnumerator GetEnumerator()
|
|
91
|
+
{
|
|
92
|
+
return new CyclicBufferEnumerator(this);
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
IEnumerator<T> IEnumerable<T>.GetEnumerator()
|
|
96
|
+
{
|
|
97
|
+
return GetEnumerator();
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
IEnumerator IEnumerable.GetEnumerator()
|
|
101
|
+
{
|
|
102
|
+
return GetEnumerator();
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
public void Add(T item)
|
|
106
|
+
{
|
|
107
|
+
if (Capacity == 0)
|
|
108
|
+
{
|
|
109
|
+
return;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
if (_position < _buffer.Count)
|
|
113
|
+
{
|
|
114
|
+
_buffer[_position] = item;
|
|
115
|
+
}
|
|
116
|
+
else
|
|
117
|
+
{
|
|
118
|
+
_buffer.Add(item);
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
_position = (_position + 1) % Capacity;
|
|
122
|
+
if (Count < Capacity)
|
|
123
|
+
{
|
|
124
|
+
++Count;
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
public bool Remove(T element, IEqualityComparer<T> comparer = null)
|
|
129
|
+
{
|
|
130
|
+
if (Count == 0)
|
|
131
|
+
{
|
|
132
|
+
return false;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
int write = 0;
|
|
136
|
+
bool removed = false;
|
|
137
|
+
comparer ??= EqualityComparer<T>.Default;
|
|
138
|
+
for (int i = 0; i < Count; ++i)
|
|
139
|
+
{
|
|
140
|
+
int readIdx = AdjustedIndexFor(i);
|
|
141
|
+
T item = _buffer[readIdx];
|
|
142
|
+
|
|
143
|
+
if (!removed && comparer.Equals(item, element))
|
|
144
|
+
{
|
|
145
|
+
removed = true;
|
|
146
|
+
continue;
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
_buffer[write++] = item;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
if (!removed)
|
|
153
|
+
{
|
|
154
|
+
return false;
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
_buffer.RemoveRange(write, _buffer.Count - write);
|
|
158
|
+
|
|
159
|
+
Count--;
|
|
160
|
+
_position = Count < Capacity ? Count : 0;
|
|
161
|
+
return true;
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
public int RemoveAll(Func<T, bool> predicate)
|
|
165
|
+
{
|
|
166
|
+
if (Count == 0)
|
|
167
|
+
{
|
|
168
|
+
return 0;
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
int write = 0;
|
|
172
|
+
int removedCount = 0;
|
|
173
|
+
|
|
174
|
+
for (int i = 0; i < Count; ++i)
|
|
175
|
+
{
|
|
176
|
+
int readIdx = AdjustedIndexFor(i);
|
|
177
|
+
T item = _buffer[readIdx];
|
|
178
|
+
if (predicate(item))
|
|
179
|
+
{
|
|
180
|
+
removedCount++;
|
|
181
|
+
}
|
|
182
|
+
else
|
|
183
|
+
{
|
|
184
|
+
_buffer[write++] = item;
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
if (removedCount == 0)
|
|
189
|
+
{
|
|
190
|
+
return 0;
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
_buffer.RemoveRange(write, _buffer.Count - write);
|
|
194
|
+
Count -= removedCount;
|
|
195
|
+
_position = Count < Capacity ? Count : 0;
|
|
196
|
+
return removedCount;
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
public void Clear()
|
|
200
|
+
{
|
|
201
|
+
Count = 0;
|
|
202
|
+
_position = 0;
|
|
203
|
+
_buffer.Clear();
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
public void Resize(int newCapacity)
|
|
207
|
+
{
|
|
208
|
+
if (newCapacity == Capacity)
|
|
209
|
+
{
|
|
210
|
+
return;
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
if (newCapacity < 0)
|
|
214
|
+
{
|
|
215
|
+
throw new ArgumentException(nameof(newCapacity));
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
int oldCapacity = Capacity;
|
|
219
|
+
Capacity = newCapacity;
|
|
220
|
+
_buffer.Shift(-_position);
|
|
221
|
+
if (newCapacity < _buffer.Count)
|
|
222
|
+
{
|
|
223
|
+
_buffer.RemoveRange(newCapacity, _buffer.Count - newCapacity);
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
_position =
|
|
227
|
+
newCapacity < oldCapacity && newCapacity <= _buffer.Count ? 0 : _buffer.Count;
|
|
228
|
+
Count = Math.Min(newCapacity, Count);
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
public bool Contains(T item)
|
|
232
|
+
{
|
|
233
|
+
return _buffer.Contains(item);
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
private int AdjustedIndexFor(int index)
|
|
237
|
+
{
|
|
238
|
+
long longCapacity = Capacity;
|
|
239
|
+
if (longCapacity == 0L)
|
|
240
|
+
{
|
|
241
|
+
return 0;
|
|
242
|
+
}
|
|
243
|
+
unchecked
|
|
244
|
+
{
|
|
245
|
+
int adjustedIndex = (int)(
|
|
246
|
+
(_position - 1L + longCapacity - (_buffer.Count - 1 - index)) % longCapacity
|
|
247
|
+
);
|
|
248
|
+
return adjustedIndex;
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
private void BoundsCheck(int index)
|
|
253
|
+
{
|
|
254
|
+
if (!InBounds(index))
|
|
255
|
+
{
|
|
256
|
+
throw new IndexOutOfRangeException($"{index} is outside of bounds [0, {Count})");
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
private bool InBounds(int index)
|
|
261
|
+
{
|
|
262
|
+
return 0 <= index && index < Count;
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
namespace DxMessaging.Core.Diagnostics
|
|
2
|
+
{
|
|
3
|
+
using System;
|
|
4
|
+
#if UNITY_2017_1_OR_NEWER
|
|
5
|
+
using UnityEngine;
|
|
6
|
+
#endif
|
|
7
|
+
|
|
8
|
+
public readonly struct MessageEmissionData
|
|
9
|
+
{
|
|
10
|
+
private static readonly string[] NewlineSeparators = { "\r\n", "\n", "\r" };
|
|
11
|
+
private static readonly string JoinSeparator = Environment.NewLine;
|
|
12
|
+
|
|
13
|
+
public readonly IMessage message;
|
|
14
|
+
public readonly InstanceId? context;
|
|
15
|
+
public readonly string stackTrace;
|
|
16
|
+
|
|
17
|
+
public MessageEmissionData(IMessage message, InstanceId? context = null)
|
|
18
|
+
{
|
|
19
|
+
this.message = message;
|
|
20
|
+
this.context = context;
|
|
21
|
+
stackTrace = GetAccurateStackTrace();
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
private static string GetAccurateStackTrace()
|
|
25
|
+
{
|
|
26
|
+
string fullStackTrace;
|
|
27
|
+
#if UNITY_2017_1_OR_NEWER
|
|
28
|
+
fullStackTrace = StackTraceUtility.ExtractStackTrace();
|
|
29
|
+
#else
|
|
30
|
+
fullStackTrace = new StackTrace(true).ToString();
|
|
31
|
+
#endif
|
|
32
|
+
if (string.IsNullOrWhiteSpace(fullStackTrace))
|
|
33
|
+
{
|
|
34
|
+
return fullStackTrace;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
string[] lines = fullStackTrace.Split(NewlineSeparators, StringSplitOptions.None);
|
|
38
|
+
|
|
39
|
+
int startIndex = 1;
|
|
40
|
+
while (
|
|
41
|
+
startIndex < lines.Length
|
|
42
|
+
&& lines[startIndex].Contains("DxMessaging", StringComparison.OrdinalIgnoreCase)
|
|
43
|
+
)
|
|
44
|
+
{
|
|
45
|
+
++startIndex;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
return lines.Length <= startIndex
|
|
49
|
+
? string.Empty
|
|
50
|
+
: string.Join(JoinSeparator, lines, startIndex, lines.Length - startIndex);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
namespace DxMessaging.Core.Diagnostics
|
|
2
|
+
{
|
|
3
|
+
using System;
|
|
4
|
+
|
|
5
|
+
public readonly struct MessageRegistrationMetadata
|
|
6
|
+
{
|
|
7
|
+
public readonly InstanceId? context;
|
|
8
|
+
public readonly MessageRegistrationType registrationType;
|
|
9
|
+
public readonly Type type;
|
|
10
|
+
public readonly int priority;
|
|
11
|
+
|
|
12
|
+
public MessageRegistrationMetadata(
|
|
13
|
+
InstanceId? context,
|
|
14
|
+
Type type,
|
|
15
|
+
MessageRegistrationType registrationType,
|
|
16
|
+
int priority
|
|
17
|
+
)
|
|
18
|
+
{
|
|
19
|
+
this.context = context;
|
|
20
|
+
this.type = type;
|
|
21
|
+
this.registrationType = registrationType;
|
|
22
|
+
this.priority = priority;
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
namespace DxMessaging.Core.Diagnostics
|
|
2
|
+
{
|
|
3
|
+
public enum MessageRegistrationType
|
|
4
|
+
{
|
|
5
|
+
None = 0,
|
|
6
|
+
Targeted = 1,
|
|
7
|
+
Untargeted = 2,
|
|
8
|
+
Broadcast = 3,
|
|
9
|
+
BroadcastPostProcessor = 4,
|
|
10
|
+
TargetedPostProcessor = 5,
|
|
11
|
+
TargetedWithoutTargeting = 6,
|
|
12
|
+
TargetedWithoutTargetingPostProcessor = 7,
|
|
13
|
+
BroadcastWithoutSource = 8,
|
|
14
|
+
BroadcastWithoutSourcePostProcessor = 9,
|
|
15
|
+
UntargetedPostProcessor = 10,
|
|
16
|
+
GlobalAcceptAll = 11,
|
|
17
|
+
UntargetedInterceptor = 12,
|
|
18
|
+
TargetedInterceptor = 13,
|
|
19
|
+
BroadcastInterceptor = 14,
|
|
20
|
+
}
|
|
21
|
+
}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
namespace DxMessaging.Core.Extensions
|
|
2
|
+
{
|
|
3
|
+
using System;
|
|
4
|
+
using System.Collections.Generic;
|
|
5
|
+
|
|
6
|
+
internal static class IListExtensions
|
|
7
|
+
{
|
|
8
|
+
public static void Shift<T>(this IList<T> list, int amount)
|
|
9
|
+
{
|
|
10
|
+
if (list is not { Count: > 1 })
|
|
11
|
+
{
|
|
12
|
+
return;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
int count = list.Count;
|
|
16
|
+
amount %= count;
|
|
17
|
+
amount += count;
|
|
18
|
+
amount %= count;
|
|
19
|
+
if (amount == 0)
|
|
20
|
+
{
|
|
21
|
+
return;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
Reverse(list, 0, count - 1);
|
|
25
|
+
Reverse(list, 0, amount - 1);
|
|
26
|
+
Reverse(list, amount, count - 1);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
public static void Reverse<T>(this IList<T> list, int start, int end)
|
|
30
|
+
{
|
|
31
|
+
if (start < 0 || list.Count <= start)
|
|
32
|
+
{
|
|
33
|
+
throw new ArgumentException(nameof(start));
|
|
34
|
+
}
|
|
35
|
+
if (end < 0 || list.Count <= end)
|
|
36
|
+
{
|
|
37
|
+
throw new ArgumentException(nameof(end));
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
while (start < end)
|
|
41
|
+
{
|
|
42
|
+
(list[start], list[end]) = (list[end], list[start]);
|
|
43
|
+
start++;
|
|
44
|
+
end--;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
}
|
|
@@ -174,6 +174,24 @@
|
|
|
174
174
|
messageBus.UntargetedBroadcast(ref message);
|
|
175
175
|
}
|
|
176
176
|
|
|
177
|
+
/// <summary>
|
|
178
|
+
/// Emits an UntargetedMessage of the given type.
|
|
179
|
+
/// </summary>
|
|
180
|
+
/// <param name="message">UntargetedMessage to emit.</param>
|
|
181
|
+
/// <param name="messageBus">MessageBus to emit to. If null, uses the GlobalMessageBus.</param>
|
|
182
|
+
public static void Emit<TMessage>(this TMessage message, IMessageBus messageBus = null)
|
|
183
|
+
where TMessage : class, IUntargetedMessage
|
|
184
|
+
{
|
|
185
|
+
messageBus ??= MessageHandler.MessageBus;
|
|
186
|
+
if (typeof(TMessage) == typeof(IUntargetedMessage))
|
|
187
|
+
{
|
|
188
|
+
messageBus.UntypedUntargetedBroadcast(message);
|
|
189
|
+
return;
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
messageBus.UntargetedBroadcast(ref message);
|
|
193
|
+
}
|
|
194
|
+
|
|
177
195
|
/// <summary>
|
|
178
196
|
/// Emits an UntargetedMessage of the given type.
|
|
179
197
|
/// </summary>
|
|
@@ -195,6 +213,24 @@
|
|
|
195
213
|
messageBus.UntargetedBroadcast(ref message);
|
|
196
214
|
}
|
|
197
215
|
|
|
216
|
+
/// <summary>
|
|
217
|
+
/// Emits an UntargetedMessage of the given type.
|
|
218
|
+
/// </summary>
|
|
219
|
+
/// <param name="message">UntargetedMessage to emit.</param>
|
|
220
|
+
/// <param name="messageBus">MessageBus to emit to. If null, uses the GlobalMessageBus.</param>
|
|
221
|
+
public static void Emit<TMessage>(this ref TMessage message, IMessageBus messageBus = null)
|
|
222
|
+
where TMessage : struct, IUntargetedMessage
|
|
223
|
+
{
|
|
224
|
+
messageBus ??= MessageHandler.MessageBus;
|
|
225
|
+
if (typeof(TMessage) == typeof(IUntargetedMessage))
|
|
226
|
+
{
|
|
227
|
+
messageBus.UntypedUntargetedBroadcast(message);
|
|
228
|
+
return;
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
messageBus.UntargetedBroadcast(ref message);
|
|
232
|
+
}
|
|
233
|
+
|
|
198
234
|
#if UNITY_2017_1_OR_NEWER
|
|
199
235
|
/// <summary>
|
|
200
236
|
/// Emits a BroadcastMessage of the given type.
|
|
@@ -338,5 +374,35 @@
|
|
|
338
374
|
|
|
339
375
|
messageBus.SourcedBroadcast(ref source, ref message);
|
|
340
376
|
}
|
|
377
|
+
|
|
378
|
+
/// <summary>
|
|
379
|
+
/// Emits a StringMessage at the target containing the provided string.
|
|
380
|
+
/// </summary>
|
|
381
|
+
/// <param name="message">Message to send to the target.</param>
|
|
382
|
+
/// <param name="target">Target to send the message to.</param>
|
|
383
|
+
/// <param name="messageBus">MessageBus to emit to. If null, uses the GlobalMessageBus.</param>
|
|
384
|
+
public static void Emit(
|
|
385
|
+
this string message,
|
|
386
|
+
InstanceId target,
|
|
387
|
+
IMessageBus messageBus = null
|
|
388
|
+
)
|
|
389
|
+
{
|
|
390
|
+
StringMessage stringMessage = new(message);
|
|
391
|
+
(messageBus ?? MessageHandler.MessageBus).TargetedBroadcast(
|
|
392
|
+
ref target,
|
|
393
|
+
ref stringMessage
|
|
394
|
+
);
|
|
395
|
+
}
|
|
396
|
+
|
|
397
|
+
/// <summary>
|
|
398
|
+
/// Emits a GlobalStringMessage containing the provided string.
|
|
399
|
+
/// </summary>
|
|
400
|
+
/// <param name="message">Message to send globally.</param>
|
|
401
|
+
/// <param name="messageBus">MessageBus to emit to. If null, uses the GlobalMessageBus.</param>
|
|
402
|
+
public static void Emit(this string message, IMessageBus messageBus = null)
|
|
403
|
+
{
|
|
404
|
+
GlobalStringMessage stringMessage = new(message);
|
|
405
|
+
(messageBus ?? MessageHandler.MessageBus).UntargetedBroadcast(ref stringMessage);
|
|
406
|
+
}
|
|
341
407
|
}
|
|
342
408
|
}
|
|
@@ -10,11 +10,16 @@
|
|
|
10
10
|
/// </summary>
|
|
11
11
|
public interface IMessageBus
|
|
12
12
|
{
|
|
13
|
+
public static bool GlobalDiagnosticsMode { get; set; }
|
|
14
|
+
public static int GlobalMessageBufferSize { get; set; }
|
|
15
|
+
|
|
13
16
|
internal static int GlobalSequentialIndex = -1;
|
|
14
17
|
|
|
15
18
|
protected static int GenerateNewGlobalSequentialIndex() =>
|
|
16
19
|
Interlocked.Increment(ref GlobalSequentialIndex);
|
|
17
20
|
|
|
21
|
+
public bool DiagnosticsMode { get; }
|
|
22
|
+
|
|
18
23
|
public int RegisteredGlobalSequentialIndex { get; }
|
|
19
24
|
public int RegisteredBroadcast { get; }
|
|
20
25
|
|
|
@@ -283,7 +288,6 @@
|
|
|
283
288
|
/// Broadcasts a fast Untargeted message to all listeners registered to this bus.
|
|
284
289
|
/// </summary>
|
|
285
290
|
/// <param name="typedMessage">Message to broadcast.</param>
|
|
286
|
-
|
|
287
291
|
void UntargetedBroadcast<TMessage>(ref TMessage typedMessage)
|
|
288
292
|
where TMessage : IUntargetedMessage;
|
|
289
293
|
|
|
@@ -299,7 +303,6 @@
|
|
|
299
303
|
/// </summary>
|
|
300
304
|
/// <param name="target">Target to send the message to.</param>
|
|
301
305
|
/// <param name="typedMessage">Message to broadcast.</param>
|
|
302
|
-
|
|
303
306
|
void TargetedBroadcast<TMessage>(ref InstanceId target, ref TMessage typedMessage)
|
|
304
307
|
where TMessage : ITargetedMessage;
|
|
305
308
|
|
|
@@ -315,7 +318,6 @@
|
|
|
315
318
|
/// </summary>
|
|
316
319
|
/// <param name="source">Source of the message.</param>
|
|
317
320
|
/// <param name="typedMessage">Message to broadcast.</param>
|
|
318
|
-
|
|
319
321
|
void SourcedBroadcast<TMessage>(ref InstanceId source, ref TMessage typedMessage)
|
|
320
322
|
where TMessage : IBroadcastMessage;
|
|
321
323
|
}
|