Skip to content

Commit 37b442b

Browse files
authored
Merge pull request #3 from gamesmiths-guild/feature/csharp-record
Refactor immutable structs into record types.
2 parents af6fb79 + 10c6adc commit 37b442b

33 files changed

+265
-1552
lines changed

Forge.Tests/Core/Curve.cs

Lines changed: 3 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,10 @@ namespace Gamesmiths.Forge.Tests.Core;
77
/// <summary>
88
/// Initializes a new instance of the <see cref="Curve"/> class.
99
/// </summary>
10-
/// <param name="keys">The keys for the curve.</param>
11-
public readonly struct Curve(CurveKey[] keys) : ICurve, IEquatable<Curve>
10+
/// <param name="Keys">The keys for the curve.</param>
11+
public readonly record struct Curve(CurveKey[] Keys) : ICurve
1212
{
13-
private readonly CurveKey[] _keys = [.. keys.OrderBy(x => x.Time)];
13+
private readonly CurveKey[] _keys = [.. Keys.OrderBy(x => x.Time)];
1414

1515
/// <summary>
1616
/// Evaluates the curve at a given time.
@@ -47,62 +47,4 @@ public float Evaluate(float value)
4747
// Fallback.
4848
return 1.0f;
4949
}
50-
51-
/// <inheritdoc/>
52-
public override int GetHashCode()
53-
{
54-
var hash = default(HashCode);
55-
foreach (CurveKey key in _keys)
56-
{
57-
hash.Add(key);
58-
}
59-
60-
return hash.ToHashCode();
61-
}
62-
63-
/// <inheritdoc/>
64-
public override bool Equals(object? obj)
65-
{
66-
if (obj is Curve other)
67-
{
68-
return Equals(other);
69-
}
70-
71-
return false;
72-
}
73-
74-
/// <inheritdoc/>
75-
public bool Equals(Curve other)
76-
{
77-
if (_keys is null)
78-
{
79-
return other._keys is null;
80-
}
81-
82-
return _keys.SequenceEqual(other._keys);
83-
}
84-
85-
/// <summary>
86-
/// Determines if two <see cref="Curve"/> objects are equal.
87-
/// </summary>
88-
/// <param name="lhs">The first <see cref="Curve"/> to compare.</param>
89-
/// <param name="rhs">The second <see cref="Curve"/> to compare.</param>
90-
/// <returns><see langword="true"/> if the values of <paramref name="lhs"/> and <paramref name="rhs"/> are equal;
91-
/// otherwise, <see langword="false"/>.</returns>
92-
public static bool operator ==(Curve lhs, Curve rhs)
93-
{
94-
return lhs.Equals(rhs);
95-
}
96-
97-
/// <summary>
98-
/// Determines if two <see cref="Curve"/> objects are not equal.
99-
/// </summary>
100-
/// <param name="lhs">The first <see cref="Curve"/> to compare.</param>
101-
/// <param name="rhs">The second <see cref="Curve"/> to compare.</param>
102-
/// <returns><see langword="true"/> if the values of <paramref name="lhs"/> and <paramref name="rhs"/> are not
103-
/// equal; otherwise, <see langword="false"/>.</returns>
104-
public static bool operator !=(Curve lhs, Curve rhs)
105-
{
106-
return !(lhs == rhs);
107-
}
10850
}

Forge.Tests/Core/CurveKey.cs

Lines changed: 4 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -1,74 +1,10 @@
11
// Copyright © Gamesmiths Guild.
22

3-
namespace Gamesmiths.Forge.Core;
3+
namespace Gamesmiths.Forge.Tests.Core;
44

