diff --git a/Content.IntegrationTests/DummyGameTicker.cs b/Content.IntegrationTests/DummyGameTicker.cs index afe44ed8ff..5259c3de5c 100644 --- a/Content.IntegrationTests/DummyGameTicker.cs +++ b/Content.IntegrationTests/DummyGameTicker.cs @@ -2,14 +2,13 @@ using System; using System.Collections.Generic; using Content.Server.GameTicking; using Content.Server.Interfaces.GameTicking; -using Content.Shared; using Robust.Server.Interfaces.Player; using Robust.Shared.Map; using Robust.Shared.Timing; namespace Content.IntegrationTests { - public class DummyGameTicker : SharedGameTicker, IGameTicker + public class DummyGameTicker : GameTickerBase, IGameTicker { public GameRunLevel RunLevel { get; } = GameRunLevel.InRound; @@ -25,10 +24,6 @@ namespace Content.IntegrationTests remove { } } - public void Initialize() - { - } - public void Update(FrameEventArgs frameEventArgs) { } diff --git a/Content.Server/GameTicking/GameTicker.cs b/Content.Server/GameTicking/GameTicker.cs index 785ec372a0..78f17b8e78 100644 --- a/Content.Server/GameTicking/GameTicker.cs +++ b/Content.Server/GameTicking/GameTicker.cs @@ -60,7 +60,7 @@ using Timer = Robust.Shared.Timers.Timer; namespace Content.Server.GameTicking { - public partial class GameTicker : SharedGameTicker, IGameTicker + public partial class GameTicker : GameTickerBase, IGameTicker { private static readonly Counter RoundNumberMetric = Metrics.CreateCounter( "ss14_round_number", @@ -124,8 +124,10 @@ namespace Content.Server.GameTicking private TimeSpan LobbyDuration => TimeSpan.FromSeconds(_configurationManager.GetCVar("game.lobbyduration")); - public void Initialize() + public override void Initialize() { + base.Initialize(); + DebugTools.Assert(!_initialized); _configurationManager.RegisterCVar("game.lobbyenabled", false, CVar.ARCHIVE); @@ -135,8 +137,6 @@ namespace Content.Server.GameTicking PresetSuspicion.RegisterCVars(_configurationManager); - _playerManager.PlayerStatusChanged += _handlePlayerStatusChanged; - _netManager.RegisterNetMessage(nameof(MsgTickerJoinLobby)); _netManager.RegisterNetMessage(nameof(MsgTickerJoinGame)); _netManager.RegisterNetMessage(nameof(MsgTickerLobbyStatus)); @@ -209,7 +209,7 @@ namespace Content.Server.GameTicking } else { - if (_playerManager.PlayerCount == 0) + if (PlayerManager.PlayerCount == 0) _roundStartCountdownHasNotStartedYetDueToNoPlayers = true; else _roundStartTimeUtc = DateTime.UtcNow + LobbyDuration; @@ -222,7 +222,7 @@ namespace Content.Server.GameTicking private void ReqWindowAttentionAll() { - foreach (var player in _playerManager.GetAllPlayers()) + foreach (var player in PlayerManager.GetAllPlayers()) { player.RequestWindowAttention(); } @@ -347,7 +347,7 @@ namespace Content.Server.GameTicking //Generate a list of basic player info to display in the end round summary. var listOfPlayerInfo = new List(); - foreach (var ply in _playerManager.GetAllPlayers().OrderBy(p => p.Name)) + foreach (var ply in PlayerManager.GetAllPlayers().OrderBy(p => p.Name)) { var mind = ply.ContentData().Mind; if (mind != null) @@ -643,7 +643,7 @@ namespace Content.Server.GameTicking // Delete the minds of everybody. // TODO: Maybe move this into a separate manager? - foreach (var unCastData in _playerManager.GetAllPlayerData()) unCastData.ContentData().WipeMind(); + foreach (var unCastData in PlayerManager.GetAllPlayerData()) unCastData.ContentData().WipeMind(); // Clear up any game rules. foreach (var rule in _gameRules) rule.Removed(); @@ -651,7 +651,7 @@ namespace Content.Server.GameTicking _gameRules.Clear(); // Move everybody currently in the server to lobby. - foreach (var player in _playerManager.GetAllPlayers()) + foreach (var player in PlayerManager.GetAllPlayers()) { if (_playersInLobby.ContainsKey(player)) continue; @@ -681,8 +681,10 @@ namespace Content.Server.GameTicking Logger.InfoS("ticker", $"Loaded map in {timeSpan.TotalMilliseconds:N2}ms."); } - private void _handlePlayerStatusChanged(object sender, SessionStatusEventArgs args) + protected override void PlayerStatusChanged(object sender, SessionStatusEventArgs args) { + base.PlayerStatusChanged(sender, args); + var session = args.Session; switch (args.NewStatus) @@ -694,13 +696,6 @@ namespace Content.Server.GameTicking case SessionStatus.Connected: { - // Always make sure the client has player data. Mind gets assigned on spawn. - if (session.Data.ContentDataUncast == null) - session.Data.ContentDataUncast = new PlayerData(session.SessionId); - - // timer time must be > tick length - Timer.Spawn(0, args.Session.JoinGame); - _chatManager.DispatchServerAnnouncement($"Player {args.Session.SessionId} joined server!"); if (LobbyEnabled && _roundStartCountdownHasNotStartedYetDueToNoPlayers) @@ -761,7 +756,7 @@ namespace Content.Server.GameTicking // Can't simple check the current connected player count since that doesn't update // before PlayerStatusChanged gets fired. // So in the disconnect handler we'd still see a single player otherwise. - var playersOnline = _playerManager.GetAllPlayers().Any(p => p.Status != SessionStatus.Disconnected); + var playersOnline = PlayerManager.GetAllPlayers().Any(p => p.Status != SessionStatus.Disconnected); if (playersOnline || !_updateOnRoundEnd) { // Still somebody online. @@ -989,7 +984,6 @@ The current game mode is: [color=white]{0}[/color]. [Dependency] private IMapLoader _mapLoader; [Dependency] private IGameTiming _gameTiming; [Dependency] private IConfigurationManager _configurationManager; - [Dependency] private IPlayerManager _playerManager; [Dependency] private IChatManager _chatManager; [Dependency] private IServerNetManager _netManager; [Dependency] private IDynamicTypeFactory _dynamicTypeFactory; diff --git a/Content.Server/GameTicking/GameTickerBase.cs b/Content.Server/GameTicking/GameTickerBase.cs new file mode 100644 index 0000000000..2fc8e350df --- /dev/null +++ b/Content.Server/GameTicking/GameTickerBase.cs @@ -0,0 +1,41 @@ +using Content.Server.Players; +using Content.Shared; +using Robust.Server.Interfaces.Player; +using Robust.Server.Player; +using Robust.Shared.Enums; +using Robust.Shared.IoC; +using Robust.Shared.Timers; + +#nullable enable + +namespace Content.Server.GameTicking +{ + /// + /// Handles some low-level GameTicker behavior such as setting up clients when they connect. + /// Does not contain lobby/round handling mechanisms. + /// + public abstract class GameTickerBase : SharedGameTicker + { + [Dependency] protected readonly IPlayerManager PlayerManager = default!; + + public virtual void Initialize() + { + PlayerManager.PlayerStatusChanged += PlayerStatusChanged; + } + + protected virtual void PlayerStatusChanged(object sender, SessionStatusEventArgs args) + { + var session = args.Session; + + if (args.NewStatus == SessionStatus.Connected) + { + // Always make sure the client has player data. Mind gets assigned on spawn. + if (session.Data.ContentDataUncast == null) + session.Data.ContentDataUncast = new PlayerData(session.SessionId); + + // timer time must be > tick length + Timer.Spawn(0, args.Session.JoinGame); + } + } + } +}