using System; using System.Collections.Generic; using Content.Client.Lobby; using Content.Client.RoundEnd; using Content.Client.Viewport; using Content.Shared.GameTicking; using Content.Shared.GameWindow; using Robust.Client.Graphics; using Robust.Client.State; using Robust.Shared.IoC; using Robust.Shared.Network; using Robust.Shared.Utility; using Robust.Shared.ViewVariables; namespace Content.Client.GameTicking.Managers { public class ClientGameTicker : SharedGameTicker, IClientGameTicker { [Dependency] private readonly IClientNetManager _netManager = default!; [Dependency] private readonly IStateManager _stateManager = default!; [ViewVariables] private bool _initialized; private readonly List _jobsAvailable = new(); [ViewVariables] public bool AreWeReady { get; private set; } [ViewVariables] public bool IsGameStarted { get; private set; } [ViewVariables] public string? LobbySong { get; private set; } [ViewVariables] public bool DisallowedLateJoin { get; private set; } [ViewVariables] public string? ServerInfoBlob { get; private set; } [ViewVariables] public TimeSpan StartTime { get; private set; } [ViewVariables] public bool Paused { get; private set; } [ViewVariables] public Dictionary Status { get; private set; } = new(); [ViewVariables] public IReadOnlyList JobsAvailable => _jobsAvailable; public event Action? InfoBlobUpdated; public event Action? LobbyStatusUpdated; public event Action? LobbyReadyUpdated; public event Action? LobbyLateJoinStatusUpdated; public event Action>? LobbyJobsAvailableUpdated; public void Initialize() { DebugTools.Assert(!_initialized); _netManager.RegisterNetMessage(nameof(MsgTickerJoinLobby), JoinLobby); _netManager.RegisterNetMessage(nameof(MsgTickerJoinGame), JoinGame); _netManager.RegisterNetMessage(nameof(MsgTickerLobbyStatus), LobbyStatus); _netManager.RegisterNetMessage(nameof(MsgTickerLobbyInfo), LobbyInfo); _netManager.RegisterNetMessage(nameof(MsgTickerLobbyCountdown), LobbyCountdown); _netManager.RegisterNetMessage(nameof(MsgTickerLobbyReady), LobbyReady); _netManager.RegisterNetMessage(nameof(MsgRoundEndMessage), RoundEnd); _netManager.RegisterNetMessage(nameof(MsgRequestWindowAttention), msg => { IoCManager.Resolve().RequestWindowAttention(); }); _netManager.RegisterNetMessage(nameof(MsgTickerLateJoinStatus), LateJoinStatus); _netManager.RegisterNetMessage(nameof(MsgTickerJobsAvailable), UpdateJobsAvailable); Status = new Dictionary(); _initialized = true; } private void LateJoinStatus(MsgTickerLateJoinStatus message) { DisallowedLateJoin = message.Disallowed; LobbyLateJoinStatusUpdated?.Invoke(); } private void UpdateJobsAvailable(MsgTickerJobsAvailable message) { _jobsAvailable.Clear(); _jobsAvailable.AddRange(message.JobsAvailable); LobbyJobsAvailableUpdated?.Invoke(JobsAvailable); } private void JoinLobby(MsgTickerJoinLobby message) { _stateManager.RequestStateChange(); } private void LobbyStatus(MsgTickerLobbyStatus message) { StartTime = message.StartTime; IsGameStarted = message.IsRoundStarted; AreWeReady = message.YouAreReady; LobbySong = message.LobbySong; Paused = message.Paused; if (IsGameStarted) Status.Clear(); LobbyStatusUpdated?.Invoke(); } private void LobbyInfo(MsgTickerLobbyInfo message) { ServerInfoBlob = message.TextBlob; InfoBlobUpdated?.Invoke(); } private void JoinGame(MsgTickerJoinGame message) { _stateManager.RequestStateChange(); } private void LobbyCountdown(MsgTickerLobbyCountdown message) { StartTime = message.StartTime; Paused = message.Paused; } private void LobbyReady(MsgTickerLobbyReady message) { // Merge the Dictionaries foreach (var p in message.PlayerStatus) { Status[p.Key] = p.Value; } LobbyReadyUpdated?.Invoke(); } private void RoundEnd(MsgRoundEndMessage message) { //This is not ideal at all, but I don't see an immediately better fit anywhere else. var roundEnd = new RoundEndSummaryWindow(message.GamemodeTitle, message.RoundEndText, message.RoundDuration, message.AllPlayersEndInfo); } } }