55
/// <summary>
66
/// Represents a key into a <see cref="Curve"/>.
77
/// </summary>
8-
/// <param name="time">The time of the curve key.</param>
9-
/// <param name="value">The value of the curve key.</param>
10-
public readonly struct CurveKey(float time, float value) : IEquatable<CurveKey>
11-
{
12-
/// <summary>
13-
/// Gets the time of this curve key.
14-
/// </summary>
15-
public float Time { get; } = time;
16-
17-
/// <summary>
18-
/// Gets the value of this curve key.
19-
/// </summary>
20-
public float Value { get; } = value;
21-
22-
/// <inheritdoc/>
23-
public override int GetHashCode()
24-
{
25-
var hash = default(HashCode);
26-
hash.Add(Time);
27-
hash.Add(Value);
28-
return hash.ToHashCode();
29-
}
30-
31-
/// <inheritdoc/>
32-
public override bool Equals(object? obj)
33-
{
34-
if (obj is CurveKey other)
35-
{
36-
return Equals(other);
37-
}
38-
39-
return false;
40-
}
41-
42-
/// <inheritdoc/>
43-
public bool Equals(CurveKey other)
44-
{
45-
#pragma warning disable S1244 // Floating point numbers should not be tested for equality
46-
return Time == other.Time
47-
&& Value.Equals(other.Value);
48-
#pragma warning restore S1244 // Floating point numbers should not be tested for equality
49-
}
50-
51-
/// <summary>
52-
/// Determines if two <see cref="CurveKey"/> objects are equal.
53-
/// </summary>
54-
/// <param name="lhs">The first <see cref="CurveKey"/> to compare.</param>
55-
/// <param name="rhs">The second <see cref="CurveKey"/> to compare.</param>
56-
/// <returns><see langword="true"/> if the values of <paramref name="lhs"/> and <paramref name="rhs"/> are equal;
57-
/// otherwise, <see langword="false"/>.</returns>
58-
public static bool operator ==(CurveKey lhs, CurveKey rhs)
59-
{
60-
return lhs.Equals(rhs);
61-
}
62-
63-
/// <summary>
64-
/// Determines if two <see cref="CurveKey"/> objects are not equal.
65-
/// </summary>
66-
/// <param name="lhs">The first <see cref="CurveKey"/> to compare.</param>
67-
/// <param name="rhs">The second <see cref="CurveKey"/> to compare.</param>
68-
/// <returns><see langword="true"/> if the values of <paramref name="lhs"/> and <paramref name="rhs"/> are not
69-
/// equal; otherwise, <see langword="false"/>.</returns>
70-
public static bool operator !=(CurveKey lhs, CurveKey rhs)
71-
{
72-
return !(lhs == rhs);
73-
}
74-
}
8+
/// <param name="Time">The time of the curve key.</param>
9+
/// <param name="Value">The value of the curve key.</param>
10+
public readonly record struct CurveKey(float Time, float Value);

Forge.Tests/Cues/CueTests.cs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2456,10 +2456,10 @@ private static EffectData CreateDurationStackableEffectData(
24562456
StackMagnitudePolicy.Sum,
24572457
StackOverflowPolicy.AllowApplication,
24582458
StackExpirationPolicy.RemoveSingleStackAndRefreshDuration,
2459-
levelDenialPolicy: LevelComparison.None,
2460-
levelOverridePolicy: LevelComparison.Lower | LevelComparison.Equal | LevelComparison.Higher,
2461-
levelOverrideStackCountPolicy: StackLevelOverrideStackCountPolicy.IncreaseStacks,
2462-
applicationRefreshPolicy: StackApplicationRefreshPolicy.RefreshOnSuccessfulApplication),
2459+
LevelDenialPolicy: LevelComparison.None,
2460+
LevelOverridePolicy: LevelComparison.Lower | LevelComparison.Equal | LevelComparison.Higher,
2461+
LevelOverrideStackCountPolicy: StackLevelOverrideStackCountPolicy.IncreaseStacks,
2462+
ApplicationRefreshPolicy: StackApplicationRefreshPolicy.RefreshOnSuccessfulApplication),
24632463
snapshopLevel: false,
24642464
requireModifierSuccessToTriggerCue: requireModifierSuccessToTriggerCue,
24652465
suppressStackingCues: suppressStackingCues,

