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
|
@@ -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
|
|
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.
|
|
37
|
-
handler.RemoveTag("Buff"
|
|
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",
|
|
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
|
|
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"
|
|
57
|
+
handler.RemoveTag("Buff");
|
|
57
58
|
|
|
58
59
|
Assert.IsFalse(handler.HasTag("Buff"));
|
|
59
|
-
Assert.AreEqual(
|
|
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
|
}
|