From 2e05bd30c43b9af9dc262a55533aba4f8a1d811a Mon Sep 17 00:00:00 2001 From: MrDave1999 Date: Sun, 22 Sep 2024 12:52:15 -0500 Subject: [PATCH] feat: Implement a timer to apply automatic flag return This timer starts when the player drops the flag on the ground. After 120 seconds, the flag will automatically return to its base position. --- src/Application/Common/ServerSettings.cs | 1 + .../Maps/Services/MapRotationService.cs | 7 ++- .../Teams/Flags/Events/OnFlagDropped.cs | 4 +- .../Teams/Flags/Events/OnFlagReturned.cs | 4 +- .../Teams/Flags/Events/OnFlagTaken.cs | 4 +- .../Teams/ServiceCollectionExtensions.cs | 1 + .../Teams/Services/FlagAutoReturnTimer.cs | 56 +++++++++++++++++++ 7 files changed, 73 insertions(+), 4 deletions(-) create mode 100644 src/Application/Teams/Services/FlagAutoReturnTimer.cs diff --git a/src/Application/Common/ServerSettings.cs b/src/Application/Common/ServerSettings.cs index 5d5d54bf..77917850 100644 --- a/src/Application/Common/ServerSettings.cs +++ b/src/Application/Common/ServerSettings.cs @@ -8,4 +8,5 @@ public class ServerSettings public string MapName { get; init; } = string.Empty; public string WebUrl { get; init; } = string.Empty; public string IntroAudioUrl { get; init; } = string.Empty; + public int FlagAutoReturnTime { get; init; } = 120; } diff --git a/src/Application/Maps/Services/MapRotationService.cs b/src/Application/Maps/Services/MapRotationService.cs index f04d53ef..a4b047b1 100644 --- a/src/Application/Maps/Services/MapRotationService.cs +++ b/src/Application/Maps/Services/MapRotationService.cs @@ -11,6 +11,7 @@ public class MapRotationService private readonly TeamPickupService _teamPickupService; private readonly TeamTextDrawRenderer _teamTextDrawRenderer; private readonly PlayerStatsRenderer _playerStatsRenderer; + private readonly FlagAutoReturnTimer _flagAutoReturnTimer; private readonly TimeLeft _timeLeft; private readonly LoadTime _loadTime; private TimerReference _timerReference; @@ -27,7 +28,8 @@ public MapRotationService( TeamIconService teamIconService, TeamPickupService teamPickupService, TeamTextDrawRenderer teamTextDrawRenderer, - PlayerStatsRenderer playerStatsRenderer) + PlayerStatsRenderer playerStatsRenderer, + FlagAutoReturnTimer flagAutoReturnTimer) { _serverService = serverService; _worldService = worldService; @@ -38,6 +40,7 @@ public MapRotationService( _teamPickupService = teamPickupService; _teamTextDrawRenderer = teamTextDrawRenderer; _playerStatsRenderer = playerStatsRenderer; + _flagAutoReturnTimer = flagAutoReturnTimer; _timeLeft = new TimeLeft(); _loadTime = new LoadTime(OnLoadingMap, OnLoadedMap); _isMapLoading = false; @@ -112,6 +115,8 @@ private void OnLoadingMap() _teamIconService.DestroyAll(); _teamIconService.CreateFromBasePosition(Team.Alpha); _teamIconService.CreateFromBasePosition(Team.Beta); + _flagAutoReturnTimer.Stop(Team.Alpha); + _flagAutoReturnTimer.Stop(Team.Beta); _serverService.SendRconCommand($"loadfs {nextMap.Name}"); _serverService.SendRconCommand($"mapname {nextMap.Name}"); } diff --git a/src/Application/Teams/Flags/Events/OnFlagDropped.cs b/src/Application/Teams/Flags/Events/OnFlagDropped.cs index 59584a6f..d2390d37 100644 --- a/src/Application/Teams/Flags/Events/OnFlagDropped.cs +++ b/src/Application/Teams/Flags/Events/OnFlagDropped.cs @@ -7,7 +7,8 @@ public class OnFlagDropped( IPlayerRepository playerRepository, IWorldService worldService, TeamPickupService teamPickupService, - TeamSoundsService teamSoundsService) : IFlagEvent + TeamSoundsService teamSoundsService, + FlagAutoReturnTimer flagAutoReturnTimer) : IFlagEvent { public FlagStatus FlagStatus => FlagStatus.Dropped; @@ -15,6 +16,7 @@ public void Handle(Team team, Player player) { teamPickupService.CreateFlagFromVector3(team, player.Position); teamSoundsService.PlayFlagDroppedSound(team); + flagAutoReturnTimer.Start(team); team.Flag.RemoveCarrier(); var message = Smart.Format(Messages.OnFlagDropped, new { diff --git a/src/Application/Teams/Flags/Events/OnFlagReturned.cs b/src/Application/Teams/Flags/Events/OnFlagReturned.cs index 8b6a4612..6f523ae2 100644 --- a/src/Application/Teams/Flags/Events/OnFlagReturned.cs +++ b/src/Application/Teams/Flags/Events/OnFlagReturned.cs @@ -8,7 +8,8 @@ public class OnFlagReturned( IWorldService worldService, TeamPickupService teamPickupService, TeamSoundsService teamSoundsService, - PlayerStatsRenderer playerStatsRenderer) : IFlagEvent + PlayerStatsRenderer playerStatsRenderer, + FlagAutoReturnTimer flagAutoReturnTimer) : IFlagEvent { public FlagStatus FlagStatus => FlagStatus.Returned; @@ -17,6 +18,7 @@ public void Handle(Team team, Player player) teamPickupService.CreateFlagFromBasePosition(team); teamPickupService.DestroyPickupWithInfo(team); teamSoundsService.PlayFlagReturnedSound(team); + flagAutoReturnTimer.Stop(team); var message = Smart.Format(Messages.OnFlagReturned, new { PlayerName = player.Name, diff --git a/src/Application/Teams/Flags/Events/OnFlagTaken.cs b/src/Application/Teams/Flags/Events/OnFlagTaken.cs index da8090cf..d3125b63 100644 --- a/src/Application/Teams/Flags/Events/OnFlagTaken.cs +++ b/src/Application/Teams/Flags/Events/OnFlagTaken.cs @@ -6,7 +6,8 @@ public class OnFlagTaken( IWorldService worldService, TeamPickupService teamPickupService, - TeamSoundsService teamSoundsService) : IFlagEvent + TeamSoundsService teamSoundsService, + FlagAutoReturnTimer flagAutoReturnTimer) : IFlagEvent { public FlagStatus FlagStatus => FlagStatus.Taken; @@ -14,6 +15,7 @@ public void Handle(Team team, Player player) { teamPickupService.DestroyFlag(team); teamSoundsService.PlayFlagTakenSound(team); + flagAutoReturnTimer.Stop(team); var message = Smart.Format(Messages.OnFlagTaken, new { PlayerName = player.Name, diff --git a/src/Application/Teams/ServiceCollectionExtensions.cs b/src/Application/Teams/ServiceCollectionExtensions.cs index 05e9b727..4e41be80 100644 --- a/src/Application/Teams/ServiceCollectionExtensions.cs +++ b/src/Application/Teams/ServiceCollectionExtensions.cs @@ -9,6 +9,7 @@ public static IServiceCollection AddTeamServices(this IServiceCollection service .AddSingleton() .AddSingleton() .AddSingleton() + .AddSingleton() .AddSingleton() .AddFlagServices(); diff --git a/src/Application/Teams/Services/FlagAutoReturnTimer.cs b/src/Application/Teams/Services/FlagAutoReturnTimer.cs new file mode 100644 index 00000000..898ca2fa --- /dev/null +++ b/src/Application/Teams/Services/FlagAutoReturnTimer.cs @@ -0,0 +1,56 @@ +namespace CTF.Application.Teams.Services; + +public class FlagAutoReturnTimer( + ITimerService timerService, + IWorldService worldService, + TeamPickupService teamPickupService, + TeamSoundsService teamSoundsService, + ServerSettings serverSettings) +{ + private TimerReference _alphaTeamTimer; + private TimerReference _betaTeamTimer; + + public void Start(Team team) + { + void OnComplete(IServiceProvider serviceProvider) + { + teamPickupService.CreateFlagFromBasePosition(team); + teamPickupService.DestroyPickupWithInfo(team); + teamSoundsService.PlayFlagReturnedSound(team); + team.IsFlagAtBasePosition = true; + var message = Smart.Format(Messages.FlagAutoReturn, new + { + Seconds = serverSettings.FlagAutoReturnTime, + team.ColorName + }); + worldService.SendClientMessage(team.ColorHex, message); + worldService.GameText($"~n~~n~~n~{team.GameText}{team.ColorName} flag returned!", 5000, 3); + Stop(team); + } + + if (team.Id == TeamId.Alpha) + { + TimeSpan interval = TimeSpan.FromSeconds(serverSettings.FlagAutoReturnTime); + _alphaTeamTimer ??= timerService.Start(OnComplete, interval); + } + else if (team.Id == TeamId.Beta) + { + TimeSpan interval = TimeSpan.FromSeconds(serverSettings.FlagAutoReturnTime); + _betaTeamTimer ??= timerService.Start(OnComplete, interval); + } + } + + public void Stop(Team team) + { + if (team.Id == TeamId.Alpha && _alphaTeamTimer is not null) + { + timerService.Stop(_alphaTeamTimer); + _alphaTeamTimer = default; + } + else if (team.Id == TeamId.Beta && _betaTeamTimer is not null) + { + timerService.Stop(_betaTeamTimer); + _betaTeamTimer = default; + } + } +}