Forge.Tests/Effects/EffectsTests.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -138,7 +138,7 @@ public void Attribute_based_effect_with_curve_modifies_values_based_on_curve_loo
138138
new ScalableFloat(coefficient),
139139
new ScalableFloat(preMultiplyAdditiveValue),
140140
new ScalableFloat(postMultiplyAdditiveValue),
141-
lookupCurve: new Curve(
141+
LookupCurve: new Curve(
142142
[
143143
new CurveKey(6, 4),
144144
new CurveKey(8, 3),

Forge.Tests/Effects/TargetTagRequirementsComponentTests.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -348,7 +348,7 @@ public void Effect_meets_application_requirements_with_query()
348348
new DurationData(DurationType.Infinite),
349349
effectComponents:
350350
[
351-
new TargetTagRequirementsEffectComponent(new TagRequirements(tagQuery: query))
351+
new TargetTagRequirementsEffectComponent(new TagRequirements(TagQuery: query))
352352
]);
353353

354354
var effect = new Effect(effectData, new EffectOwnership(entity, entity));
@@ -391,7 +391,7 @@ public void Effect_does_not_meet_application_requirements_with_query()
391391
new DurationData(DurationType.Infinite),
392392
effectComponents:
393393
[
394-
new TargetTagRequirementsEffectComponent(new TagRequirements(tagQuery: query))
394+
new TargetTagRequirementsEffectComponent(new TagRequirements(TagQuery: query))
395395
]);
396396

397397
var effect = new Effect(effectData, new EffectOwnership(entity, entity));

Forge.Tests/Samples/QuickStartTests.cs

Lines changed: 49 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -239,9 +239,9 @@ public void Periodic_effect_example()
239239
)
240240
},
241241
periodicData: new PeriodicData(
242-
period: new ScalableFloat(2.0f),
243-
executeOnApplication: true,
244-
periodInhibitionRemovedPolicy: PeriodInhibitionRemovedPolicy.ResetPeriod
242+
Period: new ScalableFloat(2.0f),
243+
ExecuteOnApplication: true,
244+
PeriodInhibitionRemovedPolicy: PeriodInhibitionRemovedPolicy.ResetPeriod
245245
)
246246
);
247247

@@ -282,23 +282,23 @@ public void Stacking_poison_effect_example()
282282
)
283283
},
284284
periodicData: new PeriodicData(
285-
period: new ScalableFloat(2.0f),
286-
executeOnApplication: false,
287-
periodInhibitionRemovedPolicy: PeriodInhibitionRemovedPolicy.ResetPeriod
285+
Period: new ScalableFloat(2.0f),
286+
ExecuteOnApplication: false,
287+
PeriodInhibitionRemovedPolicy: PeriodInhibitionRemovedPolicy.ResetPeriod
288288
),
289289
stackingData: new StackingData(
290-
stackLimit: new ScalableInt(3), // Max 3 stacks
291-
initialStack: new ScalableInt(1), // Starts with 1 stack
292-
overflowPolicy: StackOverflowPolicy.DenyApplication, // Deny if max stacks reached
293-
magnitudePolicy: StackMagnitudePolicy.Sum, // Total damage increases with stacks
294-
expirationPolicy: StackExpirationPolicy.ClearEntireStack, // All stacks expire together
295-
applicationRefreshPolicy: StackApplicationRefreshPolicy.RefreshOnSuccessfulApplication,
296-
stackPolicy: StackPolicy.AggregateBySource, // Aggregate stacks from the same source
297-
stackLevelPolicy: StackLevelPolicy.SegregateLevels, // Each stack can have its own level
290+
StackLimit: new ScalableInt(3), // Max 3 stacks
291+
InitialStack: new ScalableInt(1), // Starts with 1 stack
292+
OverflowPolicy: StackOverflowPolicy.DenyApplication, // Deny if max stacks reached
293+
MagnitudePolicy: StackMagnitudePolicy.Sum, // Total damage increases with stacks
294+
ExpirationPolicy: StackExpirationPolicy.ClearEntireStack, // All stacks expire together
295+
ApplicationRefreshPolicy: StackApplicationRefreshPolicy.RefreshOnSuccessfulApplication,
296+
StackPolicy: StackPolicy.AggregateBySource, // Aggregate stacks from the same source
297+
StackLevelPolicy: StackLevelPolicy.SegregateLevels, // Each stack can have its own level
298298

299299
// The next two values must be defined because this is a periodic effect with stacking
300-
executeOnSuccessfulApplication: false, // Do not execute on successful application
301-
applicationResetPeriodPolicy: StackApplicationResetPeriodPolicy.ResetOnSuccessfulApplication
300+
ExecuteOnSuccessfulApplication: false, // Do not execute on successful application
301+
ApplicationResetPeriodPolicy: StackApplicationResetPeriodPolicy.ResetOnSuccessfulApplication
302302
)
303303
);
304304

