2020-04-09 00:28:56 +02:00
using System ;
using System.Threading ;
2021-06-09 22:19:39 +02:00
using Content.Server.Chat.Managers ;
using Content.Server.GameTicking ;
2020-11-26 17:07:46 +00:00
using Content.Shared.GameTicking ;
2021-03-01 20:42:54 -08:00
using Robust.Shared.Audio ;
2021-02-11 01:13:03 -08:00
using Robust.Shared.GameObjects ;
2020-04-09 00:28:56 +02:00
using Robust.Shared.IoC ;
2020-09-23 11:53:31 +02:00
using Robust.Shared.Localization ;
2021-03-01 20:42:54 -08:00
using Robust.Shared.Player ;
2021-02-11 01:13:03 -08:00
using Robust.Shared.Timing ;
2021-02-18 20:45:45 -08:00
using Timer = Robust . Shared . Timing . Timer ;
2020-04-09 00:28:56 +02:00
2021-06-09 22:19:39 +02:00
namespace Content.Server.RoundEnd
2020-04-09 00:28:56 +02:00
{
2020-11-26 17:07:46 +00:00
public class RoundEndSystem : EntitySystem , IResettingEntitySystem
2020-04-09 00:28:56 +02:00
{
2020-08-24 14:10:28 +02:00
[Dependency] private readonly IGameTicker _gameTicker = default ! ;
[Dependency] private readonly IGameTiming _gameTiming = default ! ;
2020-09-23 11:53:31 +02:00
[Dependency] private readonly IChatManager _chatManager = default ! ;
public const float RestartRoundTime = 20f ;
2020-04-09 00:28:56 +02:00
2020-11-27 11:00:49 +01:00
private CancellationTokenSource _roundEndCancellationTokenSource = new ( ) ;
2021-02-16 09:31:57 +01:00
private CancellationTokenSource _callCooldownEndedTokenSource = new ( ) ;
2020-04-09 00:28:56 +02:00
public bool IsRoundEndCountdownStarted { get ; private set ; }
2020-04-10 13:37:13 +02:00
public TimeSpan RoundEndCountdownTime { get ; set ; } = TimeSpan . FromMinutes ( 4 ) ;
2020-04-09 20:28:22 +02:00
public TimeSpan ? ExpectedCountdownEnd = null ;
2020-04-09 00:28:56 +02:00
2021-02-16 09:31:57 +01:00
public TimeSpan LastCallTime { get ; private set ; }
public TimeSpan CallCooldown { get ; } = TimeSpan . FromSeconds ( 30 ) ;
2020-04-09 00:28:56 +02:00
public delegate void RoundEndCountdownStarted ( ) ;
2021-03-16 15:50:20 +01:00
public event RoundEndCountdownStarted ? OnRoundEndCountdownStarted ;
2020-04-09 00:28:56 +02:00
public delegate void RoundEndCountdownCancelled ( ) ;
2021-03-16 15:50:20 +01:00
public event RoundEndCountdownCancelled ? OnRoundEndCountdownCancelled ;
2020-04-09 00:28:56 +02:00
public delegate void RoundEndCountdownFinished ( ) ;
2021-03-16 15:50:20 +01:00
public event RoundEndCountdownFinished ? OnRoundEndCountdownFinished ;
2020-04-09 00:28:56 +02:00
2021-02-16 09:31:57 +01:00
public delegate void CallCooldownEnded ( ) ;
2021-03-16 15:50:20 +01:00
public event CallCooldownEnded ? OnCallCooldownEnded ;
2021-02-16 09:31:57 +01:00
2020-11-26 17:07:46 +00:00
void IResettingEntitySystem . Reset ( )
{
IsRoundEndCountdownStarted = false ;
_roundEndCancellationTokenSource . Cancel ( ) ;
_roundEndCancellationTokenSource = new CancellationTokenSource ( ) ;
2021-02-16 09:31:57 +01:00
_callCooldownEndedTokenSource . Cancel ( ) ;
_callCooldownEndedTokenSource = new CancellationTokenSource ( ) ;
2020-11-26 17:07:46 +00:00
ExpectedCountdownEnd = null ;
2021-02-16 09:31:57 +01:00
LastCallTime = default ;
}
public bool CanCall ( )
{
return _gameTiming . CurTime > = LastCallTime + CallCooldown ;
}
private void ActivateCooldown ( )
{
_callCooldownEndedTokenSource . Cancel ( ) ;
_callCooldownEndedTokenSource = new CancellationTokenSource ( ) ;
LastCallTime = _gameTiming . CurTime ;
Timer . Spawn ( CallCooldown , ( ) = > OnCallCooldownEnded ? . Invoke ( ) , _callCooldownEndedTokenSource . Token ) ;
2020-11-26 17:07:46 +00:00
}
2020-04-09 00:28:56 +02:00
public void RequestRoundEnd ( )
{
if ( IsRoundEndCountdownStarted )
return ;
2021-02-16 09:31:57 +01:00
if ( ! CanCall ( ) )
{
return ;
}
2020-04-09 00:28:56 +02:00
IsRoundEndCountdownStarted = true ;
2021-01-01 16:34:54 +01:00
_chatManager . DispatchStationAnnouncement ( Loc . GetString ( "An emergency shuttle has been sent. ETA: {0} minutes." , RoundEndCountdownTime . Minutes ) , Loc . GetString ( "Station" ) ) ;
2021-03-01 20:42:54 -08:00
SoundSystem . Play ( Filter . Broadcast ( ) , "/Audio/Announcements/shuttlecalled.ogg" ) ;
2021-01-01 16:34:54 +01:00
2020-04-10 13:37:13 +02:00
ExpectedCountdownEnd = _gameTiming . CurTime + RoundEndCountdownTime ;
2020-04-09 00:28:56 +02:00
Timer . Spawn ( RoundEndCountdownTime , EndRound , _roundEndCancellationTokenSource . Token ) ;
2021-02-16 09:31:57 +01:00
ActivateCooldown ( ) ;
2020-04-09 00:28:56 +02:00
OnRoundEndCountdownStarted ? . Invoke ( ) ;
}
public void CancelRoundEndCountdown ( )
{
2020-04-09 01:43:28 +02:00
if ( ! IsRoundEndCountdownStarted )
return ;
2021-02-16 09:31:57 +01:00
if ( ! CanCall ( ) )
{
return ;
}
2020-04-09 01:43:28 +02:00
IsRoundEndCountdownStarted = false ;
2021-01-01 16:34:54 +01:00
_chatManager . DispatchStationAnnouncement ( Loc . GetString ( "The emergency shuttle has been recalled." ) , Loc . GetString ( "Station" ) ) ;
2021-03-01 20:42:54 -08:00
SoundSystem . Play ( Filter . Broadcast ( ) , "/Audio/Announcements/shuttlerecalled.ogg" ) ;
2021-01-01 16:34:54 +01:00
2020-04-09 00:28:56 +02:00
_roundEndCancellationTokenSource . Cancel ( ) ;
_roundEndCancellationTokenSource = new CancellationTokenSource ( ) ;
ExpectedCountdownEnd = null ;
2021-02-16 09:31:57 +01:00
ActivateCooldown ( ) ;
2020-04-09 00:28:56 +02:00
OnRoundEndCountdownCancelled ? . Invoke ( ) ;
}
private void EndRound ( )
{
OnRoundEndCountdownFinished ? . Invoke ( ) ;
_gameTicker . EndRound ( ) ;
2020-09-23 11:53:31 +02:00
_chatManager . DispatchServerAnnouncement ( Loc . GetString ( "Restarting the round in {0} seconds..." , RestartRoundTime ) ) ;
Timer . Spawn ( TimeSpan . FromSeconds ( RestartRoundTime ) , ( ) = > _gameTicker . RestartRound ( ) , CancellationToken . None ) ;
2020-04-09 00:28:56 +02:00
}
}
}