diff --git a/Content.Client/GameTicking/ClientGameTicker.cs b/Content.Client/GameTicking/ClientGameTicker.cs index 3b58d1c17b..d618046255 100644 --- a/Content.Client/GameTicking/ClientGameTicker.cs +++ b/Content.Client/GameTicking/ClientGameTicker.cs @@ -26,6 +26,7 @@ namespace Content.Client.GameTicking [ViewVariables] public bool AreWeReady { get; private set; } [ViewVariables] public bool IsGameStarted { get; private set; } + [ViewVariables] public bool DisallowedLateJoin { get; private set; } [ViewVariables] public string ServerInfoBlob { get; private set; } [ViewVariables] public DateTime StartTime { get; private set; } [ViewVariables] public bool Paused { get; private set; } @@ -34,6 +35,7 @@ namespace Content.Client.GameTicking public event Action InfoBlobUpdated; public event Action LobbyStatusUpdated; public event Action LobbyReadyUpdated; + public event Action LobbyLateJoinStatusUpdated; public void Initialize() { @@ -50,11 +52,17 @@ namespace Content.Client.GameTicking { IoCManager.Resolve().RequestWindowAttention(); }); + _netManager.RegisterNetMessage(nameof(MsgTickerLateJoinStatus), LateJoinStatus); Ready = new Dictionary(); _initialized = true; } + private void LateJoinStatus(MsgTickerLateJoinStatus message) + { + DisallowedLateJoin = message.Disallowed; + LobbyLateJoinStatusUpdated?.Invoke(); + } private void JoinLobby(MsgTickerJoinLobby message) diff --git a/Content.Client/Interfaces/IClientGameTicker.cs b/Content.Client/Interfaces/IClientGameTicker.cs index 0bedce3995..e1e584e2f3 100644 --- a/Content.Client/Interfaces/IClientGameTicker.cs +++ b/Content.Client/Interfaces/IClientGameTicker.cs @@ -9,6 +9,7 @@ namespace Content.Client.Interfaces bool IsGameStarted { get; } string ServerInfoBlob { get; } bool AreWeReady { get; } + bool DisallowedLateJoin { get; } DateTime StartTime { get; } bool Paused { get; } Dictionary Ready { get; } @@ -17,5 +18,6 @@ namespace Content.Client.Interfaces event Action InfoBlobUpdated; event Action LobbyStatusUpdated; event Action LobbyReadyUpdated; + event Action LobbyLateJoinStatusUpdated; } } diff --git a/Content.Client/State/LobbyState.cs b/Content.Client/State/LobbyState.cs index b5fc2c35a1..2580dadb64 100644 --- a/Content.Client/State/LobbyState.cs +++ b/Content.Client/State/LobbyState.cs @@ -101,6 +101,7 @@ namespace Content.Client.State _clientGameTicker.InfoBlobUpdated += UpdateLobbyUi; _clientGameTicker.LobbyStatusUpdated += LobbyStatusUpdated; _clientGameTicker.LobbyReadyUpdated += LobbyReadyUpdated; + _clientGameTicker.LobbyLateJoinStatusUpdated += LobbyLateJoinStatusUpdated; } public override void Shutdown() @@ -109,6 +110,7 @@ namespace Content.Client.State _clientGameTicker.InfoBlobUpdated -= UpdateLobbyUi; _clientGameTicker.LobbyStatusUpdated -= LobbyStatusUpdated; _clientGameTicker.LobbyReadyUpdated -= LobbyReadyUpdated; + _clientGameTicker.LobbyLateJoinStatusUpdated -= LobbyLateJoinStatusUpdated; _clientGameTicker.Ready.Clear(); @@ -173,6 +175,11 @@ namespace Content.Client.State UpdateLobbyUi(); } + private void LobbyLateJoinStatusUpdated() + { + _lobby.ReadyButton.Disabled = _clientGameTicker.DisallowedLateJoin; + } + private void UpdateLobbyUi() { if (_lobby == null) @@ -191,6 +198,7 @@ namespace Content.Client.State _lobby.StartTime.Text = ""; _lobby.ReadyButton.Text = Loc.GetString("Ready Up"); _lobby.ReadyButton.ToggleMode = true; + _lobby.ReadyButton.Disabled = false; _lobby.ReadyButton.Pressed = _clientGameTicker.AreWeReady; } diff --git a/Content.Server/GameTicking/GamePreset.cs b/Content.Server/GameTicking/GamePreset.cs index 0e7ce86795..ddde553722 100644 --- a/Content.Server/GameTicking/GamePreset.cs +++ b/Content.Server/GameTicking/GamePreset.cs @@ -12,6 +12,7 @@ namespace Content.Server.GameTicking public abstract bool Start(IReadOnlyList readyPlayers, bool force = false); public virtual string ModeTitle => "Sandbox"; public virtual string Description => "Secret!"; + public virtual bool DisallowLateJoin => false; public Dictionary readyProfiles; } } diff --git a/Content.Server/GameTicking/GamePresets/PresetSuspicion.cs b/Content.Server/GameTicking/GamePresets/PresetSuspicion.cs index 3ce23717d4..c77b8a110e 100644 --- a/Content.Server/GameTicking/GamePresets/PresetSuspicion.cs +++ b/Content.Server/GameTicking/GamePresets/PresetSuspicion.cs @@ -30,6 +30,9 @@ namespace Content.Server.GameTicking.GamePresets public int MinPlayers { get; set; } = 5; public int MinTraitors { get; set; } = 2; public int PlayersPerTraitor { get; set; } = 5; + + public override bool DisallowLateJoin => true; + private static string TraitorID = "SuspicionTraitor"; private static string InnocentID = "SuspicionInnocent"; diff --git a/Content.Server/GameTicking/GameTicker.cs b/Content.Server/GameTicking/GameTicker.cs index 476a7c55f8..34d40c8df3 100644 --- a/Content.Server/GameTicking/GameTicker.cs +++ b/Content.Server/GameTicking/GameTicker.cs @@ -94,6 +94,8 @@ namespace Content.Server.GameTicking [ViewVariables] private GameRunLevel _runLevel; [ViewVariables(VVAccess.ReadWrite)] private GridCoordinates _spawnPoint; + [ViewVariables] private bool DisallowLateJoin { get; set; } = false; + [ViewVariables] private bool LobbyEnabled => _configurationManager.GetCVar("game.lobbyenabled"); [ViewVariables] private bool _updateOnRoundEnd; @@ -142,6 +144,7 @@ namespace Content.Server.GameTicking _netManager.RegisterNetMessage(nameof(MsgTickerLobbyReady)); _netManager.RegisterNetMessage(nameof(MsgRoundEndMessage)); _netManager.RegisterNetMessage(nameof(MsgRequestWindowAttention)); + _netManager.RegisterNetMessage(nameof(MsgTickerLateJoinStatus)); SetStartPreset(_configurationManager.GetCVar("game.defaultpreset")); @@ -285,6 +288,8 @@ namespace Content.Server.GameTicking // Time to start the preset. var preset = MakeGamePreset(profiles); + DisallowLateJoin |= preset.DisallowLateJoin; + if (!preset.Start(assignedJobs.Keys.ToList(), force)) { SetStartPreset(_configurationManager.GetCVar("game.fallbackpreset")); @@ -300,6 +305,13 @@ namespace Content.Server.GameTicking _roundStartTimeSpan = IoCManager.Resolve().RealTime; _sendStatusToAll(); ReqWindowAttentionAll(); + UpdateLateJoinStatus(); + } + + private void UpdateLateJoinStatus() + { + var msg = new MsgTickerLateJoinStatus(null) {Disallowed = DisallowLateJoin}; + _netManager.ServerSendToAll(msg); } private void SendServerMessage(string message) @@ -405,7 +417,7 @@ namespace Content.Server.GameTicking foreach (var rule in _gameRules) { - if (rule.GetType().Equals(t)) + if (rule.GetType().IsAssignableFrom(t)) return true; } @@ -637,7 +649,7 @@ namespace Content.Server.GameTicking _playerJoinLobby(player); } - + EntitySystem.Get().ResettingCleanup(); EntitySystem.Get().ResettingCleanup(); EntitySystem.Get().ResettingCleanup(); @@ -646,6 +658,7 @@ namespace Content.Server.GameTicking _spawnedPositions.Clear(); _manifest.Clear(); + DisallowLateJoin = false; } private void _preRoundSetup() @@ -776,6 +789,12 @@ namespace Content.Server.GameTicking string jobId = null, bool lateJoin = true) { + if (lateJoin && DisallowLateJoin) + { + MakeObserve(session); + return; + } + _playerJoinGame(session); var data = session.ContentData(); diff --git a/Content.Shared/SharedGameTicker.cs b/Content.Shared/SharedGameTicker.cs index d7100f93e4..e180ddb198 100644 --- a/Content.Shared/SharedGameTicker.cs +++ b/Content.Shared/SharedGameTicker.cs @@ -54,6 +54,31 @@ namespace Content.Shared } } + protected class MsgTickerLateJoinStatus : NetMessage + { + #region REQUIRED + + public const MsgGroups GROUP = MsgGroups.Command; + public const string NAME = nameof(MsgTickerLateJoinStatus); + + public bool Disallowed { get; set; } + + public MsgTickerLateJoinStatus(INetChannel channel) : base(NAME, GROUP) { } + + #endregion + + public override void ReadFromBuffer(NetIncomingMessage buffer) + { + Disallowed = buffer.ReadBoolean(); + } + + public override void WriteToBuffer(NetOutgoingMessage buffer) + { + buffer.Write(Disallowed); + } + } + + protected class MsgTickerLobbyStatus : NetMessage { #region REQUIRED