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.
@@ -80,6 +80,112 @@ namespace WallstopStudios.UnityHelpers.Tests.Tags
80
80
  Assert.IsTrue(entity.HasAnyTag(list));
81
81
  }
82
82
 
83
+ [UnityTest]
84
+ public IEnumerator GetActiveTagsExtensionHandlesBuffers()
85
+ {
86
+ GameObject entity = CreateTrackedGameObject("Tagged", typeof(TagHandler));
87
+ yield return null;
88
+ TagHandler handler = entity.GetComponent<TagHandler>();
89
+ handler.ApplyTag("Buff");
90
+ handler.ApplyTag("Shield");
91
+
92
+ List<string> initial = entity.GetActiveTags();
93
+ CollectionAssert.AreEquivalent(new[] { "Buff", "Shield" }, initial);
94
+
95
+ List<string> reusable = new() { "Sentinel" };
96
+ List<string> reused = entity.GetActiveTags(reusable);
97
+ Assert.AreSame(reusable, reused);
98
+ CollectionAssert.AreEquivalent(new[] { "Buff", "Shield" }, reused);
99
+ Assert.IsFalse(reused.Contains("Sentinel"));
100
+ }
101
+
102
+ [UnityTest]
103
+ public IEnumerator GetHandlesWithTagExtensionCreatesBuffers()
104
+ {
105
+ GameObject entity = CreateTrackedGameObject("Entity", typeof(TestAttributesComponent));
106
+ yield return null;
107
+ EffectHandler effectHandler = entity.GetComponent<EffectHandler>();
108
+
109
+ AttributeEffect effect = CreateEffect(
110
+ "Buff",
111
+ e =>
112
+ {
113
+ e.effectTags.Add("Buff");
114
+ }
115
+ );
116
+ EffectHandle handle = effectHandler.ApplyEffect(effect).Value;
117
+
118
+ List<EffectHandle> handles = entity.GetHandlesWithTag("Buff");
119
+ Assert.AreEqual(1, handles.Count);
120
+ Assert.AreEqual(handle, handles[0]);
121
+
122
+ List<EffectHandle> reusable = new() { EffectHandle.CreateInstance(effect) };
123
+ List<EffectHandle> reused = entity.GetHandlesWithTag("Buff", reusable);
124
+ Assert.AreSame(reusable, reused);
125
+ Assert.AreEqual(1, reused.Count);
126
+ Assert.AreEqual(handle, reused[0]);
127
+ }
128
+
129
+ [Test]
130
+ public void AttributeEffectQueryHelpersReturnExpectedResults()
131
+ {
132
+ AttributeEffect effect = CreateEffect(
133
+ "Query",
134
+ e =>
135
+ {
136
+ e.effectTags.Add("Buff");
137
+ e.effectTags.Add("Shield");
138
+ e.modifications.Add(
139
+ new AttributeModification
140
+ {
141
+ attribute = nameof(TestAttributesComponent.health),
142
+ action = ModificationAction.Addition,
143
+ value = 5f,
144
+ }
145
+ );
146
+ e.modifications.Add(
147
+ new AttributeModification
148
+ {
149
+ attribute = nameof(TestAttributesComponent.armor),
150
+ action = ModificationAction.Addition,
151
+ value = 3f,
152
+ }
153
+ );
154
+ e.modifications.Add(
155
+ new AttributeModification
156
+ {
157
+ attribute = nameof(TestAttributesComponent.health),
158
+ action = ModificationAction.Multiplication,
159
+ value = 1.1f,
160
+ }
161
+ );
162
+ }
163
+ );
164
+
165
+ Assert.IsTrue(effect.HasTag("Buff"));
166
+ Assert.IsFalse(effect.HasTag("Missing"));
167
+
168
+ HashSet<string> query = new() { "Missing", "Shield" };
169
+ Assert.IsTrue(effect.HasAnyTag(query));
170
+ IReadOnlyList<string> list = new List<string> { "Other", "Buff" };
171
+ Assert.IsTrue(effect.HasAnyTag(list));
172
+ List<string> none = new() { "Missing" };
173
+ Assert.IsFalse(effect.HasAnyTag(none));
174
+
175
+ Assert.IsTrue(effect.ModifiesAttribute(nameof(TestAttributesComponent.health)));
176
+ Assert.IsTrue(effect.ModifiesAttribute(nameof(TestAttributesComponent.armor)));
177
+ Assert.IsFalse(effect.ModifiesAttribute("Speed"));
178
+
179
+ List<AttributeModification> buffer = new();
180
+ effect.GetModifications(nameof(TestAttributesComponent.health), buffer);
181
+ Assert.AreEqual(2, buffer.Count);
182
+ Assert.AreEqual(nameof(TestAttributesComponent.health), buffer[0].attribute);
183
+ Assert.AreEqual(nameof(TestAttributesComponent.health), buffer[1].attribute);
184
+
185
+ effect.GetModifications("Speed", buffer);
186
+ Assert.AreEqual(0, buffer.Count);
187
+ }
188
+
83
189
  [UnityTest]
