com.wallstop-studios.unity-helpers 2.0.3 → 2.0.4
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/Runtime/Core/Helper/UnityMainThreadDispatcher.cs +4 -2
- package/Runtime/Tags/AttributeEffect.cs +167 -3
- package/Runtime/Tags/AttributeUtilities.cs +465 -0
- package/Runtime/Tags/EffectHandler.cs +179 -0
- package/Runtime/Tags/TagHandler.cs +375 -21
- package/Tests/Runtime/Tags/AttributeUtilitiesTests.cs +245 -0
- package/Tests/Runtime/Tags/CosmeticAndCollisionTests.cs +1 -1
- package/Tests/Runtime/Tags/EffectHandlerTests.cs +191 -0
- package/Tests/Runtime/Tags/TagHandlerTests.cs +130 -6
- package/package.json +1 -1
|
@@ -2,6 +2,7 @@ namespace WallstopStudios.UnityHelpers.Core.Helper
|
|
|
2
2
|
{
|
|
3
3
|
using System;
|
|
4
4
|
using System.Collections.Concurrent;
|
|
5
|
+
using System.Threading.Tasks;
|
|
5
6
|
using UnityEngine;
|
|
6
7
|
using Utils;
|
|
7
8
|
#if UNITY_EDITOR
|
|
@@ -104,7 +105,8 @@ namespace WallstopStudios.UnityHelpers.Core.Helper
|
|
|
104
105
|
/// </summary>
|
|
105
106
|
public System.Threading.Tasks.Task RunAsync(Action action)
|
|
106
107
|
{
|
|
107
|
-
|
|
108
|
+
TaskCompletionSource<bool> tcs =
|
|
109
|
+
new System.Threading.Tasks.TaskCompletionSource<bool>();
|
|
108
110
|
RunOnMainThread(() =>
|
|
109
111
|
{
|
|
110
112
|
try
|
|
@@ -125,7 +127,7 @@ namespace WallstopStudios.UnityHelpers.Core.Helper
|
|
|
125
127
|
/// </summary>
|
|
126
128
|
public System.Threading.Tasks.Task<T> Post<T>(Func<T> func)
|
|
127
129
|
{
|
|
128
|
-
|
|
130
|
+
TaskCompletionSource<T> tcs = new System.Threading.Tasks.TaskCompletionSource<T>();
|
|
129
131
|
RunOnMainThread(() =>
|
|
130
132
|
{
|
|
131
133
|
try
|
|
@@ -9,6 +9,7 @@ namespace WallstopStudios.UnityHelpers.Tags
|
|
|
9
9
|
using Core.Extension;
|
|
10
10
|
using Core.Helper;
|
|
11
11
|
using UnityEngine;
|
|
12
|
+
using WallstopStudios.UnityHelpers.Utils;
|
|
12
13
|
#if ODIN_INSPECTOR
|
|
13
14
|
using Sirenix.OdinInspector;
|
|
14
15
|
#endif
|
|
@@ -52,6 +53,7 @@ namespace WallstopStudios.UnityHelpers.Tags
|
|
|
52
53
|
/// </para>
|
|
53
54
|
/// </remarks>
|
|
54
55
|
[Serializable]
|
|
56
|
+
[CreateAssetMenu(menuName = "Wallstop Studios/Unity Helpers/Attribute Effect")]
|
|
55
57
|
public sealed class AttributeEffect :
|
|
56
58
|
#if ODIN_INSPECTOR
|
|
57
59
|
SerializedScriptableObject
|
|
@@ -72,7 +74,7 @@ namespace WallstopStudios.UnityHelpers.Tags
|
|
|
72
74
|
/// The list of attribute modifications to apply when this effect is activated.
|
|
73
75
|
/// Each modification specifies an attribute name, action type, and value.
|
|
74
76
|
/// </summary>
|
|
75
|
-
public
|
|
77
|
+
public List<AttributeModification> modifications = new();
|
|
76
78
|
|
|
77
79
|
/// <summary>
|
|
78
80
|
/// Specifies how long this effect should persist (Instant, Duration, or Infinite).
|
|
@@ -110,12 +112,172 @@ namespace WallstopStudios.UnityHelpers.Tags
|
|
|
110
112
|
/// </example>
|
|
111
113
|
public List<string> effectTags = new();
|
|
112
114
|
|
|
115
|
+
/// <summary>
|
|
116
|
+
/// Determines whether this effect applies the specified tag.
|
|
117
|
+
/// </summary>
|
|
118
|
+
/// <param name="effectTag">The tag to check.</param>
|
|
119
|
+
/// <returns><c>true</c> if the tag is present; otherwise, <c>false</c>.</returns>
|
|
120
|
+
public bool HasTag(string effectTag)
|
|
121
|
+
{
|
|
122
|
+
if (effectTags == null || string.IsNullOrEmpty(effectTag))
|
|
123
|
+
{
|
|
124
|
+
return false;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
for (int i = 0; i < effectTags.Count; ++i)
|
|
128
|
+
{
|
|
129
|
+
if (string.Equals(effectTags[i], effectTag, StringComparison.Ordinal))
|
|
130
|
+
{
|
|
131
|
+
return true;
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
return false;
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
/// <summary>
|
|
139
|
+
/// Determines whether this effect applies any of the specified tags.
|
|
140
|
+
/// </summary>
|
|
141
|
+
/// <param name="effectTagsToCheck">The tags to inspect.</param>
|
|
142
|
+
/// <returns><c>true</c> if at least one tag is applied; otherwise, <c>false</c>.</returns>
|
|
143
|
+
public bool HasAnyTag(IEnumerable<string> effectTagsToCheck)
|
|
144
|
+
{
|
|
145
|
+
if (effectTags == null || effectTagsToCheck == null)
|
|
146
|
+
{
|
|
147
|
+
return false;
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
switch (effectTagsToCheck)
|
|
151
|
+
{
|
|
152
|
+
case IReadOnlyList<string> list:
|
|
153
|
+
{
|
|
154
|
+
return HasAnyTag(list);
|
|
155
|
+
}
|
|
156
|
+
case HashSet<string> hashSet:
|
|
157
|
+
{
|
|
158
|
+
foreach (string candidate in hashSet)
|
|
159
|
+
{
|
|
160
|
+
if (string.IsNullOrEmpty(candidate))
|
|
161
|
+
{
|
|
162
|
+
continue;
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
if (HasTag(candidate))
|
|
166
|
+
{
|
|
167
|
+
return true;
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
return false;
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
foreach (string candidate in effectTagsToCheck)
|
|
176
|
+
{
|
|
177
|
+
if (string.IsNullOrEmpty(candidate))
|
|
178
|
+
{
|
|
179
|
+
continue;
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
if (HasTag(candidate))
|
|
183
|
+
{
|
|
184
|
+
return true;
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
return false;
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
/// <summary>
|
|
192
|
+
/// Determines whether this effect applies any of the specified tags.
|
|
193
|
+
/// Optimized for indexed collections.
|
|
194
|
+
/// </summary>
|
|
195
|
+
/// <param name="effectTagsToCheck">The tags to inspect.</param>
|
|
196
|
+
/// <returns><c>true</c> if at least one tag is applied; otherwise, <c>false</c>.</returns>
|
|
197
|
+
public bool HasAnyTag(IReadOnlyList<string> effectTagsToCheck)
|
|
198
|
+
{
|
|
199
|
+
if (effectTags == null || effectTagsToCheck == null)
|
|
200
|
+
{
|
|
201
|
+
return false;
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
for (int i = 0; i < effectTagsToCheck.Count; ++i)
|
|
205
|
+
{
|
|
206
|
+
string candidate = effectTagsToCheck[i];
|
|
207
|
+
if (string.IsNullOrEmpty(candidate))
|
|
208
|
+
{
|
|
209
|
+
continue;
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
if (HasTag(candidate))
|
|
213
|
+
{
|
|
214
|
+
return true;
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
return false;
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
/// <summary>
|
|
222
|
+
/// Determines whether this effect contains modifications for the specified attribute.
|
|
223
|
+
/// </summary>
|
|
224
|
+
/// <param name="attributeName">The attribute name to inspect.</param>
|
|
225
|
+
/// <returns><c>true</c> if the effect modifies <paramref name="attributeName"/>; otherwise, <c>false</c>.</returns>
|
|
226
|
+
public bool ModifiesAttribute(string attributeName)
|
|
227
|
+
{
|
|
228
|
+
if (modifications == null || string.IsNullOrEmpty(attributeName))
|
|
229
|
+
{
|
|
230
|
+
return false;
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
for (int i = 0; i < modifications.Count; ++i)
|
|
234
|
+
{
|
|
235
|
+
AttributeModification modification = modifications[i];
|
|
236
|
+
if (string.Equals(modification.attribute, attributeName, StringComparison.Ordinal))
|
|
237
|
+
{
|
|
238
|
+
return true;
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
return false;
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
/// <summary>
|
|
246
|
+
/// Copies all modifications that affect the specified attribute into the provided buffer.
|
|
247
|
+
/// </summary>
|
|
248
|
+
/// <param name="attributeName">The attribute to filter by.</param>
|
|
249
|
+
/// <param name="buffer">The destination buffer. Existing entries are preserved.</param>
|
|
250
|
+
/// <returns>The number of modifications added to <paramref name="buffer"/>.</returns>
|
|
251
|
+
public List<AttributeModification> GetModifications(
|
|
252
|
+
string attributeName,
|
|
253
|
+
List<AttributeModification> buffer = null
|
|
254
|
+
)
|
|
255
|
+
{
|
|
256
|
+
buffer ??= new List<AttributeModification>();
|
|
257
|
+
buffer.Clear();
|
|
258
|
+
if (modifications == null || string.IsNullOrEmpty(attributeName))
|
|
259
|
+
{
|
|
260
|
+
return buffer;
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
for (int i = 0; i < modifications.Count; ++i)
|
|
264
|
+
{
|
|
265
|
+
AttributeModification modification = modifications[i];
|
|
266
|
+
if (string.Equals(modification.attribute, attributeName, StringComparison.Ordinal))
|
|
267
|
+
{
|
|
268
|
+
buffer.Add(modification);
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
return buffer;
|
|
273
|
+
}
|
|
274
|
+
|
|
113
275
|
/// <summary>
|
|
114
276
|
/// A list of cosmetic effect data that defines visual and audio feedback for this effect.
|
|
115
277
|
/// These are applied when the effect becomes active and removed when it expires.
|
|
116
278
|
/// </summary>
|
|
117
279
|
[JsonIgnore]
|
|
118
|
-
public
|
|
280
|
+
public List<CosmeticEffectData> cosmeticEffects = new();
|
|
119
281
|
|
|
120
282
|
private List<string> CosmeticEffectsForJson =>
|
|
121
283
|
cosmeticEffects?.Select(cosmeticEffectData => cosmeticEffectData.name).ToList()
|
|
@@ -145,7 +307,9 @@ namespace WallstopStudios.UnityHelpers.Tags
|
|
|
145
307
|
return nameof(AttributeEffect);
|
|
146
308
|
}
|
|
147
309
|
|
|
148
|
-
StringBuilder
|
|
310
|
+
using PooledResource<StringBuilder> stringBuilderBuffer = Buffers.StringBuilder.Get(
|
|
311
|
+
out StringBuilder descriptionBuilder
|
|
312
|
+
);
|
|
149
313
|
for (int i = 0; i < modifications.Count; ++i)
|
|
150
314
|
{
|
|
151
315
|
AttributeModification modification = modifications[i];
|