diff --git a/src/Application/GunGames/GunGame.cs b/src/Application/GunGames/GunGame.cs index 59702443..f5c4dce5 100644 --- a/src/Application/GunGames/GunGame.cs +++ b/src/Application/GunGames/GunGame.cs @@ -9,7 +9,7 @@ /// the final kill. /// public readonly struct GunGame( - WeaponProgression weaponProgression, + ActiveWeaponProgression weaponProgression, KillsRequiredPerLevel killsRequiredPerLevel) { diff --git a/src/Application/GunGames/GunGameSystem.cs b/src/Application/GunGames/GunGameSystem.cs index 6f555300..4c46ff25 100644 --- a/src/Application/GunGames/GunGameSystem.cs +++ b/src/Application/GunGames/GunGameSystem.cs @@ -5,7 +5,7 @@ public class GunGameSystem( IWorldService worldService, IDialogService dialogService, FrozenDictionary handlers, - WeaponProgression weaponProgression, + ActiveWeaponProgression weaponProgression, GunGameSession gunGameSession, GunGameReward gunGameReward) : ISystem, IGunGameMode { diff --git a/src/Application/GunGames/GunGameWeaponEnforcer.cs b/src/Application/GunGames/GunGameWeaponEnforcer.cs index dc7a48bf..b37a44fa 100644 --- a/src/Application/GunGames/GunGameWeaponEnforcer.cs +++ b/src/Application/GunGames/GunGameWeaponEnforcer.cs @@ -8,7 +8,7 @@ namespace CTF.Application.GunGames; /// public class GunGameWeaponEnforcer( IGunGameMode gunGameMode, - WeaponProgression weaponProgression) : ISystem + ActiveWeaponProgression weaponProgression) : ISystem { [Event] public void OnPlayerUpdate(Player player, TimePoint _) diff --git a/src/Application/GunGames/Results/PlayerLeveledDown.cs b/src/Application/GunGames/Results/PlayerLeveledDown.cs index 53b3cc42..eb5bbf2b 100644 --- a/src/Application/GunGames/Results/PlayerLeveledDown.cs +++ b/src/Application/GunGames/Results/PlayerLeveledDown.cs @@ -5,7 +5,7 @@ /// public class PlayerLeveledDown( IWorldService worldService, - WeaponProgression weaponProgression) : IGunGameResultHandler + ActiveWeaponProgression weaponProgression) : IGunGameResultHandler { public GunGameResult Result => GunGameResult.LeveledDown; diff --git a/src/Application/GunGames/Results/PlayerLeveledUp.cs b/src/Application/GunGames/Results/PlayerLeveledUp.cs index ee3dfdcb..14c2df6b 100644 --- a/src/Application/GunGames/Results/PlayerLeveledUp.cs +++ b/src/Application/GunGames/Results/PlayerLeveledUp.cs @@ -5,7 +5,7 @@ /// public class PlayerLeveledUp( IWorldService worldService, - WeaponProgression weaponProgression) : IGunGameResultHandler + ActiveWeaponProgression weaponProgression) : IGunGameResultHandler { public GunGameResult Result => GunGameResult.LeveledUp; diff --git a/src/Application/GunGames/Results/PlayerReachedFinalLevel.cs b/src/Application/GunGames/Results/PlayerReachedFinalLevel.cs index 62b5a4c5..2601fdc6 100644 --- a/src/Application/GunGames/Results/PlayerReachedFinalLevel.cs +++ b/src/Application/GunGames/Results/PlayerReachedFinalLevel.cs @@ -5,7 +5,7 @@ /// public class PlayerReachedFinalLevel( IWorldService worldService, - WeaponProgression weaponProgression) : IGunGameResultHandler + ActiveWeaponProgression weaponProgression) : IGunGameResultHandler { public GunGameResult Result => GunGameResult.ReachedFinalLevel; public void Handle(KillContext context) diff --git a/src/Application/GunGames/ServiceCollectionExtensions.cs b/src/Application/GunGames/ServiceCollectionExtensions.cs index 0965c859..e3809765 100644 --- a/src/Application/GunGames/ServiceCollectionExtensions.cs +++ b/src/Application/GunGames/ServiceCollectionExtensions.cs @@ -7,7 +7,7 @@ public static IServiceCollection AddGunGameServices(this IServiceCollection serv services .AddSingleton() .AddSingleton() - .AddSingleton() + .AddSingleton() .AddSingleton(sp => sp.GetRequiredService()); services @@ -21,7 +21,7 @@ public static IServiceCollection AddGunGameServices(this IServiceCollection serv .AddWeaponProgression() .AddSingleton(sp => { - var progressions = sp.GetRequiredService>(); + var progressions = sp.GetRequiredService>(); return progressions.ToFrozenDictionary(w => w.Type); }); @@ -40,9 +40,9 @@ public static IServiceCollection AddGunGameServices(this IServiceCollection serv } private static IServiceCollection AddWeaponProgression(this IServiceCollection services) - where T : WeaponProgressionBase + where T : WeaponProgression { - services.AddSingleton(); + services.AddSingleton(); return services; } diff --git a/src/Application/GunGames/WeaponProgressions/ActiveWeaponProgression.cs b/src/Application/GunGames/WeaponProgressions/ActiveWeaponProgression.cs new file mode 100644 index 00000000..295ae750 --- /dev/null +++ b/src/Application/GunGames/WeaponProgressions/ActiveWeaponProgression.cs @@ -0,0 +1,28 @@ +namespace CTF.Application.GunGames.WeaponProgressions; + +/// +/// Represents the active weapon progression for the current GunGame session. +/// +/// +/// Consumers do not need to know which weapon progression is active. +/// This class always exposes the progression selected for the current session. +/// +public class ActiveWeaponProgression( + GunGameSession gunGameSession, + FrozenDictionary progressions) +{ + private WeaponProgression Current + => progressions[gunGameSession.WeaponProgressionType]; + + /// + public IWeapon GetWeapon(WeaponLevel level) + => Current.GetWeapon(level); + + /// + public bool IsFinalLevel(WeaponLevel level) + => Current.IsFinalLevel(level); + + /// + public MaxWeaponLevel MaxLevel + => Current.MaxLevel; +} diff --git a/src/Application/GunGames/WeaponProgressions/Definitions/ClassicWeaponProgression.cs b/src/Application/GunGames/WeaponProgressions/Definitions/ClassicWeaponProgression.cs index 0fd648c1..d7b19613 100644 --- a/src/Application/GunGames/WeaponProgressions/Definitions/ClassicWeaponProgression.cs +++ b/src/Application/GunGames/WeaponProgressions/Definitions/ClassicWeaponProgression.cs @@ -1,11 +1,11 @@ namespace CTF.Application.GunGames.WeaponProgressions.Definitions; /// -/// Defines the default GunGame weapon progression, +/// Defines the classic GunGame weapon progression, /// where players advance through increasingly challenging /// weapons until reaching the final knife level. /// -public class ClassicWeaponProgression : WeaponProgressionBase +public class ClassicWeaponProgression : WeaponProgression { public override WeaponProgressionType Type => WeaponProgressionType.Classic; diff --git a/src/Application/GunGames/WeaponProgressions/Definitions/HardcoreWeaponProgression.cs b/src/Application/GunGames/WeaponProgressions/Definitions/HardcoreWeaponProgression.cs index e4d4dd52..431cb255 100644 --- a/src/Application/GunGames/WeaponProgressions/Definitions/HardcoreWeaponProgression.cs +++ b/src/Application/GunGames/WeaponProgressions/Definitions/HardcoreWeaponProgression.cs @@ -3,7 +3,7 @@ /// /// Defines a GunGame weapon progression using only high-skill weapons. /// -public class HardcoreWeaponProgression : WeaponProgressionBase +public class HardcoreWeaponProgression : WeaponProgression { public override WeaponProgressionType Type => WeaponProgressionType.Hardcore; diff --git a/src/Application/GunGames/WeaponProgressions/Definitions/PistolsWeaponProgression.cs b/src/Application/GunGames/WeaponProgressions/Definitions/PistolsWeaponProgression.cs index 34a3c186..88903a1a 100644 --- a/src/Application/GunGames/WeaponProgressions/Definitions/PistolsWeaponProgression.cs +++ b/src/Application/GunGames/WeaponProgressions/Definitions/PistolsWeaponProgression.cs @@ -3,7 +3,7 @@ /// /// Defines a GunGame weapon progression using only pistols. /// -public class PistolsWeaponProgression : WeaponProgressionBase +public class PistolsWeaponProgression : WeaponProgression { public override WeaponProgressionType Type => WeaponProgressionType.Pistols; diff --git a/src/Application/GunGames/WeaponProgressions/Definitions/PowerfulWeaponProgression.cs b/src/Application/GunGames/WeaponProgressions/Definitions/PowerfulWeaponProgression.cs index 53714a20..c75ed2db 100644 --- a/src/Application/GunGames/WeaponProgressions/Definitions/PowerfulWeaponProgression.cs +++ b/src/Application/GunGames/WeaponProgressions/Definitions/PowerfulWeaponProgression.cs @@ -3,7 +3,7 @@ /// /// Defines a GunGame weapon progression featuring the most powerful weapons in GTA. /// -public class PowerfulWeaponProgression : WeaponProgressionBase +public class PowerfulWeaponProgression : WeaponProgression { public override WeaponProgressionType Type => WeaponProgressionType.Powerful; diff --git a/src/Application/GunGames/WeaponProgressions/Definitions/ReverseClassicWeaponProgression.cs b/src/Application/GunGames/WeaponProgressions/Definitions/ReverseClassicWeaponProgression.cs index 5e520288..39e6d62b 100644 --- a/src/Application/GunGames/WeaponProgressions/Definitions/ReverseClassicWeaponProgression.cs +++ b/src/Application/GunGames/WeaponProgressions/Definitions/ReverseClassicWeaponProgression.cs @@ -5,7 +5,7 @@ /// Players begin with the most difficult weapons and finish with the easiest, /// before reaching the final knife level. /// -public class ReverseClassicWeaponProgression : WeaponProgressionBase +public class ReverseClassicWeaponProgression : WeaponProgression { public override WeaponProgressionType Type => WeaponProgressionType.ReverseClassic; diff --git a/src/Application/GunGames/WeaponProgressions/Definitions/RiflesWeaponProgression.cs b/src/Application/GunGames/WeaponProgressions/Definitions/RiflesWeaponProgression.cs index 2312f4ed..fa2f692a 100644 --- a/src/Application/GunGames/WeaponProgressions/Definitions/RiflesWeaponProgression.cs +++ b/src/Application/GunGames/WeaponProgressions/Definitions/RiflesWeaponProgression.cs @@ -3,7 +3,7 @@ /// /// Defines a GunGame weapon progression using only rifles. /// -public class RiflesWeaponProgression : WeaponProgressionBase +public class RiflesWeaponProgression : WeaponProgression { public override WeaponProgressionType Type => WeaponProgressionType.Rifles; diff --git a/src/Application/GunGames/WeaponProgressions/Definitions/ShotgunsWeaponProgression.cs b/src/Application/GunGames/WeaponProgressions/Definitions/ShotgunsWeaponProgression.cs index 94306cd2..f58a7057 100644 --- a/src/Application/GunGames/WeaponProgressions/Definitions/ShotgunsWeaponProgression.cs +++ b/src/Application/GunGames/WeaponProgressions/Definitions/ShotgunsWeaponProgression.cs @@ -3,7 +3,7 @@ /// /// Defines a GunGame weapon progression using only shotguns. /// -public class ShotgunsWeaponProgression : WeaponProgressionBase +public class ShotgunsWeaponProgression : WeaponProgression { public override WeaponProgressionType Type => WeaponProgressionType.Shotguns; diff --git a/src/Application/GunGames/WeaponProgressions/Definitions/SmgsWeaponProgression.cs b/src/Application/GunGames/WeaponProgressions/Definitions/SmgsWeaponProgression.cs index 886b7ff7..0ce824bc 100644 --- a/src/Application/GunGames/WeaponProgressions/Definitions/SmgsWeaponProgression.cs +++ b/src/Application/GunGames/WeaponProgressions/Definitions/SmgsWeaponProgression.cs @@ -3,7 +3,7 @@ /// /// Defines a GunGame weapon progression using only submachine guns. /// -public class SmgsWeaponProgression : WeaponProgressionBase +public class SmgsWeaponProgression : WeaponProgression { public override WeaponProgressionType Type => WeaponProgressionType.SMGs; diff --git a/src/Application/GunGames/WeaponProgressions/WeaponProgression.cs b/src/Application/GunGames/WeaponProgressions/WeaponProgression.cs index f12ae6ee..106bf191 100644 --- a/src/Application/GunGames/WeaponProgressions/WeaponProgression.cs +++ b/src/Application/GunGames/WeaponProgressions/WeaponProgression.cs @@ -1,28 +1,66 @@ namespace CTF.Application.GunGames.WeaponProgressions; /// -/// Represents the weapon progression used by the current GunGame session. +/// Represents a weapon progression consisting of an ordered sequence of weapons. /// -/// -/// Consumers do not need to know which progression implementation is active. -/// The active progression is resolved automatically from the current GunGame session. -/// -public class WeaponProgression( - GunGameSession gunGameSession, - FrozenDictionary progressions) +public abstract class WeaponProgression { - private WeaponProgressionBase Current - => progressions[gunGameSession.WeaponProgressionType]; + private readonly List _weapons = []; - /// - public IWeapon GetWeapon(WeaponLevel level) - => Current.GetWeapon(level); + /// + /// Gets the type of weapon progression. + /// + public abstract WeaponProgressionType Type { get; } + + protected WeaponProgression() + { + Define(_weapons); + if (_weapons.Count == 0) + throw new InvalidOperationException( + "A weapon progression must define at least one weapon."); + } + + /// + /// Defines the weapon sequence for this progression. + /// Weapons must be added in ascending level order, + /// starting from the first weapon level. + /// + /// + /// The collection to populate with weapons in progression order. + /// + protected abstract void Define(List weapons); + + /// + /// Gets the maximum weapon level defined by this progression. + /// + public MaxWeaponLevel MaxLevel + => new(_weapons.Count); - /// + /// + /// Determines whether the specified weapon level is the final level + /// of this progression. + /// + /// + /// The weapon level to evaluate. + /// public bool IsFinalLevel(WeaponLevel level) - => Current.IsFinalLevel(level); - - /// - public MaxWeaponLevel MaxLevel - => Current.MaxLevel; + => level.Value == MaxLevel.Value; + + /// + /// Gets the weapon associated with the specified weapon level. + /// + /// + /// The weapon level. + /// + /// + /// The weapon assigned to the specified level. + /// + public IWeapon GetWeapon(WeaponLevel level) + { + int index = level.Value - 1; + if (index < 0 || index >= _weapons.Count) + throw new InvalidOperationException($"No weapon defined for level {level.Value}"); + + return _weapons[index]; + } } diff --git a/src/Application/GunGames/WeaponProgressions/WeaponProgressionBase.cs b/src/Application/GunGames/WeaponProgressions/WeaponProgressionBase.cs deleted file mode 100644 index 6263a9f4..00000000 --- a/src/Application/GunGames/WeaponProgressions/WeaponProgressionBase.cs +++ /dev/null @@ -1,66 +0,0 @@ -namespace CTF.Application.GunGames.WeaponProgressions; - -/// -/// Represents a weapon progression used by GunGame. -/// -public abstract class WeaponProgressionBase -{ - private readonly List _weapons = []; - - /// - /// Gets the type of weapon progression. - /// - public abstract WeaponProgressionType Type { get; } - - protected WeaponProgressionBase() - { - Define(_weapons); - if (_weapons.Count == 0) - throw new InvalidOperationException( - "A weapon progression must define at least one weapon."); - } - - /// - /// Defines the weapon sequence for this progression. - /// Weapons must be added in ascending level order, - /// starting from the first weapon level. - /// - /// - /// The collection to populate with weapons in progression order. - /// - protected abstract void Define(List weapons); - - /// - /// Gets the maximum weapon level defined by this progression. - /// - public MaxWeaponLevel MaxLevel - => new(_weapons.Count); - - /// - /// Determines whether the specified weapon level is the final level - /// of this progression. - /// - /// - /// The weapon level to evaluate. - /// - public bool IsFinalLevel(WeaponLevel level) - => level.Value == MaxLevel.Value; - - /// - /// Gets the weapon associated with the specified weapon level. - /// - /// - /// The weapon level. - /// - /// - /// The weapon assigned to the specified level. - /// - public IWeapon GetWeapon(WeaponLevel level) - { - int index = level.Value - 1; - if (index < 0 || index >= _weapons.Count) - throw new InvalidOperationException($"No weapon defined for level {level.Value}"); - - return _weapons[index]; - } -} diff --git a/tests/Application.Tests/GunGames/ProcessKillTests.cs b/tests/Application.Tests/GunGames/ProcessKillTests.cs index 8a9b3479..27a64238 100644 --- a/tests/Application.Tests/GunGames/ProcessKillTests.cs +++ b/tests/Application.Tests/GunGames/ProcessKillTests.cs @@ -14,12 +14,12 @@ public void Init() KillsRequiredPerLevel = new KillsRequiredPerLevel(2) }; - var progressions = new Dictionary + var progressions = new Dictionary { [WeaponProgressionType.Classic] = new TestWeaponProgression() }.ToFrozenDictionary(); - var weaponProgression = new WeaponProgression(session, progressions); + var weaponProgression = new ActiveWeaponProgression(session, progressions); _gunGame = new GunGame(weaponProgression, session.KillsRequiredPerLevel); _maxLevel = weaponProgression.MaxLevel; } @@ -170,12 +170,12 @@ public void ProcessKill_WhenPlayerAtFinalLevelKillsWithNonKnifeFinalWeapon_Shoul KillsRequiredPerLevel = new KillsRequiredPerLevel(2) }; - var progressions = new Dictionary + var progressions = new Dictionary { [WeaponProgressionType.Classic] = new NonKnifeFinalWeaponProgression() }.ToFrozenDictionary(); - var weaponProgression = new WeaponProgression(session, progressions); + var weaponProgression = new ActiveWeaponProgression(session, progressions); var gunGame = new GunGame(weaponProgression, session.KillsRequiredPerLevel); var killer = new PlayerProgression(); var victim = new PlayerProgression(); diff --git a/tests/Application.Tests/GunGames/TestWeaponProgression.cs b/tests/Application.Tests/GunGames/TestWeaponProgression.cs index c94f09db..80b7c0cb 100644 --- a/tests/Application.Tests/GunGames/TestWeaponProgression.cs +++ b/tests/Application.Tests/GunGames/TestWeaponProgression.cs @@ -1,6 +1,6 @@ namespace CTF.Application.Tests.GunGames; -public class TestWeaponProgression : WeaponProgressionBase +public class TestWeaponProgression : WeaponProgression { public override WeaponProgressionType Type => WeaponProgressionType.Classic; @@ -16,7 +16,7 @@ protected override void Define(List weapons) } } -public class NonKnifeFinalWeaponProgression : WeaponProgressionBase +public class NonKnifeFinalWeaponProgression : WeaponProgression { public override WeaponProgressionType Type => WeaponProgressionType.Classic; diff --git a/tests/Application.Tests/GunGames/WeaponProgressionBaseTests.cs b/tests/Application.Tests/GunGames/WeaponProgressionTests.cs similarity index 97% rename from tests/Application.Tests/GunGames/WeaponProgressionBaseTests.cs rename to tests/Application.Tests/GunGames/WeaponProgressionTests.cs index 89f16a03..13df3156 100644 --- a/tests/Application.Tests/GunGames/WeaponProgressionBaseTests.cs +++ b/tests/Application.Tests/GunGames/WeaponProgressionTests.cs @@ -1,6 +1,6 @@ namespace CTF.Application.Tests.GunGames; -public class WeaponProgressionBaseTests +public class WeaponProgressionTests { private TestWeaponProgression _progression; @@ -125,7 +125,7 @@ public void IsFinalLevel_WhenWeaponLevelIsBelowMaxLevel_ShouldReturnFalse() isFinalLevel.Should().BeFalse(); } - private class EmptyWeaponProgression : WeaponProgressionBase + private class EmptyWeaponProgression : WeaponProgression { public override WeaponProgressionType Type => WeaponProgressionType.Classic;