84
190
  public IEnumerator ApplyEffectAddsAttributesCosmeticsAndTags()
85
191
  {
@@ -370,6 +476,145 @@ namespace WallstopStudios.UnityHelpers.Tests.Tags
370
476
  Assert.IsFalse(entity.HasTag("Buff"));
371
477
  }
372
478
 
479
+ [UnityTest]
480
+ public IEnumerator ExtensionHelpersBridgeTagAndEffectQueries()
481
+ {
482
+ GameObject entity = CreateTrackedGameObject("Entity", typeof(TestAttributesComponent));
483
+ yield return null;
484
+
485
+ AttributeEffect effect = CreateEffect(
486
+ "Utility",
487
+ e =>
488
+ {
489
+ e.duration = 0.3f;
490
+ e.resetDurationOnReapplication = true;
491
+ e.effectTags.Add("Buff");
492
+ e.modifications.Add(
493
+ new AttributeModification
494
+ {
495
+ attribute = nameof(TestAttributesComponent.health),
496
+ action = ModificationAction.Addition,
497
+ value = 5f,
498
+ }
499
+ );
500
+ }
501
+ );
502
+
503
+ List<string> tagsBuffer = new();
504
+ List<EffectHandle> handlesBuffer = new();
505
+
506
+ Assert.IsFalse(entity.HasAllTags(new[] { "Buff" }));
507
+ EffectHandle? handle = entity.ApplyEffect(effect);
508
+ Assert.IsTrue(handle.HasValue);
509
+
510
+ Assert.IsTrue(entity.HasAllTags(new[] { "Buff" }));
511
+ Assert.IsFalse(entity.HasAllTags(new[] { "Buff", "Missing" }));
512
+ Assert.IsTrue(entity.HasNoneOfTags(new[] { "Missing" }));
513
+ List<string> none = new() { "Buff" };
514
+ Assert.IsFalse(entity.HasNoneOfTags(none));
515
+
516
+ Assert.IsTrue(entity.TryGetTagCount("Buff", out int tagCount));
517
+ Assert.AreEqual(1, tagCount);
518
+
519
+ Assert.AreNotEqual(0, entity.GetActiveTags(tagsBuffer).Count);
520
+ CollectionAssert.Contains(tagsBuffer, "Buff");
521
+
522
+ Assert.AreNotEqual(0, entity.GetHandlesWithTag("Buff", handlesBuffer).Count);
523
+ Assert.AreEqual(1, handlesBuffer.Count);
524
+
525
+ Assert.IsTrue(entity.IsEffectActive(effect));
526
+ Assert.AreEqual(1, entity.GetEffectStackCount(effect));
527
+
528
+ List<EffectHandle> activeEffects = entity.GetActiveEffects(new List<EffectHandle>());
529
+ Assert.AreEqual(1, activeEffects.Count);
530
+
531
+ EffectHandle activeHandle = handlesBuffer[0];
532
+ Assert.IsTrue(entity.TryGetRemainingDuration(activeHandle, out float remaining));
533
+ Assert.Greater(remaining, 0f);
534
+
535
+ yield return null;
536
+ Assert.IsTrue(entity.TryGetRemainingDuration(activeHandle, out float beforeEnsure));
537
+
538
+ EffectHandle? ensured = entity.EnsureHandle(effect);
539
+ Assert.IsTrue(ensured.HasValue);
540
+ Assert.AreEqual(activeHandle, ensured.Value);
541
+ Assert.IsTrue(entity.TryGetRemainingDuration(activeHandle, out float afterEnsure));
542
+ Assert.Greater(afterEnsure, beforeEnsure);
543
+
544
+ yield return null;
545
+ Assert.IsTrue(entity.TryGetRemainingDuration(activeHandle, out float beforeNoRefresh));
546
+ EffectHandle? ensuredNoRefresh = entity.EnsureHandle(effect, refreshDuration: false);
547
+ Assert.IsTrue(ensuredNoRefresh.HasValue);
548
+ Assert.AreEqual(activeHandle, ensuredNoRefresh.Value);
549
+ Assert.IsTrue(entity.TryGetRemainingDuration(activeHandle, out float afterNoRefresh));
550
+ Assert.LessOrEqual(afterNoRefresh, beforeNoRefresh);
551
+
552
+ Assert.IsTrue(entity.RefreshEffect(activeHandle));
553
+
554
+ entity.RemoveAllEffects();
555
+ tagsBuffer.Clear();
556
+ Assert.AreEqual(0, entity.GetActiveTags(tagsBuffer).Count);
557
+ Assert.IsEmpty(tagsBuffer);
558
+ handlesBuffer.Clear();
559
+ Assert.AreEqual(0, entity.GetHandlesWithTag("Buff", handlesBuffer).Count);
560
+ }
561
+
562
+ [UnityTest]
563
+ public IEnumerator ApplyEffectsNoAllocAppendsToProvidedHandlesBuffer()
564
+ {
565
+ GameObject entity = CreateTrackedGameObject("Entity", typeof(TestAttributesComponent));
566
+ yield return null;
567
+
568
+ List<AttributeEffect> effects = new() { CreateEffect("BuffA"), CreateEffect("BuffB") };
569
+
570
+ EffectHandle sentinel = EffectHandle.CreateInstance(CreateEffect("Sentinel"));
571
+ List<EffectHandle> handles = new() { sentinel };
572
+ entity.ApplyEffectsNoAlloc(effects, handles);
573
+
574
+ Assert.AreEqual(effects.Count + 1, handles.Count);
575
+ Assert.AreEqual(sentinel, handles[0]);
576
+ }
577
+
578
+ [UnityTest]
579
+ public IEnumerator GetActiveEffectsClearsBufferBeforePopulation()
580
+ {
581
+ GameObject entity = CreateTrackedGameObject("Entity", typeof(TestAttributesComponent));
582
+ yield return null;
583
+ EffectHandler handler = entity.GetComponent<EffectHandler>();
584
+
585
+ AttributeEffect effect = CreateEffect("Tracked");
586
+ EffectHandle handle = handler.ApplyEffect(effect).Value;
587
+
588
+ EffectHandle sentinel = EffectHandle.CreateInstance(CreateEffect("Sentinel"));
589
+ List<EffectHandle> buffer = new() { sentinel };
590
+ List<EffectHandle> populated = entity.GetActiveEffects(buffer);
591
+ Assert.AreSame(buffer, populated);
592
+ Assert.AreEqual(1, populated.Count);
593
+ Assert.AreEqual(handle, populated[0]);
594
+ Assert.AreNotEqual(sentinel, populated[0]);
595
+ yield return null;
596
+ }
597
+
598
+ [UnityTest]
599
+ public IEnumerator RefreshEffectIgnorePolicyExtensionRefreshesWhenDisallowed()
600
+ {
601
+ GameObject entity = CreateTrackedGameObject("Entity", typeof(TestAttributesComponent));
602
+ yield return null;
603
+ AttributeEffect effect = CreateEffect(
604
+ "Policy",
605
+ e =>
606
+ {
607
+ e.duration = 0.2f;
608
+ e.resetDurationOnReapplication = false;
609
+ }
610
+ );
611
+
612
+ EffectHandle handle = entity.ApplyEffect(effect).Value;
613
+ yield return null;
614
+ Assert.IsFalse(entity.RefreshEffect(handle));
615
+ Assert.IsTrue(entity.RefreshEffect(handle, ignoreReapplicationPolicy: true));
616
+ }
617
+
373
618
  [UnityTest]