@@ -351,20 +351,20 @@ public void Unique_effect_example()
351351
)
352352
},
353353
stackingData: new StackingData(
354-
stackLimit: new ScalableInt(1), // Only 1 instance allowed
355-
initialStack: new ScalableInt(1), // Starts with 1 stack
356-
overflowPolicy: StackOverflowPolicy.AllowApplication, // Allow application even if max stacks reached
357-
magnitudePolicy: StackMagnitudePolicy.Sum, // Total damage increases with stacks
358-
expirationPolicy: StackExpirationPolicy.ClearEntireStack, // All stacks expire together
359-
applicationRefreshPolicy: StackApplicationRefreshPolicy.RefreshOnSuccessfulApplication,
360-
stackPolicy: StackPolicy.AggregateByTarget, // Only one effect per target
361-
ownerDenialPolicy: StackOwnerDenialPolicy.AlwaysAllow, // Always allow application regardless of owner
362-
ownerOverridePolicy: StackOwnerOverridePolicy.Override, // Override existing effect if applied again
363-
ownerOverrideStackCountPolicy: StackOwnerOverrideStackCountPolicy.ResetStacks,
364-
stackLevelPolicy: StackLevelPolicy.AggregateLevels, // Aggregate levels of the effect
365-
levelOverridePolicy: LevelComparison.Equal | LevelComparison.Higher,
366-
levelDenialPolicy: LevelComparison.Lower, // Deny lower-level effects
367-
levelOverrideStackCountPolicy: StackLevelOverrideStackCountPolicy.ResetStacks
354+
StackLimit: new ScalableInt(1), // Only 1 instance allowed
355+
InitialStack: new ScalableInt(1), // Starts with 1 stack
356+
OverflowPolicy: StackOverflowPolicy.AllowApplication, // Allow application even if max stacks reached
357+
MagnitudePolicy: StackMagnitudePolicy.Sum, // Total damage increases with stacks
358+
ExpirationPolicy: StackExpirationPolicy.ClearEntireStack, // All stacks expire together
359+
ApplicationRefreshPolicy: StackApplicationRefreshPolicy.RefreshOnSuccessfulApplication,
360+
StackPolicy: StackPolicy.AggregateByTarget, // Only one effect per target
361+
OwnerDenialPolicy: StackOwnerDenialPolicy.AlwaysAllow, // Always allow application regardless of owner
362+
OwnerOverridePolicy: StackOwnerOverridePolicy.Override, // Override existing effect if applied again
363+
OwnerOverrideStackCountPolicy: StackOwnerOverrideStackCountPolicy.ResetStacks,
364+
StackLevelPolicy: StackLevelPolicy.AggregateLevels, // Aggregate levels of the effect
365+
LevelOverridePolicy: LevelComparison.Equal | LevelComparison.Higher,
366+
LevelDenialPolicy: LevelComparison.Lower, // Deny lower-level effects
367+
LevelOverrideStackCountPolicy: StackLevelOverrideStackCountPolicy.ResetStacks
368368
)
369369
);
370370

