com.wallstop-studios.unity-helpers 2.0.0-rc67 → 2.0.0-rc69
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/Attributes/ValidateAssignmentAttribute.cs +1 -1
- package/Runtime/Core/Helper/Helpers.cs +1 -1
- package/Runtime/Core/Helper/Partials/LogHelpers.cs +1 -1
- package/Runtime/Core/Helper/Partials/MathHelpers.cs +1 -1
- package/Runtime/Core/Helper/Partials/ObjectHelpers.cs +3 -4
- package/Runtime/Tags/Attribute.cs +205 -0
- package/Runtime/Tags/Attribute.cs.meta +3 -0
- package/Runtime/Tags/AttributeEffect.cs +276 -0
- package/Runtime/Tags/AttributeEffect.cs.meta +3 -0
- package/Runtime/Tags/AttributeModification.cs +51 -0
- package/Runtime/Tags/AttributeModification.cs.meta +3 -0
- package/Runtime/Tags/AttributeUtilities.cs +208 -0
- package/Runtime/Tags/AttributeUtilities.cs.meta +3 -0
- package/Runtime/Tags/AttributesComponent.cs +163 -0
- package/Runtime/Tags/AttributesComponent.cs.meta +3 -0
- package/Runtime/Tags/CosmeticEffectComponent.cs +50 -0
- package/Runtime/Tags/CosmeticEffectComponent.cs.meta +3 -0
- package/Runtime/Tags/CosmeticEffectData.cs +63 -0
- package/Runtime/Tags/CosmeticEffectData.cs.meta +3 -0
- package/Runtime/Tags/EffectHandle.cs +63 -0
- package/Runtime/Tags/EffectHandle.cs.meta +3 -0
- package/Runtime/Tags/EffectHandler.cs +379 -0
- package/Runtime/Tags/EffectHandler.cs.meta +3 -0
- package/Runtime/Tags/ModificationAction.cs +9 -0
- package/Runtime/Tags/ModificationAction.cs.meta +3 -0
- package/Runtime/Tags/ModifierDurationType.cs +13 -0
- package/Runtime/Tags/ModifierDurationType.cs.meta +3 -0
- package/Runtime/{Utils → Tags}/TagHandler.cs +42 -5
- package/Runtime/Tags.meta +3 -0
- package/Tests/Runtime/DataStructures/SpatialTreeTests.cs +1 -1
- package/Tests/Runtime/Helper/ObjectHelperTests.cs +1 -0
- package/package.json +1 -1
- /package/Runtime/{Utils → Tags}/TagHandler.cs.meta +0 -0
|
@@ -0,0 +1,379 @@
|
|
|
1
|
+
namespace WallstopStudios.UnityHelpers.Tags
|
|
2
|
+
{
|
|
3
|
+
using System.Collections.Generic;
|
|
4
|
+
using System.Linq;
|
|
5
|
+
using Core.Attributes;
|
|
6
|
+
using Core.DataStructure.Adapters;
|
|
7
|
+
using Core.Extension;
|
|
8
|
+
using Core.Helper;
|
|
9
|
+
using UnityEngine;
|
|
10
|
+
using Utils;
|
|
11
|
+
|
|
12
|
+
[DisallowMultipleComponent]
|
|
13
|
+
public sealed class EffectHandler : MonoBehaviour
|
|
14
|
+
{
|
|
15
|
+
[SiblingComponent(optional = true)]
|
|
16
|
+
private TagHandler _tagHandler;
|
|
17
|
+
|
|
18
|
+
[SiblingComponent(optional = true)]
|
|
19
|
+
private AttributesComponent[] _attributes;
|
|
20
|
+
|
|
21
|
+
// Stores instanced cosmetic effect data for associated effects.
|
|
22
|
+
private readonly Dictionary<
|
|
23
|
+
EffectHandle,
|
|
24
|
+
List<CosmeticEffectData>
|
|
25
|
+
> _instancedCosmeticEffects = new();
|
|
26
|
+
|
|
27
|
+
// Stores expiration time of duration effects (We store by Id because it's much cheaper to iterate Guids than it is EffectHandles
|
|
28
|
+
private readonly Dictionary<KGuid, float> _effectExpirations = new();
|
|
29
|
+
private readonly Dictionary<KGuid, EffectHandle> _effectHandlesById = new();
|
|
30
|
+
|
|
31
|
+
// Used only to save allocations in Update()
|
|
32
|
+
private readonly List<KGuid> _expiredEffectIds = new();
|
|
33
|
+
private readonly List<EffectHandle> _appliedEffects = new();
|
|
34
|
+
|
|
35
|
+
private bool _initialized;
|
|
36
|
+
|
|
37
|
+
private void Awake()
|
|
38
|
+
{
|
|
39
|
+
this.AssignRelationalComponents();
|
|
40
|
+
_initialized = true;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
public EffectHandle? ApplyEffect(AttributeEffect effect)
|
|
44
|
+
{
|
|
45
|
+
EffectHandle? maybeHandle = null;
|
|
46
|
+
|
|
47
|
+
if (effect.durationType != ModifierDurationType.Instant)
|
|
48
|
+
{
|
|
49
|
+
if (effect.durationType == ModifierDurationType.Duration)
|
|
50
|
+
{
|
|
51
|
+
foreach (EffectHandle appliedEffect in _appliedEffects)
|
|
52
|
+
{
|
|
53
|
+
if (appliedEffect.effect == null)
|
|
54
|
+
{
|
|
55
|
+
continue;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
string serializableName = appliedEffect.effect.name;
|
|
59
|
+
if (string.Equals(effect.name, serializableName))
|
|
60
|
+
{
|
|
61
|
+
maybeHandle = appliedEffect;
|
|
62
|
+
break;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
maybeHandle ??= EffectHandle.CreateInstance(effect);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
if (maybeHandle.HasValue)
|
|
71
|
+
{
|
|
72
|
+
EffectHandle handle = maybeHandle.Value;
|
|
73
|
+
InternalApplyEffect(handle);
|
|
74
|
+
if (
|
|
75
|
+
effect.durationType == ModifierDurationType.Duration
|
|
76
|
+
&& (effect.resetDurationOnReapplication || !_appliedEffects.Contains(handle))
|
|
77
|
+
)
|
|
78
|
+
{
|
|
79
|
+
KGuid handleId = handle.id;
|
|
80
|
+
_effectExpirations[handleId] = Time.time + effect.duration;
|
|
81
|
+
_effectHandlesById[handleId] = handle;
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
else
|
|
85
|
+
{
|
|
86
|
+
InternalApplyEffect(effect);
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
return maybeHandle;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
public void RemoveEffect(EffectHandle handle)
|
|
93
|
+
{
|
|
94
|
+
InternalRemoveEffect(handle);
|
|
95
|
+
_ = _appliedEffects.Remove(handle);
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
public void RemoveAllEffects()
|
|
99
|
+
{
|
|
100
|
+
foreach (EffectHandle handle in _appliedEffects.ToArray())
|
|
101
|
+
{
|
|
102
|
+
InternalRemoveEffect(handle);
|
|
103
|
+
}
|
|
104
|
+
_appliedEffects.Clear();
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
private void InternalRemoveEffect(EffectHandle handle)
|
|
108
|
+
{
|
|
109
|
+
foreach (AttributesComponent attributesComponent in _attributes)
|
|
110
|
+
{
|
|
111
|
+
attributesComponent.ForceRemoveAttributeModifications(handle);
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
if (!_initialized && _tagHandler == null)
|
|
115
|
+
{
|
|
116
|
+
this.AssignRelationalComponents();
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
// Then, tags are removed (so cosmetic components can look up if any tags are still applied)
|
|
120
|
+
if (_tagHandler != null)
|
|
121
|
+
{
|
|
122
|
+
_ = _tagHandler.ForceRemoveTags(handle);
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
KGuid handleId = handle.id;
|
|
126
|
+
_ = _effectExpirations.Remove(handleId);
|
|
127
|
+
_ = _effectHandlesById.Remove(handleId);
|
|
128
|
+
InternalRemoveCosmeticEffects(handle);
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
private void InternalApplyEffect(EffectHandle handle)
|
|
132
|
+
{
|
|
133
|
+
bool exists = _appliedEffects.Contains(handle);
|
|
134
|
+
if (!exists)
|
|
135
|
+
{
|
|
136
|
+
_appliedEffects.Add(handle);
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
AttributeEffect effect = handle.effect;
|
|
140
|
+
if (effect.durationType == ModifierDurationType.Duration)
|
|
141
|
+
{
|
|
142
|
+
if (effect.resetDurationOnReapplication || !exists)
|
|
143
|
+
{
|
|
144
|
+
KGuid handleId = handle.id;
|
|
145
|
+
_effectExpirations[handleId] = Time.time + effect.duration;
|
|
146
|
+
_effectHandlesById[handleId] = handle;
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
if (!_initialized && _tagHandler == null)
|
|
151
|
+
{
|
|
152
|
+
this.AssignRelationalComponents();
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
if (_tagHandler != null && effect.effectTags is { Count: > 0 })
|
|
156
|
+
{
|
|
157
|
+
_tagHandler.ForceApplyTags(handle);
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
if (effect.cosmeticEffects is { Count: > 0 })
|
|
161
|
+
{
|
|
162
|
+
InternalApplyCosmeticEffects(handle);
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
if (effect.modifications is { Count: > 0 })
|
|
166
|
+
{
|
|
167
|
+
foreach (AttributesComponent attributesComponent in _attributes)
|
|
168
|
+
{
|
|
169
|
+
attributesComponent.ForceApplyAttributeModifications(handle);
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
private void InternalApplyEffect(AttributeEffect effect)
|
|
175
|
+
{
|
|
176
|
+
if (!_initialized && _tagHandler == null)
|
|
177
|
+
{
|
|
178
|
+
this.AssignRelationalComponents();
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
if (_tagHandler != null && effect.effectTags is { Count: > 0 })
|
|
182
|
+
{
|
|
183
|
+
_tagHandler.ForceApplyEffect(effect);
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
if (effect.cosmeticEffects is { Count: > 0 })
|
|
187
|
+
{
|
|
188
|
+
InternalApplyCosmeticEffects(effect);
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
if (effect.modifications is { Count: > 0 })
|
|
192
|
+
{
|
|
193
|
+
foreach (AttributesComponent attributesComponent in _attributes)
|
|
194
|
+
{
|
|
195
|
+
attributesComponent.ForceApplyAttributeModifications(effect);
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
private void InternalApplyCosmeticEffects(EffectHandle handle)
|
|
201
|
+
{
|
|
202
|
+
if (_instancedCosmeticEffects.ContainsKey(handle))
|
|
203
|
+
{
|
|
204
|
+
return;
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
List<CosmeticEffectData> instancedCosmeticData = null;
|
|
208
|
+
|
|
209
|
+
AttributeEffect effect = handle.effect;
|
|
210
|
+
|
|
211
|
+
foreach (CosmeticEffectData cosmeticEffectData in effect.cosmeticEffects)
|
|
212
|
+
{
|
|
213
|
+
CosmeticEffectData cosmeticEffect = cosmeticEffectData;
|
|
214
|
+
if (cosmeticEffect == null)
|
|
215
|
+
{
|
|
216
|
+
this.LogError(
|
|
217
|
+
$"CosmeticEffectData is null for effect {effect:json}, cannot determine instancing scheme."
|
|
218
|
+
);
|
|
219
|
+
continue;
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
if (cosmeticEffectData.RequiresInstancing)
|
|
223
|
+
{
|
|
224
|
+
cosmeticEffect = Instantiate(
|
|
225
|
+
cosmeticEffectData,
|
|
226
|
+
transform.position,
|
|
227
|
+
Quaternion.identity
|
|
228
|
+
);
|
|
229
|
+
cosmeticEffect.transform.SetParent(transform, true);
|
|
230
|
+
(instancedCosmeticData ??= new List<CosmeticEffectData>()).Add(cosmeticEffect);
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
Buffers<CosmeticEffectComponent>.List.Clear();
|
|
234
|
+
cosmeticEffect.GetComponents(Buffers<CosmeticEffectComponent>.List);
|
|
235
|
+
foreach (
|
|
236
|
+
CosmeticEffectComponent cosmeticComponent in Buffers<CosmeticEffectComponent>.List
|
|
237
|
+
)
|
|
238
|
+
{
|
|
239
|
+
cosmeticComponent.OnApplyEffect(gameObject);
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
if (instancedCosmeticData != null)
|
|
244
|
+
{
|
|
245
|
+
_instancedCosmeticEffects.Add(handle, instancedCosmeticData);
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
private void InternalApplyCosmeticEffects(AttributeEffect attributeEffect)
|
|
250
|
+
{
|
|
251
|
+
foreach (CosmeticEffectData cosmeticEffectData in attributeEffect.cosmeticEffects)
|
|
252
|
+
{
|
|
253
|
+
CosmeticEffectData cosmeticEffect = cosmeticEffectData;
|
|
254
|
+
if (cosmeticEffect == null)
|
|
255
|
+
{
|
|
256
|
+
this.LogError(
|
|
257
|
+
$"CosmeticEffectData is null for effect {attributeEffect:json}, cannot determine instancing scheme."
|
|
258
|
+
);
|
|
259
|
+
continue;
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
if (cosmeticEffectData.RequiresInstancing)
|
|
263
|
+
{
|
|
264
|
+
this.LogError(
|
|
265
|
+
$"CosmeticEffectData requires instancing, but can't instance (no handle)."
|
|
266
|
+
);
|
|
267
|
+
continue;
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
Buffers<CosmeticEffectComponent>.List.Clear();
|
|
271
|
+
cosmeticEffect.GetComponents(Buffers<CosmeticEffectComponent>.List);
|
|
272
|
+
foreach (
|
|
273
|
+
CosmeticEffectComponent cosmeticComponent in Buffers<CosmeticEffectComponent>.List
|
|
274
|
+
)
|
|
275
|
+
{
|
|
276
|
+
cosmeticComponent.OnApplyEffect(gameObject);
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
private void InternalRemoveCosmeticEffects(EffectHandle handle)
|
|
282
|
+
{
|
|
283
|
+
if (
|
|
284
|
+
!_instancedCosmeticEffects.TryGetValue(
|
|
285
|
+
handle,
|
|
286
|
+
out List<CosmeticEffectData> cosmeticDatas
|
|
287
|
+
)
|
|
288
|
+
)
|
|
289
|
+
{
|
|
290
|
+
// If we don't have instanced cosmetic effects, then they were applied directly to the cosmetic data
|
|
291
|
+
foreach (
|
|
292
|
+
CosmeticEffectData cosmeticEffectData in handle.effect.cosmeticEffects
|
|
293
|
+
?? Enumerable.Empty<CosmeticEffectData>()
|
|
294
|
+
)
|
|
295
|
+
{
|
|
296
|
+
if (cosmeticEffectData.RequiresInstancing)
|
|
297
|
+
{
|
|
298
|
+
this.LogWarn(
|
|
299
|
+
$"Double-deregistration detected for handle {handle:json}. Existing handles: [{(string.Join(",", _instancedCosmeticEffects.Keys))}]."
|
|
300
|
+
);
|
|
301
|
+
continue;
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
Buffers<CosmeticEffectComponent>.List.Clear();
|
|
305
|
+
cosmeticEffectData.GetComponents(Buffers<CosmeticEffectComponent>.List);
|
|
306
|
+
foreach (
|
|
307
|
+
CosmeticEffectComponent cosmeticComponent in Buffers<CosmeticEffectComponent>.List
|
|
308
|
+
)
|
|
309
|
+
{
|
|
310
|
+
cosmeticComponent.OnRemoveEffect(gameObject);
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
return;
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
foreach (
|
|
318
|
+
CosmeticEffectComponent cosmeticComponent in cosmeticDatas.SelectMany(
|
|
319
|
+
cosmeticData => cosmeticData.GetComponents<CosmeticEffectComponent>()
|
|
320
|
+
)
|
|
321
|
+
)
|
|
322
|
+
{
|
|
323
|
+
cosmeticComponent.OnRemoveEffect(gameObject);
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
foreach (CosmeticEffectData data in cosmeticDatas)
|
|
327
|
+
{
|
|
328
|
+
bool shouldDestroyGameObject = true;
|
|
329
|
+
Buffers<CosmeticEffectComponent>.List.Clear();
|
|
330
|
+
data.GetComponents(Buffers<CosmeticEffectComponent>.List);
|
|
331
|
+
foreach (
|
|
332
|
+
CosmeticEffectComponent cosmeticEffect in Buffers<CosmeticEffectComponent>.List
|
|
333
|
+
)
|
|
334
|
+
{
|
|
335
|
+
if (cosmeticEffect.CleansUpSelf)
|
|
336
|
+
{
|
|
337
|
+
shouldDestroyGameObject = false;
|
|
338
|
+
continue;
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
cosmeticEffect.Destroy();
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
if (shouldDestroyGameObject)
|
|
345
|
+
{
|
|
346
|
+
data.gameObject.Destroy();
|
|
347
|
+
}
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
_ = _instancedCosmeticEffects.Remove(handle);
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
private void Update()
|
|
354
|
+
{
|
|
355
|
+
if (_effectExpirations.Count <= 0)
|
|
356
|
+
{
|
|
357
|
+
return;
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
_expiredEffectIds.Clear();
|
|
361
|
+
float currentTime = Time.time;
|
|
362
|
+
foreach (KeyValuePair<KGuid, float> entry in _effectExpirations)
|
|
363
|
+
{
|
|
364
|
+
if (entry.Value < currentTime)
|
|
365
|
+
{
|
|
366
|
+
_expiredEffectIds.Add(entry.Key);
|
|
367
|
+
}
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
foreach (KGuid expiredHandleId in _expiredEffectIds)
|
|
371
|
+
{
|
|
372
|
+
if (_effectHandlesById.TryGetValue(expiredHandleId, out EffectHandle expiredHandle))
|
|
373
|
+
{
|
|
374
|
+
RemoveEffect(expiredHandle);
|
|
375
|
+
}
|
|
376
|
+
}
|
|
377
|
+
}
|
|
378
|
+
}
|
|
379
|
+
}
|
|
@@ -1,21 +1,23 @@
|
|
|
1
|
-
namespace WallstopStudios.UnityHelpers.
|
|
1
|
+
namespace WallstopStudios.UnityHelpers.Tags
|
|
2
2
|
{
|
|
3
3
|
using System;
|
|
4
4
|
using System.Collections.Generic;
|
|
5
|
+
using Core.DataStructure.Adapters;
|
|
5
6
|
using Core.Extension;
|
|
6
7
|
using UnityEngine;
|
|
7
8
|
|
|
8
9
|
[DisallowMultipleComponent]
|
|
9
|
-
public class TagHandler : MonoBehaviour
|
|
10
|
+
public sealed class TagHandler : MonoBehaviour
|
|
10
11
|
{
|
|
11
12
|
public IReadOnlyCollection<string> Tags => _tagCount.Keys;
|
|
12
13
|
|
|
13
14
|
[SerializeField]
|
|
14
|
-
|
|
15
|
+
private List<string> _initialEffectTags = new();
|
|
15
16
|
|
|
16
|
-
|
|
17
|
+
private readonly Dictionary<string, uint> _tagCount = new(StringComparer.Ordinal);
|
|
18
|
+
private readonly Dictionary<KGuid, EffectHandle> _effectHandles = new();
|
|
17
19
|
|
|
18
|
-
|
|
20
|
+
private void Awake()
|
|
19
21
|
{
|
|
20
22
|
if (_initialEffectTags is { Count: > 0 })
|
|
21
23
|
{
|
|
@@ -74,6 +76,41 @@
|
|
|
74
76
|
InternalRemoveTag(effectTag);
|
|
75
77
|
}
|
|
76
78
|
|
|
79
|
+
public void ForceApplyTags(EffectHandle handle)
|
|
80
|
+
{
|
|
81
|
+
KGuid id = handle.id;
|
|
82
|
+
if (!_effectHandles.TryAdd(id, handle))
|
|
83
|
+
{
|
|
84
|
+
return;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
ForceApplyEffect(handle.effect);
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
public void ForceApplyEffect(AttributeEffect effect)
|
|
91
|
+
{
|
|
92
|
+
foreach (string effectTag in effect.effectTags)
|
|
93
|
+
{
|
|
94
|
+
InternalApplyTag(effectTag);
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
public bool ForceRemoveTags(EffectHandle handle)
|
|
99
|
+
{
|
|
100
|
+
KGuid id = handle.id;
|
|
101
|
+
if (!_effectHandles.Remove(id, out EffectHandle appliedHandle))
|
|
102
|
+
{
|
|
103
|
+
return false;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
foreach (string effectTag in appliedHandle.effect.effectTags)
|
|
107
|
+
{
|
|
108
|
+
InternalRemoveTag(effectTag);
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
return true;
|
|
112
|
+
}
|
|
113
|
+
|
|
77
114
|
private void InternalApplyTag(string effectTag)
|
|
78
115
|
{
|
|
79
116
|
_ = _tagCount.AddOrUpdate(effectTag, _ => 1U, (_, existing) => existing + 1);
|
|
@@ -2,8 +2,8 @@
|
|
|
2
2
|
{
|
|
3
3
|
using System.Collections.Generic;
|
|
4
4
|
using System.Linq;
|
|
5
|
+
using Core.DataStructure;
|
|
5
6
|
using NUnit.Framework;
|
|
6
|
-
using WallstopStudios.UnityHelpers.Core.DataStructure;
|
|
7
7
|
using WallstopStudios.UnityHelpers.Core.Helper;
|
|
8
8
|
using WallstopStudios.UnityHelpers.Core.Random;
|
|
9
9
|
using Vector2 = UnityEngine.Vector2;
|
package/package.json
CHANGED
|
File without changes
|