374
619
  public IEnumerator ApplyEffectsNoAllocSkipsNullTarget()
375
620
  {
@@ -111,7 +111,7 @@ namespace WallstopStudios.UnityHelpers.Tests.Tags
111
111
  yield return null;
112
112
  Assert.IsFalse(collider.enabled);
113
113
 
114
- handler.RemoveTag(CollisionSenses.CollisionDisabledTag, allInstances: false);
114
+ handler.RemoveTag(CollisionSenses.CollisionDisabledTag);
115
115
  yield return null;
116
116
  Assert.IsTrue(collider.enabled);
117
117
  }
@@ -1,6 +1,7 @@
1
1
  namespace WallstopStudios.UnityHelpers.Tests.Tags
2
2
  {
3
3
  using System.Collections;
4
+ using System.Collections.Generic;
4
5
  using NUnit.Framework;
5
6
  using UnityEngine;
6
7
  using UnityEngine.TestTools;
@@ -238,6 +239,196 @@ namespace WallstopStudios.UnityHelpers.Tests.Tags
238
239
  Assert.AreEqual(1, RecordingCosmeticComponent.RemovedCount);
239
240
  }
240
241
 
242
+ [UnityTest]
243
+ public IEnumerator IsEffectActiveReflectsState()
244
+ {
245
+ (
246
+ GameObject entity,
247
+ EffectHandler handler,
248
+ TestAttributesComponent attributes,
249
+ TagHandler tags
250
+ ) = CreateEntity();
251
+ yield return null;
252
+
253
+ AttributeEffect effect = CreateEffect("Buff");
254
+ Assert.IsFalse(handler.IsEffectActive(effect));
255
+
256
+ EffectHandle handle = handler.ApplyEffect(effect).Value;
257
+ Assert.IsTrue(handler.IsEffectActive(effect));
258
+
259
+ handler.RemoveEffect(handle);
260
+ Assert.IsFalse(handler.IsEffectActive(effect));
261
+ }
262
+
263
+ [UnityTest]
264
+ public IEnumerator GetEffectStackCountSupportsMultipleHandles()
265
+ {
266
+ (
267
+ GameObject entity,
268
+ EffectHandler handler,
269
+ TestAttributesComponent attributes,
270
+ TagHandler tags
271
+ ) = CreateEntity();
272
+ yield return null;
273
+
274
+ AttributeEffect effect = CreateEffect(
275
+ "Stacking",
276
+ e =>
277
+ {
278
+ e.durationType = ModifierDurationType.Infinite;
279
+ }
280
+ );
281
+
282
+ EffectHandle first = handler.ApplyEffect(effect).Value;
283
+ EffectHandle second = handler.ApplyEffect(effect).Value;
284
+
285
+ Assert.AreEqual(2, handler.GetEffectStackCount(effect));
286
+
287
+ handler.RemoveEffect(first);
288
+ Assert.AreEqual(1, handler.GetEffectStackCount(effect));
289
+
290
+ handler.RemoveEffect(second);
291
+ Assert.AreEqual(0, handler.GetEffectStackCount(effect));
292
+ }
293
+
294
+ [UnityTest]
295
+ public IEnumerator GetActiveEffectsPopulatesBuffer()
296
+ {
297
+ (
298
+ GameObject entity,
299
+ EffectHandler handler,
300
+ TestAttributesComponent attributes,
301
+ TagHandler tags
302
+ ) = CreateEntity();
303
+ yield return null;
304
+
305
+ AttributeEffect effect = CreateEffect(
306
+ "Active",
307
+ e =>
308
+ {
309
+ e.durationType = ModifierDurationType.Infinite;
310
+ }
311
+ );
312
+
313
+ EffectHandle first = handler.ApplyEffect(effect).Value;
314
+ EffectHandle second = handler.ApplyEffect(effect).Value;
315
+
316
+ List<EffectHandle> buffer = new();
317
+ handler.GetActiveEffects(buffer);
318
+ CollectionAssert.AreEquivalent(new[] { first, second }, buffer);
319
+
320
+ handler.RemoveEffect(first);
321
+ buffer.Clear();
322
+ handler.GetActiveEffects(buffer);
323
+ CollectionAssert.AreEqual(new[] { second }, buffer);
324
+
325
+ handler.RemoveEffect(second);
326
+ }
327
+
328
+ [UnityTest]
329
+ public IEnumerator TryGetRemainingDurationReportsTime()
330
+ {
331
+ (
332
+ GameObject entity,
333
+ EffectHandler handler,
334
+ TestAttributesComponent attributes,
335
+ TagHandler tags
336
+ ) = CreateEntity();
337
+ yield return null;
338
+
339
+ AttributeEffect effect = CreateEffect(
340
+ "Timed",
341
+ e =>
342
+ {
343
+ e.duration = 0.5f;
344
+ }
345
+ );
346
+
347
+ EffectHandle handle = handler.ApplyEffect(effect).Value;
348
+ Assert.IsTrue(handler.TryGetRemainingDuration(handle, out float remaining));
349
+ Assert.Greater(remaining, 0f);
350
+ Assert.LessOrEqual(remaining, effect.duration);
351
+
352
+ handler.RemoveEffect(handle);
353
+ Assert.IsFalse(handler.TryGetRemainingDuration(handle, out float afterRemoval));
354
+ Assert.AreEqual(0f, afterRemoval);
355
+ }
356
+
357
+ [UnityTest]
358
+ public IEnumerator EnsureHandleRefreshesDurationWhenRequested()
359
+ {
360
+ (
361
+ GameObject entity,
362
+ EffectHandler handler,
363
+ TestAttributesComponent attributes,
364
+ TagHandler tags
365
+ ) = CreateEntity();
366
+ yield return null;
367
+
368
+ AttributeEffect effect = CreateEffect(
369
+ "Refreshable",
370
+ e =>
371
+ {
372
+ e.duration = 0.2f;
373
+ e.resetDurationOnReapplication = true;
374
+ }
375
+ );
376
+
377
+ EffectHandle handle = handler.ApplyEffect(effect).Value;
378
+ Assert.IsTrue(handler.TryGetRemainingDuration(handle, out float initialRemaining));
379
+ yield return null;
380
+ Assert.IsTrue(handler.TryGetRemainingDuration(handle, out float beforeRefresh));
381
+ Assert.Less(beforeRefresh, initialRemaining);
382
+
383
+ EffectHandle? ensured = handler.EnsureHandle(effect);
384
+ Assert.IsTrue(ensured.HasValue);
385
+ Assert.AreEqual(handle, ensured.Value);
386
+ Assert.IsTrue(handler.TryGetRemainingDuration(handle, out float afterRefresh));
387
+ Assert.Greater(afterRefresh, beforeRefresh);
388
+
389
+ yield return null;
390
+ Assert.IsTrue(handler.TryGetRemainingDuration(handle, out float beforeNoRefresh));
391
+ EffectHandle? ensuredNoRefresh = handler.EnsureHandle(effect, refreshDuration: false);
392
+ Assert.IsTrue(ensuredNoRefresh.HasValue);
393
+ Assert.AreEqual(handle, ensuredNoRefresh.Value);
394
+ Assert.IsTrue(handler.TryGetRemainingDuration(handle, out float afterNoRefresh));
395
+ Assert.LessOrEqual(afterNoRefresh, beforeNoRefresh);
396
+
397
+ handler.RemoveEffect(handle);
398
+ }
399
+
400
+ [UnityTest]
401
+ public IEnumerator RefreshEffectHonorsReapplicationPolicy()
402
+ {
403
+ (
404
+ GameObject entity,
405
+ EffectHandler handler,
406
+ TestAttributesComponent attributes,
407
+ TagHandler tags
408
+ ) = CreateEntity();
409
+ yield return null;
410
+
411
+ AttributeEffect effect = CreateEffect(
412
+ "Policy",
413
+ e =>
414
+ {
415
+ e.duration = 0.3f;
416
+ e.resetDurationOnReapplication = false;
417
+ }
418
+ );
419
+
420
+ EffectHandle handle = handler.ApplyEffect(effect).Value;
421
+ yield return null;
422
+ Assert.IsTrue(handler.TryGetRemainingDuration(handle, out float beforeRefresh));
423
+
424
+ Assert.IsFalse(handler.RefreshEffect(handle));
425
+ Assert.IsTrue(handler.RefreshEffect(handle, ignoreReapplicationPolicy: true));
426
+ Assert.IsTrue(handler.TryGetRemainingDuration(handle, out float afterRefresh));
427
+ Assert.Greater(afterRefresh, beforeRefresh);
428
+
429
+ handler.RemoveEffect(handle);
430
+ }
431
+
241
432
  private (
242
433
  GameObject entity,
243
434
  EffectHandler handler,
@@ -33,18 +33,19 @@ namespace WallstopStudios.UnityHelpers.Tests.Tags
33
33
 
34
34
  handler.ApplyTag("Buff");
35
35
  handler.ApplyTag("Buff");
36
- handler.RemoveTag("Buff", allInstances: false);
37
- handler.RemoveTag("Buff", allInstances: false);
36
+ handler.ApplyTag("Buff");
37
+ handler.RemoveTag("Buff");
38
38
 
39
39
  Assert.AreEqual(new[] { "Buff" }, added);
40
+ Assert.AreEqual(2, changed.Count);
40
41
  Assert.AreEqual(("Buff", 2U), changed[0]);
41
- Assert.AreEqual(("Buff", 1U), changed[1]);
42
+ Assert.AreEqual(("Buff", 3U), changed[1]);
42
43
  Assert.AreEqual(new[] { "Buff" }, removed);
43
44
  yield return null;
44
45
  }