@@ -456,7 +456,7 @@ public void Preventing_effect_application_based_on_tags()
456456
new TargetTagRequirementsEffectComponent(
457457
applicationTagRequirements: new TagRequirements(
458458
// Prevent application if target has "status.immune.fire"
459-
ignoreTags: tagsManager.RequestTagContainer(new[] { "status.immune.fire" })
459+
IgnoreTags: tagsManager.RequestTagContainer(new[] { "status.immune.fire" })
460460
)
461461
)
462462
}
@@ -638,17 +638,17 @@ public void Triggering_a_cue_through_effects()
638638
)
639639
},
640640
periodicData: new PeriodicData(
641-
period: new ScalableFloat(1.0f), // Ticks every second
642-
executeOnApplication: true,
643-
periodInhibitionRemovedPolicy: PeriodInhibitionRemovedPolicy.ResetPeriod
641+
Period: new ScalableFloat(1.0f), // Ticks every second
642+
ExecuteOnApplication: true,
643+
PeriodInhibitionRemovedPolicy: PeriodInhibitionRemovedPolicy.ResetPeriod
644644
),
645645
cues: new[] {
646646
new CueData(
647-
cueTags: tagsManager.RequestTagContainer(new[] { "cues.damage.fire" }),
648-
minValue: 0,
649-
maxValue: 100,
650-
magnitudeType: CueMagnitudeType.AttributeValueChange,
651-
magnitudeAttribute: "PlayerAttributeSet.Health" // Tracks health changes
647+
CueTags: tagsManager.RequestTagContainer(new[] { "cues.damage.fire" }),
648+
MinValue: 0,
649+
MaxValue: 100,
650+
MagnitudeType: CueMagnitudeType.AttributeValueChange,
651+
MagnitudeAttribute: "PlayerAttributeSet.Health" // Tracks health changes
652652
)
653653
}
654654
);
@@ -700,10 +700,10 @@ public void Manually_triggering_a_cue()
700700

701701
// Manually trigger a fire damage cue
702702
var parameters = new CueParameters(
703-
magnitude: 25, // Raw damage value
704-
normalizedMagnitude: 0.25f, // Normalized between 0-1
705-
source: player,
706-
customParameters: new Dictionary<StringKey, object>
703+
Magnitude: 25, // Raw damage value
704+
NormalizedMagnitude: 0.25f, // Normalized between 0-1
705+
Source: player,
706+
CustomParameters: new Dictionary<StringKey, object>
707707
{
708708
{ "DamageType", "Fire" },
709709
{ "IsCritical", true }
@@ -797,12 +797,12 @@ public StrengthDamageCalculator()
797797
StrengthAttribute = new AttributeCaptureDefinition(
798798
"PlayerAttributeSet.Strength",
799799
AttributeCaptureSource.Source,
800-
snapshot: true);
800+
Snapshot: true);
801801

802802
SpeedAttribute = new AttributeCaptureDefinition(
803803
"PlayerAttributeSet.Speed",
804804
AttributeCaptureSource.Source,
805-
snapshot: true);
805+
Snapshot: true);
806806

807807
AttributesToCapture.Add(StrengthAttribute);
808808
AttributesToCapture.Add(SpeedAttribute);
@@ -833,17 +833,17 @@ public HealthDrainExecution()
833833
TargetHealth = new AttributeCaptureDefinition(
834834
"PlayerAttributeSet.Health",
835835
AttributeCaptureSource.Target,
836-
snapshot: false);
836+
Snapshot: false);
837837

838838
SourceHealth = new AttributeCaptureDefinition(
839839
"PlayerAttributeSet.Health",
840840
AttributeCaptureSource.Source,
841-
snapshot: false);
841+
Snapshot: false);
842842

843843
SourceStrength = new AttributeCaptureDefinition(
844844
"PlayerAttributeSet.Strength",
845845
AttributeCaptureSource.Source,
846-
snapshot: false);
846+
Snapshot: false);
847847

848848
// Register attributes for capture
849849
AttributesToCapture.Add(TargetHealth);
@@ -922,7 +922,7 @@ public void OnUpdate(IForgeEntity? target, CueParameters? parameters)
922922
// Logic for updating persistent cues (e.g., adjust fire intensity)
923923
if (parameters.HasValue)
924924
{
925-
Console.WriteLine($"Fire damage cue updated with magnitude: {parameters.Value.Magnitude}");
925+
Console.WriteLine($"Fire damage cue updated with Magnitude: {parameters.Value.Magnitude}");
926926
}
927927
}
928928
}

0 commit comments

Comments
 (0)