45
46
 
46
47
  [UnityTest]
47
- public IEnumerator RemoveTagAllInstancesClearsWithoutEvents()
48
+ public IEnumerator RemoveTagAllInstancesClearsWithEvents()
48
49
  {
49
50
  GameObject entity = CreateTrackedGameObject("Tags", typeof(TagHandler));
50
51
  TagHandler handler = entity.GetComponent<TagHandler>();
@@ -53,10 +54,10 @@ namespace WallstopStudios.UnityHelpers.Tests.Tags
53
54
  handler.OnTagRemoved += _ => ++removedCount;
54
55
 
55
56
  handler.ApplyTag("Buff");
56
- handler.RemoveTag("Buff", allInstances: true);
57
+ handler.RemoveTag("Buff");
57
58
 
58
59
  Assert.IsFalse(handler.HasTag("Buff"));
59
- Assert.AreEqual(0, removedCount);
60
+ Assert.AreEqual(1, removedCount);
60
61
  yield return null;
61
62
  }
62
63
 
@@ -104,5 +105,128 @@ namespace WallstopStudios.UnityHelpers.Tests.Tags
104
105
  Assert.IsFalse(handler.ForceRemoveTags(handle));
105
106
  yield return null;
106
107
  }
108
+
109
+ [UnityTest]
110
+ public IEnumerator HasAllTagsAndHasNoneTagSupport()
111
+ {
112
+ GameObject entity = CreateTrackedGameObject("Tags", typeof(TagHandler));
113
+ TagHandler handler = entity.GetComponent<TagHandler>();
114
+
115
+ handler.ApplyTag("Buff");
116
+ handler.ApplyTag("Shield");
117
+
118
+ Assert.IsTrue(handler.HasAllTags(new[] { "Buff" }));
119
+ List<string> required = new() { "Buff", "Shield" };
120
+ Assert.IsTrue(handler.HasAllTags(required));
121
+ Assert.IsFalse(handler.HasAllTags(new[] { "Buff", "Missing" }));
122
+
123
+ List<string> none = new() { "Missing", "Other" };
124
+ Assert.IsTrue(handler.HasNoneOfTags(none));
125
+ none[1] = "Buff";
126
+ Assert.IsFalse(handler.HasNoneOfTags(none));
127
+ yield return null;
128
+ }
129
+
130
+ [UnityTest]
131
+ public IEnumerator TryGetTagCountAndActiveTagsPopulateBuffer()
132
+ {
133
+ GameObject entity = CreateTrackedGameObject("Tags", typeof(TagHandler));
134
+ TagHandler handler = entity.GetComponent<TagHandler>();
135
+
136
+ handler.ApplyTag("Buff");
137
+ handler.ApplyTag("Buff");
138
+ handler.ApplyTag("Shield");
139
+
140
+ Assert.IsTrue(handler.TryGetTagCount("Buff", out int buffCount));
141
+ Assert.AreEqual(2, buffCount);
142
+ Assert.IsFalse(handler.TryGetTagCount("Missing", out int missingCount));
143
+ Assert.AreEqual(0, missingCount);
144
+
145
+ List<string> active = new();
146
+ handler.GetActiveTags(active);
147
+ CollectionAssert.AreEquivalent(new[] { "Buff", "Shield" }, active);
148
+ yield return null;
149
+ }
150
+
151
+ [UnityTest]
152
+ public IEnumerator GetHandlesWithTagTracksHandleLifecycle()
153
+ {
154
+ GameObject entity = CreateTrackedGameObject("Entity", typeof(TestAttributesComponent));
155
+ TagHandler handler = entity.GetComponent<TagHandler>();
156
+ EffectHandler effectHandler = entity.GetComponent<EffectHandler>();
157
+
158
+ AttributeEffect effect = CreateEffect(
159
+ "Buff",
160
+ e =>
161
+ {
162
+ e.effectTags.Add("Buff");
163
+ }
164
+ );
165
+ EffectHandle handle = effectHandler.ApplyEffect(effect).Value;
166
+
167
+ List<EffectHandle> handles = new();
168
+ Assert.AreNotEqual(0, handler.GetHandlesWithTag("Buff", handles).Count);
169
+ Assert.AreEqual(1, handles.Count);
170
+ Assert.AreEqual(handle, handles[0]);
171
+
172
+ handles.Clear();
173
+ handler.RemoveTag("Buff");
174
+ Assert.AreEqual(0, handler.GetHandlesWithTag("Buff", handles).Count);
175
+
176
+ handles.Clear();
177
+ effectHandler.RemoveEffect(handle);
178
+ Assert.AreEqual(0, handler.GetHandlesWithTag("Buff", handles).Count);
179
+ yield return null;
180
+ }
181
+
182
+ [UnityTest]
183
+ public IEnumerator GetActiveTagsReturnsNewBufferWhenNeeded()
184
+ {
185
+ GameObject entity = CreateTrackedGameObject("Tags", typeof(TagHandler));
186
+ TagHandler handler = entity.GetComponent<TagHandler>();
187
+
188
+ handler.ApplyTag("Buff");
189
+ handler.ApplyTag("Shield");
190
+
191
+ List<string> firstCall = handler.GetActiveTags();
192
+ Assert.IsNotNull(firstCall);
193
+ CollectionAssert.AreEquivalent(new[] { "Buff", "Shield" }, firstCall);
194
+
195
+ List<string> reusable = new() { "Sentinel" };
196
+ List<string> secondCall = handler.GetActiveTags(reusable);
197
+ Assert.AreSame(reusable, secondCall);
198
+ CollectionAssert.AreEquivalent(new[] { "Buff", "Shield" }, secondCall);
199
+ Assert.IsFalse(secondCall.Contains("Sentinel"));
200
+ yield return null;
201
+ }
202
+
203
+ [UnityTest]
204
+ public IEnumerator RemoveTagReturnsContributingHandles()
205
+ {
206
+ GameObject entity = CreateTrackedGameObject("Entity", typeof(TestAttributesComponent));
207
+ yield return null;
208
+ TagHandler handler = entity.GetComponent<TagHandler>();
209
+ EffectHandler effectHandler = entity.GetComponent<EffectHandler>();
210
+
211
+ AttributeEffect effect = CreateEffect(
212
+ "Buff",
213
+ e =>
214
+ {
215
+ e.effectTags.Add("Buff");
216
+ }
217
+ );
218
+ EffectHandle handle = effectHandler.ApplyEffect(effect).Value;
219
+
220
+ List<EffectHandle> removed = handler.RemoveTag("Buff");
221
+ Assert.AreEqual(1, removed.Count);
222
+ Assert.AreEqual(handle, removed[0]);
223
+ Assert.IsFalse(handler.HasTag("Buff"));
224
+ Assert.AreEqual(0, handler.GetHandlesWithTag("Buff").Count);
225
+
226
+ List<EffectHandle> empty = handler.RemoveTag("Missing");
227
+ Assert.IsNotNull(empty);
228
+ Assert.AreEqual(0, empty.Count);
229
+ yield return null;
230
+ }
107
231
  }
108
232
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "com.wallstop-studios.unity-helpers",
3
- "version": "2.0.3",
3
+ "version": "2.0.4",
4
4
  "displayName": "Unity Helpers",
5
5
  "description": "Various Unity Helper Library",
6
6
  "dependencies": {},